From ea42b823d8563c2c0638eaedce3694c3b3ac57db Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 30 Apr 2025 22:47:41 +1200 Subject: [PATCH 001/219] Revert name merge issue --- src/Appwrite/Messaging/Adapter/Realtime.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Messaging/Adapter/Realtime.php b/src/Appwrite/Messaging/Adapter/Realtime.php index 18b0d94e7d..be263aa655 100644 --- a/src/Appwrite/Messaging/Adapter/Realtime.php +++ b/src/Appwrite/Messaging/Adapter/Realtime.php @@ -36,12 +36,12 @@ class Realtime extends MessagingAdapter */ public array $subscriptions = []; - private PubSubPool $redis; + private PubSubPool $pubSubPool; public function __construct() { global $register; - $this->redis = new PubSubPool($register->get('pools')->get('pubsub')); + $this->pubSubPool = new PubSubPool($register->get('pools')->get('pubsub')); } /** @@ -148,7 +148,7 @@ class Realtime extends MessagingAdapter $permissionsChanged = array_key_exists('permissionsChanged', $options) && $options['permissionsChanged']; $userId = array_key_exists('userId', $options) ? $options['userId'] : null; - $this->redis->publish('realtime', json_encode([ + $this->pubSubPool->publish('realtime', json_encode([ 'project' => $projectId, 'roles' => $roles, 'permissionsChanged' => $permissionsChanged, From 7750ada4d8c541557d89d1fbf5b6412a222f8124 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Thu, 1 May 2025 18:55:04 +0530 Subject: [PATCH 002/219] * exposed internal id as a part of auto increment id * updated test cases regarding internal id --- .../Utopia/Response/Model/Document.php | 7 ++- .../e2e/Services/Databases/DatabasesBase.php | 49 ++++++++++++++++--- 2 files changed, 49 insertions(+), 7 deletions(-) diff --git a/src/Appwrite/Utopia/Response/Model/Document.php b/src/Appwrite/Utopia/Response/Model/Document.php index 41a10cee89..6c4e92b983 100644 --- a/src/Appwrite/Utopia/Response/Model/Document.php +++ b/src/Appwrite/Utopia/Response/Model/Document.php @@ -36,6 +36,12 @@ class Document extends Any 'default' => '', 'example' => '5e5ea5c16897e', ]) + ->addRule('$internalId', [ + 'type' => self::TYPE_INTEGER, + 'description' => 'Auto increment integer.', + 'default' => '', + 'example' => '1', + ]) ->addRule('$collectionId', [ 'type' => self::TYPE_STRING, 'description' => 'Collection ID.', @@ -71,7 +77,6 @@ class Document extends Any public function filter(DatabaseDocument $document): DatabaseDocument { - $document->removeAttribute('$internalId'); $document->removeAttribute('$collection'); $document->removeAttribute('$tenant'); diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 0c7e1d386e..f97e88e537 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -1553,6 +1553,7 @@ trait DatabasesBase $this->assertEquals($document1['body']['actors'][0], 'Chris Evans'); $this->assertEquals($document1['body']['actors'][1], 'Samuel Jackson'); $this->assertEquals($document1['body']['birthDay'], '1975-06-12T12:12:55.000+00:00'); + $this->assertTrue(array_key_exists('$internalId', $document1['body'])); $this->assertEquals(201, $document2['headers']['status-code']); $this->assertEquals($data['moviesId'], $document2['body']['$collectionId']); @@ -1570,6 +1571,7 @@ trait DatabasesBase $this->assertEquals($document2['body']['birthDay'], null); $this->assertEquals($document2['body']['integers'][0], 50); $this->assertEquals($document2['body']['integers'][1], 60); + $this->assertTrue(array_key_exists('$internalId', $document2['body'])); $this->assertEquals(201, $document3['headers']['status-code']); $this->assertEquals($data['moviesId'], $document3['body']['$collectionId']); @@ -1584,6 +1586,7 @@ trait DatabasesBase $this->assertEquals($document3['body']['actors'][0], 'Tom Holland'); $this->assertEquals($document3['body']['actors'][1], 'Zendaya Maree Stoermer'); $this->assertEquals($document3['body']['birthDay'], '1975-06-12T18:12:55.000+00:00'); // UTC for NY + $this->assertTrue(array_key_exists('$internalId', $document3['body'])); $this->assertEquals(400, $document4['headers']['status-code']); @@ -1615,9 +1618,9 @@ trait DatabasesBase $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); $this->assertEquals(2017, $documents['body']['documents'][1]['releaseYear']); $this->assertEquals(2019, $documents['body']['documents'][2]['releaseYear']); - $this->assertFalse(array_key_exists('$internalId', $documents['body']['documents'][0])); - $this->assertFalse(array_key_exists('$internalId', $documents['body']['documents'][1])); - $this->assertFalse(array_key_exists('$internalId', $documents['body']['documents'][2])); + $this->assertTrue(array_key_exists('$internalId', $documents['body']['documents'][0])); + $this->assertTrue(array_key_exists('$internalId', $documents['body']['documents'][1])); + $this->assertTrue(array_key_exists('$internalId', $documents['body']['documents'][2])); $this->assertCount(3, $documents['body']['documents']); foreach ($documents['body']['documents'] as $document) { @@ -1710,7 +1713,7 @@ trait DatabasesBase $this->assertEquals($response['body']['releaseYear'], $document['releaseYear']); $this->assertEquals($response['body']['$permissions'], $document['$permissions']); $this->assertEquals($response['body']['birthDay'], $document['birthDay']); - $this->assertFalse(array_key_exists('$internalId', $response['body'])); + $this->assertTrue(array_key_exists('$internalId', $response['body'])); $this->assertFalse(array_key_exists('$tenant', $response['body'])); } } @@ -1723,6 +1726,7 @@ trait DatabasesBase $databaseId = $data['databaseId']; $document = $data['documents'][0]; + // not selecting internal id $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$collectionId'] . '/documents/' . $document['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -1736,6 +1740,39 @@ trait DatabasesBase $this->assertEquals($document['title'], $response['body']['title']); $this->assertEquals($document['releaseYear'], $response['body']['releaseYear']); $this->assertArrayNotHasKey('birthDay', $response['body']); + $this->assertFalse(array_key_exists('$internalId', $response['body'])); + + // selecting internal id as well + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$collectionId'] . '/documents/' . $document['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::select(['title', 'releaseYear', '$id','$internalId'])->toString(), + ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals($document['title'], $response['body']['title']); + $this->assertEquals($document['releaseYear'], $response['body']['releaseYear']); + $this->assertArrayNotHasKey('birthDay', $response['body']); + $this->assertTrue(array_key_exists('$internalId', $response['body'])); + $internalId = $response['body']['$internalId']; + + // Query by internalId + $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$collectionId'] . '/documents/' . $document['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::equal('$internalId', [$internalId]) + ], + ]); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals($document['title'], $response['body']['title']); + $this->assertEquals($document['releaseYear'], $response['body']['releaseYear']); + $this->assertTrue(array_key_exists('$internalId', $response['body'])); } /** @@ -4005,8 +4042,8 @@ trait DatabasesBase $this->assertArrayNotHasKey('$collection', $person1['body']); $this->assertArrayNotHasKey('$collection', $person1['body']['library']); - $this->assertArrayNotHasKey('$internalId', $person1['body']); - $this->assertArrayNotHasKey('$internalId', $person1['body']['library']); + $this->assertArrayHasKey('$internalId', $person1['body']); + $this->assertArrayHasKey('$internalId', $person1['body']['library']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ 'content-type' => 'application/json', From 406630cb61eaa54b314e183a99f44c932199847a Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 14 May 2025 16:40:47 +1200 Subject: [PATCH 003/219] Update deps --- composer.lock | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/composer.lock b/composer.lock index cf15b7657e..5a3d58a047 100644 --- a/composer.lock +++ b/composer.lock @@ -1109,16 +1109,16 @@ }, { "name": "open-telemetry/api", - "version": "1.2.3", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/api.git", - "reference": "199d7ddda88f5f5619fa73463f1a5a7149ccd1f1" + "reference": "4e3bb38e069876fb73c2ce85c89583bf2b28cd86" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/199d7ddda88f5f5619fa73463f1a5a7149ccd1f1", - "reference": "199d7ddda88f5f5619fa73463f1a5a7149ccd1f1", + "url": "https://api.github.com/repos/opentelemetry-php/api/zipball/4e3bb38e069876fb73c2ce85c89583bf2b28cd86", + "reference": "4e3bb38e069876fb73c2ce85c89583bf2b28cd86", "shasum": "" }, "require": { @@ -1175,7 +1175,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-03-05T21:42:54+00:00" + "time": "2025-05-07T12:32:21+00:00" }, { "name": "open-telemetry/context", @@ -1238,16 +1238,16 @@ }, { "name": "open-telemetry/exporter-otlp", - "version": "1.2.1", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/exporter-otlp.git", - "reference": "b7580440b7481a98da97aceabeb46e1b276c8747" + "reference": "19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/b7580440b7481a98da97aceabeb46e1b276c8747", - "reference": "b7580440b7481a98da97aceabeb46e1b276c8747", + "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c", + "reference": "19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c", "shasum": "" }, "require": { @@ -1298,7 +1298,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-03-06T23:21:56+00:00" + "time": "2025-05-12T00:36:35+00:00" }, { "name": "open-telemetry/gen-otlp-protobuf", @@ -1365,16 +1365,16 @@ }, { "name": "open-telemetry/sdk", - "version": "1.3.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/sdk.git", - "reference": "05d9ceb6773b5bddcf485af6d4a6f543bbeb980b" + "reference": "939d3a28395c249a763676458140dad44b3a8011" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/05d9ceb6773b5bddcf485af6d4a6f543bbeb980b", - "reference": "05d9ceb6773b5bddcf485af6d4a6f543bbeb980b", + "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/939d3a28395c249a763676458140dad44b3a8011", + "reference": "939d3a28395c249a763676458140dad44b3a8011", "shasum": "" }, "require": { @@ -1451,7 +1451,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-01T23:20:43+00:00" + "time": "2025-05-07T12:32:21+00:00" }, { "name": "open-telemetry/sem-conv", From 3e914a4f1b698485176bbcd171acbc8de9a0ed64 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 30 Apr 2025 22:47:41 +1200 Subject: [PATCH 004/219] Revert name merge issue --- src/Appwrite/Messaging/Adapter/Realtime.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Messaging/Adapter/Realtime.php b/src/Appwrite/Messaging/Adapter/Realtime.php index 1963bdedd6..96793b2683 100644 --- a/src/Appwrite/Messaging/Adapter/Realtime.php +++ b/src/Appwrite/Messaging/Adapter/Realtime.php @@ -36,12 +36,12 @@ class Realtime extends Adapter */ public array $subscriptions = []; - private Pool $pubsubPool; + private PubSubPool $pubSubPool; public function __construct() { global $register; - $this->pubsubPool = $register->get('pools')->get('pubsub'); + $this->pubSubPool = new PubSubPool($register->get('pools')->get('pubsub')); } /** @@ -147,7 +147,7 @@ class Realtime extends Adapter $permissionsChanged = array_key_exists('permissionsChanged', $options) && $options['permissionsChanged']; $userId = array_key_exists('userId', $options) ? $options['userId'] : null; - $message = [ + $this->pubSubPool->publish('realtime', json_encode([ 'project' => $projectId, 'roles' => $roles, 'permissionsChanged' => $permissionsChanged, From 16b2449787954c2211f431323137d252356c3f3e Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 14 May 2025 18:14:07 +1200 Subject: [PATCH 005/219] Revert "Merge pull request #9703 from appwrite/revert-9659-feat-pool-adapter" This reverts commit bf9deb09f588b59399b7207fc93311f3ec2b8fe3, reversing changes made to d312fe22ff264558e240565cac4fcb2f6a24a401. # Conflicts: # app/cli.php # app/init/registers.php # composer.lock # src/Appwrite/Messaging/Adapter/Realtime.php # src/Appwrite/Platform/Tasks/ScheduleBase.php # src/Appwrite/Platform/Tasks/ScheduleExecutions.php # src/Appwrite/Platform/Tasks/ScheduleFunctions.php # src/Appwrite/Platform/Tasks/ScheduleMessages.php --- app/cli.php | 42 ++---- app/controllers/api/health.php | 137 +++++++++--------- app/controllers/api/projects.php | 3 +- app/http.php | 19 +-- app/init/registers.php | 4 +- app/init/resources.php | 52 +++---- app/realtime.php | 110 ++++++++------ app/worker.php | 69 +++------ composer.json | 2 +- composer.lock | 31 ++-- src/Appwrite/Event/Event.php | 7 - src/Appwrite/Messaging/Adapter/Realtime.php | 25 ++-- src/Appwrite/Platform/Tasks/Doctor.php | 50 ++++--- src/Appwrite/Platform/Tasks/ScheduleBase.php | 6 +- .../Platform/Tasks/ScheduleExecutions.php | 12 +- .../Platform/Tasks/ScheduleFunctions.php | 13 +- .../Platform/Tasks/ScheduleMessages.php | 7 +- src/Appwrite/Platform/Workers/Deletes.php | 5 +- src/Appwrite/Platform/Workers/StatsUsage.php | 12 +- .../Platform/Workers/StatsUsageDump.php | 15 +- src/Appwrite/PubSub/Adapter/Pool.php | 46 ++++++ tests/resources/docker/docker-compose.yml | 32 +--- 22 files changed, 317 insertions(+), 382 deletions(-) create mode 100644 src/Appwrite/PubSub/Adapter/Pool.php diff --git a/app/cli.php b/app/cli.php index 9ade97e90c..61d8a90100 100644 --- a/app/cli.php +++ b/app/cli.php @@ -10,12 +10,13 @@ use Appwrite\Event\StatsUsage; use Appwrite\Platform\Appwrite; use Appwrite\Runtimes\Runtimes; use Executor\Executor; -use Swoole\Timer; +use Utopia\Cache\Adapter\Pool as CachePool; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; use Utopia\CLI\CLI; use Utopia\CLI\Console; use Utopia\Config\Config; +use Utopia\Database\Adapter\Pool as DatabasePool; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Validator\Authorization; @@ -23,11 +24,12 @@ use Utopia\DSN\DSN; use Utopia\Logger\Log; use Utopia\Platform\Service; use Utopia\Pools\Group; +use Utopia\Queue\Broker\Pool as BrokerPool; use Utopia\Queue\Publisher; use Utopia\Registry\Registry; use Utopia\System\System; use Utopia\Telemetry\Adapter\None as NoTelemetry; - +use Swoole\Timer; use function Swoole\Coroutine\run; // Overwriting runtimes to be architecture agnostic for CLI @@ -45,10 +47,7 @@ CLI::setResource('cache', function ($pools) { $adapters = []; foreach ($list as $value) { - $adapters[] = $pools - ->get($value) - ->pop() - ->getResource(); + $adapters[] = new CachePool($pools->get($value)); } return new Cache(new Sharding($adapters)); @@ -68,12 +67,8 @@ CLI::setResource('dbForPlatform', function ($pools, $cache) { $attempts++; try { // Prepare database connection - $dbAdapter = $pools - ->get('console') - ->pop() - ->getResource(); - - $dbForPlatform = new Database($dbAdapter, $cache); + $adapter = new DatabasePool($pools->get('console')); + $dbForPlatform = new Database($adapter, $cache); $dbForPlatform ->setNamespace('_console') @@ -91,7 +86,6 @@ CLI::setResource('dbForPlatform', function ($pools, $cache) { $ready = true; } catch (\Throwable $err) { Console::warning($err->getMessage()); - $pools->get('console')->reclaim(); sleep($sleep); } } while ($attempts < $maxAttempts && !$ready); @@ -141,12 +135,8 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform return $database; } - $dbAdapter = $pools - ->get($dsn->getHost()) - ->pop() - ->getResource(); - - $database = new Database($dbAdapter, $cache); + $adapter = new DatabasePool($pools->get($dsn->getHost())); + $database = new Database($adapter, $cache); $databases[$dsn->getHost()] = $database; $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); @@ -172,21 +162,15 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = null; + return function (?Document $project = null) use ($pools, $cache, $database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { $database->setTenant($project->getInternalId()); return $database; } - $dbAdapter = $pools - ->get('logs') - ->pop() - ->getResource(); - - $database = new Database( - $dbAdapter, - $cache - ); + $adapter = new DatabasePool($pools->get('logs')); + $database = new Database($adapter, $cache); $database ->setSharedTables(true) @@ -210,7 +194,7 @@ CLI::setResource('queueForStatsResources', function (Publisher $publisher) { return new StatsResources($publisher); }, ['publisher']); CLI::setResource('publisher', function (Group $pools) { - return $pools->get('publisher')->pop()->getResource(); + return new BrokerPool(publisher: $pools->get('publisher')); }, ['pools']); CLI::setResource('queueForFunctions', function (Publisher $publisher) { return new Func($publisher); diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index 3602ab8ff9..5fe2de5549 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -3,13 +3,16 @@ use Appwrite\ClamAV\Network; use Appwrite\Event\Event; use Appwrite\Extend\Exception; +use Appwrite\PubSub\Adapter\Pool as PubSubPool; use Appwrite\SDK\AuthType; use Appwrite\SDK\ContentType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\App; +use Utopia\Cache\Adapter\Pool as CachePool; use Utopia\Config\Config; +use Utopia\Database\Adapter\Pool as DatabasePool; use Utopia\Database\Document; use Utopia\Domains\Validator\PublicDomain; use Utopia\Pools\Group; @@ -34,8 +37,8 @@ App::get('/v1/health') namespace: 'health', group: 'health', name: 'get', - auth: [AuthType::KEY], description: '/docs/references/health/get.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -70,11 +73,11 @@ App::get('/v1/health/db') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'health', name: 'getDB', description: '/docs/references/health/get-db.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -86,8 +89,8 @@ App::get('/v1/health/db') ->inject('response') ->inject('pools') ->action(function (Response $response, Group $pools) { - $output = []; + $failures = []; $configs = [ 'Console.DB' => Config::getParam('pools-console'), @@ -97,7 +100,7 @@ App::get('/v1/health/db') foreach ($configs as $key => $config) { foreach ($config as $database) { try { - $adapter = $pools->get($database)->pop()->getResource(); + $adapter = new DatabasePool($pools->get($database)); $checkStart = \microtime(true); @@ -108,16 +111,16 @@ App::get('/v1/health/db') 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } else { - $failure[] = $database; + $failures[] = $database; } - } catch (\Throwable $th) { - $failure[] = $database; + } catch (\Throwable) { + $failures[] = $database; } } } - if (!empty($failure)) { - throw new Exception(Exception::GENERAL_SERVER_ERROR, 'DB failure on: ' . implode(", ", $failure)); + if (!empty($failures)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'DB failure on: ' . implode(", ", $failures)); } $response->dynamic(new Document([ @@ -131,11 +134,11 @@ App::get('/v1/health/cache') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'health', name: 'getCache', description: '/docs/references/health/get-cache.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -147,44 +150,39 @@ App::get('/v1/health/cache') ->inject('response') ->inject('pools') ->action(function (Response $response, Group $pools) { - $output = []; + $failures = []; $configs = [ 'Cache' => Config::getParam('pools-cache'), ]; foreach ($configs as $key => $config) { - foreach ($config as $database) { + foreach ($config as $cache) { try { - /** @var \Utopia\Cache\Adapter $adapter */ - $adapter = $pools->get($database)->pop()->getResource(); + $adapter = new CachePool($pools->get($cache)); $checkStart = \microtime(true); if ($adapter->ping()) { $output[] = new Document([ - 'name' => $key . " ($database)", + 'name' => $key . " ($cache)", 'status' => 'pass', 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } else { - $output[] = new Document([ - 'name' => $key . " ($database)", - 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) - ]); + $failures[] = $cache; } - } catch (\Throwable $th) { - $output[] = new Document([ - 'name' => $key . " ($database)", - 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) - ]); + } catch (\Throwable) { + $failures[] = $cache; } } } + if (!empty($failures)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Cache failure on: ' . implode(", ", $failures)); + } + $response->dynamic(new Document([ 'statuses' => $output, 'total' => count($output), @@ -196,11 +194,11 @@ App::get('/v1/health/pubsub') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'health', name: 'getPubSub', description: '/docs/references/health/get-pubsub.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -212,44 +210,39 @@ App::get('/v1/health/pubsub') ->inject('response') ->inject('pools') ->action(function (Response $response, Group $pools) { - $output = []; + $failures = []; $configs = [ 'PubSub' => Config::getParam('pools-pubsub'), ]; foreach ($configs as $key => $config) { - foreach ($config as $database) { + foreach ($config as $pubsub) { try { - /** @var \Appwrite\PubSub\Adapter $adapter */ - $adapter = $pools->get($database)->pop()->getResource(); + $adapter = new PubSubPool($pools->get($pubsub)); $checkStart = \microtime(true); if ($adapter->ping()) { $output[] = new Document([ - 'name' => $key . " ($database)", + 'name' => $key . " ($pubsub)", 'status' => 'pass', 'ping' => \round((\microtime(true) - $checkStart) / 1000) ]); } else { - $output[] = new Document([ - 'name' => $key . " ($database)", - 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) - ]); + $failures[] = $pubsub; } - } catch (\Throwable $th) { - $output[] = new Document([ - 'name' => $key . " ($database)", - 'status' => 'fail', - 'ping' => \round((\microtime(true) - $checkStart) / 1000) - ]); + } catch (\Throwable) { + $failures[] = $pubsub; } } } + if (!empty($failures)) { + throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Pubsub failure on: ' . implode(", ", $failures)); + } + $response->dynamic(new Document([ 'statuses' => $output, 'total' => count($output), @@ -261,11 +254,11 @@ App::get('/v1/health/time') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'health', name: 'getTime', description: '/docs/references/health/get-time.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -325,11 +318,11 @@ App::get('/v1/health/queue/webhooks') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'queue', name: 'getQueueWebhooks', description: '/docs/references/health/get-queue-webhooks.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -351,18 +344,18 @@ App::get('/v1/health/queue/webhooks') } $response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE); - }, ['response']); + }); App::get('/v1/health/queue/logs') ->desc('Get logs queue') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'queue', name: 'getQueueLogs', description: '/docs/references/health/get-queue-logs.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -384,18 +377,18 @@ App::get('/v1/health/queue/logs') } $response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE); - }, ['response']); + }); App::get('/v1/health/certificate') ->desc('Get the SSL certificate for a domain') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'health', name: 'getCertificate', description: '/docs/references/health/get-certificate.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -441,18 +434,18 @@ App::get('/v1/health/certificate') 'validTo' => $certificatePayload['validTo_time_t'], 'signatureTypeSN' => $certificatePayload['signatureTypeSN'], ]), Response::MODEL_HEALTH_CERTIFICATE); - }, ['response']); + }); App::get('/v1/health/queue/certificates') ->desc('Get certificates queue') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'queue', name: 'getQueueCertificates', description: '/docs/references/health/get-queue-certificates.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -474,18 +467,18 @@ App::get('/v1/health/queue/certificates') } $response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE); - }, ['response']); + }); App::get('/v1/health/queue/builds') ->desc('Get builds queue') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'queue', name: 'getQueueBuilds', description: '/docs/references/health/get-queue-builds.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -507,18 +500,18 @@ App::get('/v1/health/queue/builds') } $response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE); - }, ['response']); + }); App::get('/v1/health/queue/databases') ->desc('Get databases queue') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'queue', name: 'getQueueDatabases', description: '/docs/references/health/get-queue-databases.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -541,18 +534,18 @@ App::get('/v1/health/queue/databases') } $response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE); - }, ['response']); + }); App::get('/v1/health/queue/deletes') ->desc('Get deletes queue') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'queue', name: 'getQueueDeletes', description: '/docs/references/health/get-queue-deletes.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -574,18 +567,18 @@ App::get('/v1/health/queue/deletes') } $response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE); - }, ['response']); + }); App::get('/v1/health/queue/mails') ->desc('Get mails queue') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'queue', name: 'getQueueMails', description: '/docs/references/health/get-queue-mails.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -607,18 +600,18 @@ App::get('/v1/health/queue/mails') } $response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE); - }, ['response']); + }); App::get('/v1/health/queue/messaging') ->desc('Get messaging queue') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'queue', name: 'getQueueMessaging', description: '/docs/references/health/get-queue-messaging.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -640,18 +633,18 @@ App::get('/v1/health/queue/messaging') } $response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE); - }, ['response']); + }); App::get('/v1/health/queue/migrations') ->desc('Get migrations queue') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'queue', name: 'getQueueMigrations', description: '/docs/references/health/get-queue-migrations.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -673,18 +666,18 @@ App::get('/v1/health/queue/migrations') } $response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE); - }, ['response']); + }); App::get('/v1/health/queue/functions') ->desc('Get functions queue') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'queue', name: 'getQueueFunctions', description: '/docs/references/health/get-queue-functions.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -706,18 +699,18 @@ App::get('/v1/health/queue/functions') } $response->dynamic(new Document([ 'size' => $size ]), Response::MODEL_HEALTH_QUEUE); - }, ['response']); + }); App::get('/v1/health/queue/stats-resources') ->desc('Get stats resources queue') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'queue', name: 'getQueueStatsResources', description: '/docs/references/health/get-queue-stats-resources.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -746,11 +739,11 @@ App::get('/v1/health/queue/stats-usage') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'queue', name: 'getQueueUsage', description: '/docs/references/health/get-queue-stats-usage.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -779,11 +772,11 @@ App::get('/v1/health/storage/local') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'storage', name: 'getStorageLocal', description: '/docs/references/health/get-storage-local.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -829,11 +822,11 @@ App::get('/v1/health/storage') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'storage', name: 'getStorage', description: '/docs/references/health/get-storage.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -877,11 +870,11 @@ App::get('/v1/health/anti-virus') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'health', name: 'getAntivirus', description: '/docs/references/health/get-storage-anti-virus.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -923,11 +916,11 @@ App::get('/v1/health/queue/failed/:name') ->groups(['api', 'health']) ->label('scope', 'health.read') ->label('sdk', new Method( - auth: [AuthType::KEY], namespace: 'health', group: 'queue', name: 'getFailedJobs', description: '/docs/references/health/get-failed-queue-jobs.md', + auth: [AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 839a51a764..c4f0b6a9df 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -24,6 +24,7 @@ use Utopia\App; use Utopia\Audit\Audit; use Utopia\Cache\Cache; use Utopia\Config\Config; +use Utopia\Database\Adapter\Pool as DatabasePool; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; @@ -223,7 +224,7 @@ App::post('/v1/projects') $sharedTables = $sharedTablesV1 || $sharedTablesV2; if (!$sharedTablesV2) { - $adapter = $pools->get($dsn->getHost())->pop()->getResource(); + $adapter = new DatabasePool($pools->get($dsn->getHost())); $dbForProject = new Database($adapter, $cache); if ($sharedTables) { diff --git a/app/http.php b/app/http.php index 963f550b8b..4d78837a8a 100644 --- a/app/http.php +++ b/app/http.php @@ -14,9 +14,11 @@ use Utopia\App; use Utopia\Audit\Audit; use Utopia\CLI\Console; use Utopia\Config\Config; +use Utopia\Database\Adapter\Pool as DatabasePool; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; +use Utopia\Database\Exception\Duplicate as DuplicateException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -167,7 +169,7 @@ function createDatabase(App $app, string $resourceKey, string $dbName, array $co $sleep = 1; $attempts = 0; - do { + while (true) { try { $attempts++; $resource = $app->getResource($resourceKey); @@ -176,13 +178,12 @@ function createDatabase(App $app, string $resourceKey, string $dbName, array $co break; // exit loop on success } catch (\Exception $e) { Console::warning(" └── Database not ready. Retrying connection ({$attempts})..."); - $pools->reclaim(); if ($attempts >= $max) { throw new \Exception(' └── Failed to connect to database: ' . $e->getMessage()); } sleep($sleep); } - } while ($attempts < $max); + } Console::success("[Setup] - $dbName database init started..."); @@ -318,11 +319,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg $cache = $app->getResource('cache'); foreach ($sharedTablesV2 as $hostname) { - $adapter = $pools - ->get($hostname) - ->pop() - ->getResource(); - + $adapter = new DatabasePool($pools->get($hostname)); $dbForProject = (new Database($adapter, $cache)) ->setDatabase('appwrite') ->setSharedTables(true) @@ -332,7 +329,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg try { Console::success('[Setup] - Creating project database: ' . $hostname . '...'); $dbForProject->create(); - } catch (Duplicate) { + } catch (DuplicateException) { Console::success('[Setup] - Skip: metadata table already exists'); } @@ -358,7 +355,6 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg } } - $pools->reclaim(); Console::success('[Setup] - Server database init completed...'); }); @@ -473,6 +469,7 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool Console::error('[Error] Message: ' . $th->getMessage()); Console::error('[Error] File: ' . $th->getFile()); Console::error('[Error] Line: ' . $th->getLine()); + Console::error('[Error] Trace: ' . $th->getTraceAsString()); $swooleResponse->setStatusCode(500); @@ -490,8 +487,6 @@ $http->on(Constant::EVENT_REQUEST, function (SwooleRequest $swooleRequest, Swool ]; $swooleResponse->end(\json_encode($output)); - } finally { - $pools->reclaim(); } }); diff --git a/app/init/registers.php b/app/init/registers.php index 1adaaf35ce..415730f936 100644 --- a/app/init/registers.php +++ b/app/init/registers.php @@ -216,13 +216,13 @@ $register->set('pools', function () { 'mysql', 'mariadb' => function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) { return new PDOProxy(function () use ($dsnHost, $dsnPort, $dsnUser, $dsnPass, $dsnDatabase) { - return new PDO("mysql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};charset=utf8mb4", $dsnUser, $dsnPass, array( + return new PDO("mysql:host={$dsnHost};port={$dsnPort};dbname={$dsnDatabase};charset=utf8mb4", $dsnUser, $dsnPass, [ \PDO::ATTR_TIMEOUT => 3, // Seconds \PDO::ATTR_PERSISTENT => false, \PDO::ATTR_DEFAULT_FETCH_MODE => \PDO::FETCH_ASSOC, \PDO::ATTR_EMULATE_PREPARES => true, \PDO::ATTR_STRINGIFY_FETCHES => true - )); + ]); }); }, 'redis' => function () use ($dsnHost, $dsnPort, $dsnPass) { diff --git a/app/init/resources.php b/app/init/resources.php index c719a47344..f48efbe177 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -24,10 +24,12 @@ use Appwrite\Utopia\Request; use Executor\Executor; use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\App; +use Utopia\Cache\Adapter\Pool as CachePool; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; use Utopia\CLI\Console; use Utopia\Config\Config; +use Utopia\Database\Adapter\Pool as DatabasePool; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; @@ -37,6 +39,7 @@ use Utopia\DSN\DSN; use Utopia\Locale\Locale; use Utopia\Logger\Log; use Utopia\Pools\Group; +use Utopia\Queue\Broker\Pool as BrokerPool; use Utopia\Queue\Publisher; use Utopia\Storage\Device; use Utopia\Storage\Device\AWS; @@ -72,10 +75,10 @@ App::setResource('localeCodes', function () { // Queues App::setResource('publisher', function (Group $pools) { - return $pools->get('publisher')->pop()->getResource(); + return new BrokerPool(publisher: $pools->get('publisher')); }, ['pools']); App::setResource('consumer', function (Group $pools) { - return $pools->get('consumer')->pop()->getResource(); + return new BrokerPool(consumer: $pools->get('consumer')); }, ['pools']); App::setResource('queueForMessaging', function (Publisher $publisher) { return new Messaging($publisher); @@ -329,12 +332,8 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - $dbAdapter = $pools - ->get($dsn->getHost()) - ->pop() - ->getResource(); - - $database = new Database($dbAdapter, $cache); + $adapter = new DatabasePool($pools->get($dsn->getHost())); + $database = new Database($adapter, $cache); $database ->setMetadata('host', \gethostname()) @@ -360,12 +359,8 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform }, ['pools', 'dbForPlatform', 'cache', 'project']); App::setResource('dbForPlatform', function (Group $pools, Cache $cache) { - $dbAdapter = $pools - ->get('console') - ->pop() - ->getResource(); - - $database = new Database($dbAdapter, $cache); + $adapter = new DatabasePool($pools->get('console')); + $database = new Database($adapter, $cache); $database ->setNamespace('_console') @@ -378,7 +373,7 @@ App::setResource('dbForPlatform', function (Group $pools, Cache $cache) { }, ['pools', 'cache']); App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform, $cache) { - $databases = []; // TODO: @Meldiron This should probably be responsibility of utopia-php/pools + $databases = []; return function (Document $project) use ($pools, $dbForPlatform, $cache, &$databases) { if ($project->isEmpty() || $project->getId() === 'console') { @@ -420,12 +415,8 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform return $database; } - $dbAdapter = $pools - ->get($dsn->getHost()) - ->pop() - ->getResource(); - - $database = new Database($dbAdapter, $cache); + $adapter = new DatabasePool($pools->get($dsn->getHost())); + $database = new Database($adapter, $cache); $databases[$dsn->getHost()] = $database; $configure($database); @@ -435,21 +426,15 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform App::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = null; - return function (?Document $project = null) use ($pools, $cache, $database) { + + return function (?Document $project = null) use ($pools, $cache, &$database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { $database->setTenant($project->getInternalId()); return $database; } - $dbAdapter = $pools - ->get('logs') - ->pop() - ->getResource(); - - $database = new Database( - $dbAdapter, - $cache - ); + $adapter = new DatabasePool($pools->get('logs')); + $database = new Database($adapter, $cache); $database ->setSharedTables(true) @@ -473,10 +458,7 @@ App::setResource('cache', function (Group $pools, Telemetry $telemetry) { $adapters = []; foreach ($list as $value) { - $adapters[] = $pools - ->get($value) - ->pop() - ->getResource(); + $adapters[] = new CachePool($pools->get($value)); } $cache = new Cache(new Sharding($adapters)); diff --git a/app/realtime.php b/app/realtime.php index 86f9c85fdd..7e6fc0e311 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -5,6 +5,7 @@ use Appwrite\Extend\Exception; use Appwrite\Extend\Exception as AppwriteException; use Appwrite\Messaging\Adapter\Realtime; use Appwrite\Network\Validator\Origin; +use Appwrite\PubSub\Adapter\Pool as PubSubPool; use Appwrite\Utopia\Request; use Appwrite\Utopia\Response; use Swoole\Http\Request as SwooleRequest; @@ -15,10 +16,12 @@ use Swoole\Timer; use Utopia\Abuse\Abuse; use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\App; +use Utopia\Cache\Adapter\Pool as CachePool; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; use Utopia\CLI\Console; use Utopia\Config\Config; +use Utopia\Database\Adapter\Pool as DatabasePool; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; @@ -28,13 +31,15 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\DSN\DSN; use Utopia\Logger\Log; +use Utopia\Pools\Group; +use Utopia\Registry\Registry; use Utopia\System\System; use Utopia\Telemetry\Adapter\None as NoTelemetry; use Utopia\WebSocket\Adapter; use Utopia\WebSocket\Server; /** - * @var \Utopia\Registry\Registry $register + * @var Registry $register */ require_once __DIR__ . '/init.php'; @@ -46,17 +51,17 @@ if (!function_exists('getConsoleDB')) { { global $register; - /** @var \Utopia\Pools\Group $pools */ + static $database = null; + + if ($database !== null) { + return $database; + } + + /** @var Group $pools */ $pools = $register->get('pools'); - $dbAdapter = $pools - ->get('console') - ->pop() - ->getResource() - ; - - $database = new Database($dbAdapter, getCache()); - + $adapter = new DatabasePool($pools->get('console')); + $database = new Database($adapter, getCache()); $database ->setNamespace('_console') ->setMetadata('host', \gethostname()) @@ -72,7 +77,13 @@ if (!function_exists('getProjectDB')) { { global $register; - /** @var \Utopia\Pools\Group $pools */ + static $databases = []; + + if (isset($databases[$project->getInternalId()])) { + return $databases[$project->getInternalId()]; + } + + /** @var Group $pools */ $pools = $register->get('pools'); if ($project->isEmpty() || $project->getId() === 'console') { @@ -86,11 +97,7 @@ if (!function_exists('getProjectDB')) { $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - $adapter = $pools - ->get($dsn->getHost()) - ->pop() - ->getResource(); - + $adapter = new DatabasePool($pools->get($dsn->getHost())); $database = new Database($adapter, getCache()); $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); @@ -111,7 +118,7 @@ if (!function_exists('getProjectDB')) { ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()); - return $database; + return $databases[$project->getInternalId()] = $database; } } @@ -121,20 +128,22 @@ if (!function_exists('getCache')) { { global $register; - $pools = $register->get('pools'); /** @var \Utopia\Pools\Group $pools */ + static $cache = null; + + if ($cache !== null) { + return $cache; + } + + $pools = $register->get('pools'); /** @var Group $pools */ $list = Config::getParam('pools-cache', []); $adapters = []; foreach ($list as $value) { - $adapters[] = $pools - ->get($value) - ->pop() - ->getResource() - ; + $adapters[] = new CachePool($pools->get($value)); } - return new Cache(new Sharding($adapters)); + return $cache = new Cache(new Sharding($adapters)); } } @@ -142,6 +151,12 @@ if (!function_exists('getCache')) { if (!function_exists('getRedis')) { function getRedis(): \Redis { + static $redis = null; + + if ($redis !== null) { + return $redis; + } + $host = System::getEnv('_APP_REDIS_HOST', 'localhost'); $port = System::getEnv('_APP_REDIS_PORT', 6379); $pass = System::getEnv('_APP_REDIS_PASS', ''); @@ -160,21 +175,39 @@ if (!function_exists('getRedis')) { if (!function_exists('getTimelimit')) { function getTimelimit(): TimeLimitRedis { - return new TimeLimitRedis("", 0, 1, getRedis()); + static $timelimit = null; + + if ($timelimit !== null) { + return $timelimit; + } + + return $timelimit = new TimeLimitRedis("", 0, 1, getRedis()); } } if (!function_exists('getRealtime')) { function getRealtime(): Realtime { - return new Realtime(); + static $realtime = null; + + if ($realtime !== null) { + return $realtime; + } + + return $realtime = new Realtime(); } } if (!function_exists('getTelemetry')) { function getTelemetry(int $workerId): Utopia\Telemetry\Adapter { - return new NoTelemetry(); + static $telemetry = null; + + if ($telemetry !== null) { + return $telemetry; + } + + return $telemetry = new NoTelemetry(); } } @@ -273,7 +306,6 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume sleep(DATABASE_RECONNECT_SLEEP); } } while (true); - $register->get('pools')->reclaim(); }); /** @@ -299,9 +331,7 @@ $server->onStart(function () use ($stats, $register, $containerId, &$statsDocume Authorization::skip(fn () => $database->updateDocument('realtime', $statsDocument->getId(), $statsDocument)); } catch (Throwable $th) { - call_user_func($logError, $th, "updateWorkerDocument"); - } finally { - $register->get('pools')->reclaim(); + $logError($th, "updateWorkerDocument"); } }); } @@ -370,8 +400,6 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, 'data' => $event['data'] ])); } - - $register->get('pools')->reclaim(); } } /** @@ -407,8 +435,8 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, } $start = time(); - /** @var \Appwrite\PubSub\Adapter $pubsub */ - $pubsub = $register->get('pools')->get('pubsub')->pop()->getResource(); + $pubsub = new PubSubPool($register->get('pools')->get('pubsub')); + if ($pubsub->ping(true)) { $attempts = 0; Console::success('Pub/sub connection established (worker: ' . $workerId . ')'); @@ -436,8 +464,6 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, $realtime->unsubscribe($connection); $realtime->subscribe($projectId, $connection, $roles, $channels); - - $register->get('pools')->reclaim(); } } @@ -463,14 +489,12 @@ $server->onWorkerStart(function (int $workerId) use ($server, $register, $stats, } }); } catch (Throwable $th) { - call_user_func($logError, $th, "pubSubConnection"); + $logError($th, "pubSubConnection"); Console::error('Pub/sub error: ' . $th->getMessage()); $attempts++; sleep(DATABASE_RECONNECT_SLEEP); continue; - } finally { - $register->get('pools')->reclaim(); } } @@ -572,7 +596,7 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, $stats->incr($project->getId(), 'connections'); $stats->incr($project->getId(), 'connectionsTotal'); } catch (Throwable $th) { - call_user_func($logError, $th, "initServer"); + $logError($th, "initServer"); // Handle SQL error code is 'HY000' $code = $th->getCode(); @@ -596,8 +620,6 @@ $server->onOpen(function (int $connection, SwooleRequest $request) use ($server, Console::error('[Error] Code: ' . $response['data']['code']); Console::error('[Error] Message: ' . $response['data']['message']); } - } finally { - $register->get('pools')->reclaim(); } }); @@ -696,8 +718,6 @@ $server->onMessage(function (int $connection, string $message) use ($server, $re if ($th->getCode() === 1008) { $server->close($connection, $th->getCode()); } - } finally { - $register->get('pools')->reclaim(); } }); diff --git a/app/worker.php b/app/worker.php index 232e0b3684..1ae2108a62 100644 --- a/app/worker.php +++ b/app/worker.php @@ -20,10 +20,12 @@ use Appwrite\Platform\Appwrite; use Executor\Executor; use Swoole\Runtime; use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; +use Utopia\Cache\Adapter\Pool as CachePool; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; use Utopia\CLI\Console; use Utopia\Config\Config; +use Utopia\Database\Adapter\Pool as DatabasePool; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; @@ -33,6 +35,7 @@ use Utopia\Logger\Log; use Utopia\Logger\Logger; use Utopia\Platform\Service; use Utopia\Pools\Group; +use Utopia\Queue\Broker\Pool as BrokerPool; use Utopia\Queue\Message; use Utopia\Queue\Publisher; use Utopia\Queue\Server; @@ -40,21 +43,17 @@ use Utopia\Registry\Registry; use Utopia\System\System; Authorization::disable(); -Runtime::enableCoroutine(SWOOLE_HOOK_ALL); +Runtime::enableCoroutine(); Server::setResource('register', fn () => $register); Server::setResource('dbForPlatform', function (Cache $cache, Registry $register) { $pools = $register->get('pools'); - $database = $pools - ->get('console') - ->pop() - ->getResource(); + $adapter = new DatabasePool($pools->get('console')); + $dbForPlatform = new Database($adapter, $cache); + $dbForPlatform->setNamespace('_console'); - $adapter = new Database($database, $cache); - $adapter->setNamespace('_console'); - - return $adapter; + return $dbForPlatform; }, ['cache', 'register']); Server::setResource('project', function (Message $message, Database $dbForPlatform) { @@ -82,20 +81,9 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, $dsn = new DSN('mysql://' . $project->getAttribute('database')); } - $adapter = $pools - ->get($dsn->getHost()) - ->pop() - ->getResource(); - + $adapter = new DatabasePool($pools->get($dsn->getHost())); $database = new Database($adapter, $cache); - try { - $dsn = new DSN($project->getAttribute('database')); - } catch (\InvalidArgumentException) { - // TODO: Temporary until all projects are using shared tables - $dsn = new DSN('mysql://' . $project->getAttribute('database')); - } - $sharedTables = \explode(',', System::getEnv('_APP_DATABASE_SHARED_TABLES', '')); if (\in_array($dsn->getHost(), $sharedTables)) { @@ -150,12 +138,8 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf return $database; } - $dbAdapter = $pools - ->get($dsn->getHost()) - ->pop() - ->getResource(); - - $database = new Database($dbAdapter, $cache); + $adapter = new DatabasePool($pools->get($dsn->getHost())); + $database = new Database($adapter, $cache); $databases[$dsn->getHost()] = $database; @@ -187,15 +171,8 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) { return $database; } - $dbAdapter = $pools - ->get('logs') - ->pop() - ->getResource(); - - $database = new Database( - $dbAdapter, - $cache - ); + $adapter = new DatabasePool($pools->get('logs')); + $database = new Database($adapter, $cache); $database ->setSharedTables(true) @@ -233,11 +210,7 @@ Server::setResource('cache', function (Registry $register) { $adapters = []; foreach ($list as $value) { - $adapters[] = $pools - ->get($value) - ->pop() - ->getResource() - ; + $adapters[] = new CachePool($pools->get($value)); } return new Cache(new Sharding($adapters)); @@ -267,11 +240,11 @@ Server::setResource('timelimit', function (\Redis $redis) { Server::setResource('log', fn () => new Log()); Server::setResource('publisher', function (Group $pools) { - return $pools->get('publisher')->pop()->getResource(); + return new BrokerPool(publisher: $pools->get('publisher')); }, ['pools']); Server::setResource('consumer', function (Group $pools) { - return $pools->get('consumer')->pop()->getResource(); + return new BrokerPool(consumer: $pools->get('consumer')); }, ['pools']); Server::setResource('queueForStatsUsage', function (Publisher $publisher) { @@ -448,13 +421,6 @@ try { $worker = $platform->getWorker(); -$worker - ->shutdown() - ->inject('pools') - ->action(function (Group $pools) { - $pools->reclaim(); - }); - $worker ->error() ->inject('error') @@ -462,8 +428,7 @@ $worker ->inject('log') ->inject('pools') ->inject('project') - ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project) use ($queueName) { - $pools->reclaim(); + ->action(function (Throwable $error, ?Logger $logger, Log $log, Group $pools, Document $project) use ($worker, $queueName) { $version = System::getEnv('_APP_VERSION', 'UNKNOWN'); if ($logger) { diff --git a/composer.json b/composer.json index 9b2cf7a1ab..914e664d7f 100644 --- a/composer.json +++ b/composer.json @@ -65,7 +65,7 @@ "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", "utopia-php/preloader": "0.2.*", - "utopia-php/queue": "0.9.*", + "utopia-php/queue": "0.10.*", "utopia-php/registry": "0.5.*", "utopia-php/storage": "0.18.*", "utopia-php/swoole": "0.8.*", diff --git a/composer.lock b/composer.lock index e6bcd919e2..d04d67366e 100644 --- a/composer.lock +++ b/composer.lock @@ -4059,16 +4059,16 @@ }, { "name": "utopia-php/platform", - "version": "0.7.4", + "version": "0.7.5", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "a5b93d8177702ec458c3af9137663133c012b71b" + "reference": "8febd7b6e0c0f2cbd2f4289447bcca97496e4aaf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/a5b93d8177702ec458c3af9137663133c012b71b", - "reference": "a5b93d8177702ec458c3af9137663133c012b71b", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/8febd7b6e0c0f2cbd2f4289447bcca97496e4aaf", + "reference": "8febd7b6e0c0f2cbd2f4289447bcca97496e4aaf", "shasum": "" }, "require": { @@ -4077,11 +4077,11 @@ "php": ">=8.0", "utopia-php/cli": "0.15.*", "utopia-php/framework": "0.33.*", - "utopia-php/queue": "0.9.*" + "utopia-php/queue": "0.10.*" }, "require-dev": { - "laravel/pint": "1.2.*", - "phpunit/phpunit": "^9.3" + "laravel/pint": "1.*", + "phpunit/phpunit": "9.*" }, "type": "library", "autoload": { @@ -4103,9 +4103,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.7.4" + "source": "https://github.com/utopia-php/platform/tree/0.7.5" }, - "time": "2025-03-13T13:00:12+00:00" + "time": "2025-04-17T12:20:16+00:00" }, { "name": "utopia-php/pools", @@ -4214,16 +4214,16 @@ }, { "name": "utopia-php/queue", - "version": "0.9.1", + "version": "0.10.0", "source": { "type": "git", "url": "https://github.com/utopia-php/queue.git", - "reference": "32b6f84c55aae761db5a5ae76cc91ca8dbc8bc32" + "reference": "0eccc559168ea72241c39a4c482d868314666be1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/queue/zipball/32b6f84c55aae761db5a5ae76cc91ca8dbc8bc32", - "reference": "32b6f84c55aae761db5a5ae76cc91ca8dbc8bc32", + "url": "https://api.github.com/repos/utopia-php/queue/zipball/0eccc559168ea72241c39a4c482d868314666be1", + "reference": "0eccc559168ea72241c39a4c482d868314666be1", "shasum": "" }, "require": { @@ -4232,6 +4232,7 @@ "utopia-php/cli": "0.15.*", "utopia-php/fetch": "0.4.*", "utopia-php/framework": "0.33.*", + "utopia-php/pools": "0.8.*", "utopia-php/telemetry": "0.1.*" }, "require-dev": { @@ -4273,9 +4274,9 @@ ], "support": { "issues": "https://github.com/utopia-php/queue/issues", - "source": "https://github.com/utopia-php/queue/tree/0.9.1" + "source": "https://github.com/utopia-php/queue/tree/0.10.0" }, - "time": "2025-03-28T19:49:36+00:00" + "time": "2025-04-17T12:15:52+00:00" }, { "name": "utopia-php/registry", diff --git a/src/Appwrite/Event/Event.php b/src/Appwrite/Event/Event.php index d699a45417..2c735ef2d4 100644 --- a/src/Appwrite/Event/Event.php +++ b/src/Appwrite/Event/Event.php @@ -286,13 +286,6 @@ class Event return $this; } - public function setParamSensitive(string $key): self - { - $this->sensitive[$key] = true; - - return $this; - } - /** * Get param of event. * diff --git a/src/Appwrite/Messaging/Adapter/Realtime.php b/src/Appwrite/Messaging/Adapter/Realtime.php index 96793b2683..be263aa655 100644 --- a/src/Appwrite/Messaging/Adapter/Realtime.php +++ b/src/Appwrite/Messaging/Adapter/Realtime.php @@ -2,14 +2,14 @@ namespace Appwrite\Messaging\Adapter; -use Appwrite\Messaging\Adapter; +use Appwrite\Messaging\Adapter as MessagingAdapter; +use Appwrite\PubSub\Adapter\Pool as PubSubPool; use Utopia\Database\DateTime; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Role; -use Utopia\Pools\Pool; -class Realtime extends Adapter +class Realtime extends MessagingAdapter { /** * Connection Tree @@ -132,11 +132,12 @@ class Realtime extends Adapter * Sends an event to the Realtime Server * @param string $projectId * @param array $payload - * @param string $event + * @param array $events * @param array $channels * @param array $roles * @param array $options * @return void + * @throws \Exception */ public function send(string $projectId, array $payload, array $events, array $channels, array $roles, array $options = []): void { @@ -158,9 +159,7 @@ class Realtime extends Adapter 'timestamp' => DateTime::formatTz(DateTime::now()), 'payload' => $payload ] - ]; - - $this->pubsubPool->use(fn (\Appwrite\PubSub\Adapter $pubsub) => $pubsub->publish('realtime', json_encode($message))); + ])); } /** @@ -175,8 +174,9 @@ class Realtime extends Adapter * - 1,121.328 ms (±0.84%) | 1,000,000 Connections / 10,000,000 Subscriptions * * @param array $event + * @return int[]|string[] */ - public function getSubscribers(array $event) + public function getSubscribers(array $event): array { $receivers = []; @@ -230,7 +230,7 @@ class Realtime extends Adapter foreach ($channels as $key => $value) { switch (true) { - case strpos($key, 'account.') === 0: + case \str_starts_with($key, 'account.'): unset($channels[$key]); break; @@ -272,6 +272,7 @@ class Realtime extends Adapter $channels[] = 'account.' . $parts[1]; $roles = [Role::user(ID::custom($parts[1]))->toString()]; break; + case 'migrations': case 'rules': $channels[] = 'console'; $channels[] = 'projects.' . $project->getId(); @@ -352,12 +353,6 @@ class Realtime extends Adapter $roles = [Role::team($project->getAttribute('teamId'))->toString()]; } - break; - case 'migrations': - $channels[] = 'console'; - $channels[] = 'projects.' . $project->getId(); - $projectId = 'console'; - $roles = [Role::team($project->getAttribute('teamId'))->toString()]; break; } diff --git a/src/Appwrite/Platform/Tasks/Doctor.php b/src/Appwrite/Platform/Tasks/Doctor.php index c43afea527..5263133eba 100644 --- a/src/Appwrite/Platform/Tasks/Doctor.php +++ b/src/Appwrite/Platform/Tasks/Doctor.php @@ -3,14 +3,19 @@ namespace Appwrite\Platform\Tasks; use Appwrite\ClamAV\Network; -use Appwrite\PubSub\Adapter; +use Appwrite\PubSub\Adapter\Pool as PubSubPool; +use PHPMailer\PHPMailer\PHPMailer; use Utopia\App; +use Utopia\Cache\Adapter\Pool as CachePool; use Utopia\CLI\Console; use Utopia\Config\Config; +use Utopia\Database\Adapter\Pool as DatabasePool; use Utopia\Domains\Domain; use Utopia\DSN\DSN; use Utopia\Logger\Logger; use Utopia\Platform\Action; +use Utopia\Pools\Group; +use Utopia\Queue\Broker\Pool as BrokerPool; use Utopia\Registry\Registry; use Utopia\Storage\Device\Local; use Utopia\Storage\Storage; @@ -76,9 +81,9 @@ class Doctor extends Action Console::log('🟢 Abuse protection is enabled'); } - $authWhitelistRoot = System::getEnv('_APP_CONSOLE_WHITELIST_ROOT', null); - $authWhitelistEmails = System::getEnv('_APP_CONSOLE_WHITELIST_EMAILS', null); - $authWhitelistIPs = System::getEnv('_APP_CONSOLE_WHITELIST_IPS', null); + $authWhitelistRoot = System::getEnv('_APP_CONSOLE_WHITELIST_ROOT'); + $authWhitelistEmails = System::getEnv('_APP_CONSOLE_WHITELIST_EMAILS'); + $authWhitelistIPs = System::getEnv('_APP_CONSOLE_WHITELIST_IPS'); if ( empty($authWhitelistRoot) @@ -114,19 +119,16 @@ class Doctor extends Action } else { Console::log('🟢 Logging adapter is enabled (' . $providerName . ')'); } - } catch (\Throwable $th) { + } catch (\Throwable) { Console::log('🔴 Logging adapter is misconfigured'); } \usleep(200 * 1000); // Sleep for 0.2 seconds - try { - Console::log("\n" . '[Connectivity]'); - } catch (\Throwable $th) { - //throw $th; - } + Console::log("\n" . '[Connectivity]'); - $pools = $register->get('pools'); /** @var \Utopia\Pools\Group $pools */ + /** @var Group $pools */ + $pools = $register->get('pools'); $configs = [ 'Console.DB' => Config::getParam('pools-console'), @@ -136,20 +138,22 @@ class Doctor extends Action foreach ($configs as $key => $config) { foreach ($config as $database) { try { - $adapter = $pools->get($database)->pop()->getResource(); + $adapter = new DatabasePool($pools->get($database)); if ($adapter->ping()) { Console::success('🟢 ' . str_pad("{$key}({$database})", 50, '.') . 'connected'); } else { Console::error('🔴 ' . str_pad("{$key}({$database})", 47, '.') . 'disconnected'); } - } catch (\Throwable $th) { + } catch (\Throwable) { Console::error('🔴 ' . str_pad("{$key}.({$database})", 47, '.') . 'disconnected'); } } } - $pools = $register->get('pools'); /** @var \Utopia\Pools\Group $pools */ + /** @var Group $pools */ + $pools = $register->get('pools'); + $configs = [ 'Cache' => Config::getParam('pools-cache'), 'Queue' => Config::getParam('pools-queue'), @@ -159,15 +163,18 @@ class Doctor extends Action foreach ($configs as $key => $config) { foreach ($config as $pool) { try { - /** @var Adapter $adapter */ - $adapter = $pools->get($pool)->pop()->getResource(); + $adapter = match($key) { + 'Cache' => new CachePool($pools->get($pool)), + 'Queue' => new BrokerPool($pools->get($pool)), + 'PubSub' => new PubSubPool($pools->get($pool)), + }; if ($adapter->ping()) { Console::success('🟢 ' . str_pad("{$key}({$pool})", 50, '.') . 'connected'); } else { Console::error('🔴 ' . str_pad("{$key}({$pool})", 47, '.') . 'disconnected'); } - } catch (\Throwable $th) { + } catch (\Throwable) { Console::error('🔴 ' . str_pad("{$key}({$pool})", 47, '.') . 'disconnected'); } } @@ -185,13 +192,14 @@ class Doctor extends Action } else { Console::error('🔴 ' . str_pad("Antivirus", 47, '.') . 'disconnected'); } - } catch (\Throwable $th) { + } catch (\Throwable) { Console::error('🔴 ' . str_pad("Antivirus", 47, '.') . 'disconnected'); } } try { - $mail = $register->get('smtp'); /* @var $mail \PHPMailer\PHPMailer\PHPMailer */ + /* @var PHPMailer $mail */ + $mail = $register->get('smtp'); $mail->addAddress('demo@example.com', 'Example.com'); $mail->Subject = 'Test SMTP Connection'; @@ -200,7 +208,7 @@ class Doctor extends Action $mail->send(); Console::success('🟢 ' . str_pad("SMTP", 50, '.') . 'connected'); - } catch (\Throwable $th) { + } catch (\Throwable) { Console::error('🔴 ' . str_pad("SMTP", 47, '.') . 'disconnected'); } @@ -274,7 +282,7 @@ class Doctor extends Action Console::error('Failed to check for a newer version' . "\n"); } } - } catch (\Throwable $th) { + } catch (\Throwable) { Console::error('Failed to check for a newer version' . "\n"); } } diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index afd7d9d22a..3e9907f877 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -13,6 +13,7 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Platform\Action; use Utopia\Pools\Group; +use Utopia\Queue\Broker\Pool as BrokerPool; use Utopia\System\System; use Utopia\Telemetry\Adapter as Telemetry; use Utopia\Telemetry\Gauge; @@ -25,6 +26,8 @@ abstract class ScheduleBase extends Action protected array $schedules = []; + protected BrokerPool $publisher; + private ?Histogram $collectSchedulesTelemetryDuration = null; private ?Gauge $collectSchedulesTelemetryCount = null; private ?Gauge $scheduleTelemetryCount = null; @@ -71,6 +74,7 @@ abstract class ScheduleBase extends Action Console::title(\ucfirst(static::getSupportedResource()) . ' scheduler V1'); Console::success(APP_NAME . ' ' . \ucfirst(static::getSupportedResource()) . ' scheduler v1 has started'); + $this->publisher = new BrokerPool($pools->get('publisher')); $this->scheduleTelemetryCount = $telemetry->createGauge('task.schedule.count'); $this->collectSchedulesTelemetryDuration = $telemetry->createHistogram('task.schedule.collect_schedules.duration', 's'); $this->collectSchedulesTelemetryCount = $telemetry->createGauge('task.schedule.collect_schedules.count'); @@ -122,8 +126,6 @@ abstract class ScheduleBase extends Action $schedule->getAttribute('resourceId') ); - $pools->reclaim(); - return [ '$internalId' => $schedule->getInternalId(), '$id' => $schedule->getId(), diff --git a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php index 89d1609a33..331928d265 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php @@ -3,7 +3,6 @@ namespace Appwrite\Platform\Tasks; use Appwrite\Event\Func; -use Swoole\Coroutine as Co; use Utopia\Database\Database; use Utopia\Pools\Group; @@ -29,9 +28,6 @@ class ScheduleExecutions extends ScheduleBase protected function enqueueResources(Group $pools, Database $dbForPlatform, callable $getProjectDB): void { - $queue = $pools->get('publisher')->pop(); - $connection = $queue->getResource(); - $queueForFunctions = new Func($connection); $intervalEnd = (new \DateTime())->modify('+' . self::ENQUEUE_TIMER . ' seconds'); foreach ($this->schedules as $schedule) { @@ -59,8 +55,10 @@ class ScheduleExecutions extends ScheduleBase $this->updateProjectAccess($schedule['project'], $dbForPlatform); - \go(function () use ($queueForFunctions, $schedule, $scheduledAt, $delay, $data) { - Co::sleep($delay); + \go(function () use ($schedule, $delay, $data, $pools) { + \Co::sleep($delay); + + $queueForFunctions = new Func($this->publisher); $queueForFunctions->setType('schedule') // Set functionId instead of function as we don't have $dbForProject @@ -85,7 +83,5 @@ class ScheduleExecutions extends ScheduleBase unset($this->schedules[$schedule['$internalId']]); } - - $queue->reclaim(); } } diff --git a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php index 6788748f3d..649fdb333a 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php @@ -75,12 +75,9 @@ class ScheduleFunctions extends ScheduleBase $delayedExecutions[$delay][] = ['key' => $key, 'nextDate' => $nextDate]; } - foreach ($delayedExecutions as $delay => $schedules) { - \go(function () use ($delay, $schedules, $pools, $dbForPlatform) { - \sleep($delay); // in seconds - - $queue = $pools->get('publisher')->pop(); - $connection = $queue->getResource(); + foreach ($delayedExecutions as $delay => $scheduleKeys) { + \go(function () use ($delay, $scheduleKeys, $pools, $dbForPlatform) { + \Co::sleep($delay); // in seconds foreach ($schedules as $delayConfig) { $scheduleKey = $delayConfig['key']; @@ -93,7 +90,7 @@ class ScheduleFunctions extends ScheduleBase $this->updateProjectAccess($schedule['project'], $dbForPlatform); - $queueForFunctions = new Func($connection); + $queueForFunctions = new Func($this->publisher); $queueForFunctions ->setType('schedule') @@ -105,8 +102,6 @@ class ScheduleFunctions extends ScheduleBase $this->recordEnqueueDelay($delayConfig['nextDate']); } - - $queue->reclaim(); }); } diff --git a/src/Appwrite/Platform/Tasks/ScheduleMessages.php b/src/Appwrite/Platform/Tasks/ScheduleMessages.php index a15df6ed5b..4f7dfab6a0 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleMessages.php +++ b/src/Appwrite/Platform/Tasks/ScheduleMessages.php @@ -40,10 +40,8 @@ class ScheduleMessages extends ScheduleBase continue; } - \go(function () use ($schedule, $scheduledAt, $pools, $dbForPlatform) { - $queue = $pools->get('publisher')->pop(); - $connection = $queue->getResource(); - $queueForMessaging = new Messaging($connection); + \go(function () use ($schedule, $pools, $dbForPlatform) { + $queueForMessaging = new Messaging($this->publisher); $this->updateProjectAccess($schedule['project'], $dbForPlatform); @@ -58,7 +56,6 @@ class ScheduleMessages extends ScheduleBase $schedule['$id'], ); - $queue->reclaim(); $this->recordEnqueueDelay($scheduledAt); unset($this->schedules[$schedule['$internalId']]); }); diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index a61db63de6..427772a6e0 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -61,10 +61,7 @@ class Deletes extends Action ->inject('executionRetention') ->inject('auditRetention') ->inject('log') - ->callback( - fn ($message, Document $project, Database $dbForPlatform, callable $getProjectDB, callable $getLogsDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, Executor $executor, string $executionRetention, string $auditRetention, Log $log) => - $this->action($message, $project, $dbForPlatform, $getProjectDB, $getLogsDB, $deviceForFiles, $deviceForFunctions, $deviceForBuilds, $deviceForCache, $certificates, $executor, $executionRetention, $auditRetention, $log) - ); + ->callback([$this, 'action']); } /** diff --git a/src/Appwrite/Platform/Workers/StatsUsage.php b/src/Appwrite/Platform/Workers/StatsUsage.php index 66f285fcf5..60fab5d2ea 100644 --- a/src/Appwrite/Platform/Workers/StatsUsage.php +++ b/src/Appwrite/Platform/Workers/StatsUsage.php @@ -325,7 +325,7 @@ class StatsUsage extends Action break; } } catch (Throwable $e) { - console::error("[reducer] " . " {DateTime::now()} " . " {$project->getInternalId()} " . " {$e->getMessage()}"); + Console::error("[reducer] " . " {DateTime::now()} " . " {$project->getInternalId()} " . " {$e->getMessage()}"); } } @@ -344,7 +344,7 @@ class StatsUsage extends Action continue; } - console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); + Console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); try { foreach ($stats['keys'] ?? [] as $key => $value) { @@ -381,7 +381,7 @@ class StatsUsage extends Action } } } catch (Exception $e) { - console::error('[' . DateTime::now() . '] project [' . $project->getInternalId() . '] database [' . $project['database'] . '] ' . ' ' . $e->getMessage()); + Console::error('[' . DateTime::now() . '] project [' . $project->getInternalId() . '] database [' . $project['database'] . '] ' . ' ' . $e->getMessage()); } } @@ -405,7 +405,7 @@ class StatsUsage extends Action } - protected function prepareForLogsDB(Document $project, Document $stat) + protected function prepareForLogsDB(Document $project, Document $stat): void { if (System::getEnv('_APP_STATS_USAGE_DUAL_WRITING', 'disabled') === 'disabled') { return; @@ -430,8 +430,7 @@ class StatsUsage extends Action return; } - $dbForLogs = call_user_func($this->getLogsDB); - $dbForLogs + $dbForLogs = ($this->getLogsDB)() ->setTenant(null) ->setTenantPerDocument(true); @@ -446,6 +445,5 @@ class StatsUsage extends Action } catch (Throwable $th) { Console::error($th->getMessage()); } - $this->register->get('pools')->get('logs')->reclaim(); } } diff --git a/src/Appwrite/Platform/Workers/StatsUsageDump.php b/src/Appwrite/Platform/Workers/StatsUsageDump.php index b9d486e0d8..77ec3f13e6 100644 --- a/src/Appwrite/Platform/Workers/StatsUsageDump.php +++ b/src/Appwrite/Platform/Workers/StatsUsageDump.php @@ -70,9 +70,9 @@ class StatsUsageDump extends Action ]; /** - * @var callable + * @var callable(Document): Database */ - protected mixed $getLogsDB; + protected $getLogsDB; protected array $periods = [ '1h' => 'Y-m-d H:00', @@ -126,10 +126,10 @@ class StatsUsageDump extends Action continue; } - console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); + Console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); try { - /** @var \Utopia\Database\Database $dbForProject */ + /** @var Database $dbForProject */ $dbForProject = $getProjectDB($project); foreach ($stats['keys'] ?? [] as $key => $value) { if ($value == 0) { @@ -169,7 +169,7 @@ class StatsUsageDump extends Action } } } catch (\Exception $e) { - console::error('[' . DateTime::now() . '] project [' . $project->getInternalId() . '] database [' . $project['database'] . '] ' . ' ' . $e->getMessage()); + Console::error('[' . DateTime::now() . '] project [' . $project->getInternalId() . '] database [' . $project['database'] . '] ' . ' ' . $e->getMessage()); } } } @@ -190,8 +190,7 @@ class StatsUsageDump extends Action } } - /** @var \Utopia\Database\Database $dbForLogs*/ - $dbForLogs = call_user_func($this->getLogsDB, $project); + $dbForLogs = ($this->getLogsDB)($project); try { $dbForLogs->createOrUpdateDocumentsWithIncrease( @@ -203,7 +202,5 @@ class StatsUsageDump extends Action } catch (\Throwable $th) { Console::error($th->getMessage()); } - - $this->register->get('pools')->get('logs')->reclaim(); } } diff --git a/src/Appwrite/PubSub/Adapter/Pool.php b/src/Appwrite/PubSub/Adapter/Pool.php new file mode 100644 index 0000000000..a498118dae --- /dev/null +++ b/src/Appwrite/PubSub/Adapter/Pool.php @@ -0,0 +1,46 @@ +delegate(__FUNCTION__, \func_get_args()); + } + + public function subscribe($channels, $callback): void + { + $this->delegate(__FUNCTION__, \func_get_args()); + } + + public function publish($channel, $message): void + { + $this->delegate(__FUNCTION__, \func_get_args()); + } + + /** + * Forward method calls to the internal adapter instance via the pool. + * + * Required because __call() can't be used to implement abstract methods. + * + * @param string $method + * @param array $args + * @return mixed + * @throws DatabaseException + */ + public function delegate(string $method, array $args): mixed + { + return $this->pool->use(function (Adapter $adapter) use ($method, $args) { + return $adapter->{$method}(...$args); + }); + } +} diff --git a/tests/resources/docker/docker-compose.yml b/tests/resources/docker/docker-compose.yml index e549ac27a5..779d63d6ed 100644 --- a/tests/resources/docker/docker-compose.yml +++ b/tests/resources/docker/docker-compose.yml @@ -35,7 +35,7 @@ services: - VERSION=dev restart: unless-stopped ports: - - 9501:80 + - "9501:80" networks: - appwrite labels: @@ -52,15 +52,12 @@ services: - ./phpunit.xml:/usr/src/code/phpunit.xml - ./tests:/usr/src/code/tests - ./app:/usr/src/code/app - # - ./vendor:/usr/src/code/vendor - ./docs:/usr/src/code/docs - ./public:/usr/src/code/public - ./src:/usr/src/code/src - - ./debug:/tmp depends_on: - mariadb - redis - # - clamav environment: - _APP_COMPRESSION_MIN_SIZE_BYTES - _APP_ENV @@ -355,33 +352,6 @@ services: volumes: - appwrite-redis:/data:rw - # clamav: - # image: appwrite/clamav:1.2.0 - # container_name: appwrite-clamav - # restart: unless-stopped - # networks: - # - appwrite - # volumes: - # - appwrite-uploads:/storage/uploads - - - # redis-commander: - # image: rediscommander/redis-commander:latest - # restart: unless-stopped - # networks: - # - appwrite - # environment: - # - REDIS_HOSTS=redis - # ports: - # - "8081:8081" - - # webgrind: - # image: 'jokkedk/webgrind:latest' - # volumes: - # - './debug:/tmp' - # ports: - # - '3001:80' - networks: gateway: appwrite: From af3388a51f9226455f0924b596047eb97f84c5d6 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 14 May 2025 18:16:54 +1200 Subject: [PATCH 006/219] Format --- app/cli.php | 3 ++- composer.lock | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/app/cli.php b/app/cli.php index 61d8a90100..663423b57a 100644 --- a/app/cli.php +++ b/app/cli.php @@ -10,6 +10,7 @@ use Appwrite\Event\StatsUsage; use Appwrite\Platform\Appwrite; use Appwrite\Runtimes\Runtimes; use Executor\Executor; +use Swoole\Timer; use Utopia\Cache\Adapter\Pool as CachePool; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; @@ -29,7 +30,7 @@ use Utopia\Queue\Publisher; use Utopia\Registry\Registry; use Utopia\System\System; use Utopia\Telemetry\Adapter\None as NoTelemetry; -use Swoole\Timer; + use function Swoole\Coroutine\run; // Overwriting runtimes to be architecture agnostic for CLI diff --git a/composer.lock b/composer.lock index d04d67366e..945948739a 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "1eeb5a0f3560aefd8f71bd0955e30360", + "content-hash": "24b02f9535e6a202fde735137f0ec900", "packages": [ { "name": "adhocore/jwt", From 09152a08e1756620fcc18072e7ff96b54876ec76 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 14 May 2025 18:27:51 +1200 Subject: [PATCH 007/219] Fix merge --- src/Appwrite/Platform/Tasks/ScheduleFunctions.php | 6 +++--- src/Appwrite/Platform/Workers/Deletes.php | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php index 649fdb333a..19e068107a 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php @@ -75,9 +75,9 @@ class ScheduleFunctions extends ScheduleBase $delayedExecutions[$delay][] = ['key' => $key, 'nextDate' => $nextDate]; } - foreach ($delayedExecutions as $delay => $scheduleKeys) { - \go(function () use ($delay, $scheduleKeys, $pools, $dbForPlatform) { - \Co::sleep($delay); // in seconds + foreach ($delayedExecutions as $delay => $schedules) { + \go(function () use ($delay, $schedules, $pools, $dbForPlatform) { + \sleep($delay); // in seconds foreach ($schedules as $delayConfig) { $scheduleKey = $delayConfig['key']; diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 427772a6e0..d47ba9cb15 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -61,7 +61,7 @@ class Deletes extends Action ->inject('executionRetention') ->inject('auditRetention') ->inject('log') - ->callback([$this, 'action']); + ->callback($this->action(...)); } /** From 33fbab7e3d0128afd17a9bdec1f50da4d1377f90 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 14 May 2025 21:28:59 +1200 Subject: [PATCH 008/219] Fix missing capture --- src/Appwrite/Platform/Tasks/ScheduleMessages.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Tasks/ScheduleMessages.php b/src/Appwrite/Platform/Tasks/ScheduleMessages.php index 4f7dfab6a0..5e65f7a8a6 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleMessages.php +++ b/src/Appwrite/Platform/Tasks/ScheduleMessages.php @@ -40,7 +40,7 @@ class ScheduleMessages extends ScheduleBase continue; } - \go(function () use ($schedule, $pools, $dbForPlatform) { + \go(function () use ($schedule, $scheduledAt, $pools, $dbForPlatform) { $queueForMessaging = new Messaging($this->publisher); $this->updateProjectAccess($schedule['project'], $dbForPlatform); From 55236524e336b8108b94e6e8c0d332dce6db9735 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 14 May 2025 21:42:39 +1200 Subject: [PATCH 009/219] Fix merge --- src/Appwrite/Platform/Tasks/ScheduleExecutions.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php index 331928d265..99c84e829a 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php @@ -3,6 +3,7 @@ namespace Appwrite\Platform\Tasks; use Appwrite\Event\Func; +use Swoole\Coroutine as Co; use Utopia\Database\Database; use Utopia\Pools\Group; @@ -28,6 +29,7 @@ class ScheduleExecutions extends ScheduleBase protected function enqueueResources(Group $pools, Database $dbForPlatform, callable $getProjectDB): void { + $queueForFunctions = new Func($this->publisher); $intervalEnd = (new \DateTime())->modify('+' . self::ENQUEUE_TIMER . ' seconds'); foreach ($this->schedules as $schedule) { @@ -55,10 +57,8 @@ class ScheduleExecutions extends ScheduleBase $this->updateProjectAccess($schedule['project'], $dbForPlatform); - \go(function () use ($schedule, $delay, $data, $pools) { - \Co::sleep($delay); - - $queueForFunctions = new Func($this->publisher); + \go(function () use ($queueForFunctions, $schedule, $scheduledAt, $delay, $data) { + Co::sleep($delay); $queueForFunctions->setType('schedule') // Set functionId instead of function as we don't have $dbForProject From c4f1a682fd4e1002d117a96517ee9ad86b235f1d Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Thu, 15 May 2025 05:58:11 +0000 Subject: [PATCH 010/219] Fix: update messaging library --- composer.json | 2 +- composer.lock | 55 ++++++++++++++++++++++++++------------------------- 2 files changed, 29 insertions(+), 28 deletions(-) diff --git a/composer.json b/composer.json index 8b8bb811af..209c8bbb9e 100644 --- a/composer.json +++ b/composer.json @@ -59,7 +59,7 @@ "utopia-php/image": "0.8.*", "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.6.*", - "utopia-php/messaging": "0.17.*", + "utopia-php/messaging": "0.18.*", "utopia-php/migration": "0.9.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", diff --git a/composer.lock b/composer.lock index 5e86bfafd2..2882375481 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "2c14e20244a06f508dd67cda717aefeb", + "content-hash": "e6b10826abe8ee1a98acd0645366d550", "packages": [ { "name": "adhocore/jwt", @@ -709,16 +709,16 @@ }, { "name": "google/protobuf", - "version": "v4.30.2", + "version": "v4.31.0", "source": { "type": "git", "url": "https://github.com/protocolbuffers/protobuf-php.git", - "reference": "a4c4d8565b40b9f76debc9dfeb221412eacb8ced" + "reference": "d59e31ce4bf0e4b48728e90c4d880839edb5be07" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/a4c4d8565b40b9f76debc9dfeb221412eacb8ced", - "reference": "a4c4d8565b40b9f76debc9dfeb221412eacb8ced", + "url": "https://api.github.com/repos/protocolbuffers/protobuf-php/zipball/d59e31ce4bf0e4b48728e90c4d880839edb5be07", + "reference": "d59e31ce4bf0e4b48728e90c4d880839edb5be07", "shasum": "" }, "require": { @@ -747,9 +747,9 @@ "proto" ], "support": { - "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.30.2" + "source": "https://github.com/protocolbuffers/protobuf-php/tree/v4.31.0" }, - "time": "2025-03-26T18:01:50+00:00" + "time": "2025-05-14T16:17:23+00:00" }, { "name": "league/csv", @@ -3499,16 +3499,16 @@ }, { "name": "utopia-php/database", - "version": "0.69.1", + "version": "0.69.2", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "cc6538e05e25d930244ab938c966d32db0922e83" + "reference": "60591ab073bb80bb9843338754b679bb8169e4ed" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/cc6538e05e25d930244ab938c966d32db0922e83", - "reference": "cc6538e05e25d930244ab938c966d32db0922e83", + "url": "https://api.github.com/repos/utopia-php/database/zipball/60591ab073bb80bb9843338754b679bb8169e4ed", + "reference": "60591ab073bb80bb9843338754b679bb8169e4ed", "shasum": "" }, "require": { @@ -3549,9 +3549,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.69.1" + "source": "https://github.com/utopia-php/database/tree/0.69.2" }, - "time": "2025-05-13T12:00:31+00:00" + "time": "2025-05-14T07:51:44+00:00" }, { "name": "utopia-php/domains", @@ -3902,16 +3902,16 @@ }, { "name": "utopia-php/messaging", - "version": "0.17.0", + "version": "0.18.0", "source": { "type": "git", "url": "https://github.com/utopia-php/messaging.git", - "reference": "c51915d0e030db3a3add37f1561751d18b2d9a85" + "reference": "c151aa5d4d475c788ca15c210b5b2017e21c41d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/messaging/zipball/c51915d0e030db3a3add37f1561751d18b2d9a85", - "reference": "c51915d0e030db3a3add37f1561751d18b2d9a85", + "url": "https://api.github.com/repos/utopia-php/messaging/zipball/c151aa5d4d475c788ca15c210b5b2017e21c41d6", + "reference": "c151aa5d4d475c788ca15c210b5b2017e21c41d6", "shasum": "" }, "require": { @@ -3947,9 +3947,9 @@ ], "support": { "issues": "https://github.com/utopia-php/messaging/issues", - "source": "https://github.com/utopia-php/messaging/tree/0.17.0" + "source": "https://github.com/utopia-php/messaging/tree/0.18.0" }, - "time": "2025-05-12T16:14:08+00:00" + "time": "2025-05-15T05:00:03+00:00" }, { "name": "utopia-php/migration", @@ -4331,16 +4331,16 @@ }, { "name": "utopia-php/storage", - "version": "0.18.10", + "version": "0.18.11", "source": { "type": "git", "url": "https://github.com/utopia-php/storage.git", - "reference": "76f31158f4251abb207f7a9b16f7cb0bfdb3b39e" + "reference": "43bb91814e0ae9c70d2e4224fe0c9e85aa915c52" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/storage/zipball/76f31158f4251abb207f7a9b16f7cb0bfdb3b39e", - "reference": "76f31158f4251abb207f7a9b16f7cb0bfdb3b39e", + "url": "https://api.github.com/repos/utopia-php/storage/zipball/43bb91814e0ae9c70d2e4224fe0c9e85aa915c52", + "reference": "43bb91814e0ae9c70d2e4224fe0c9e85aa915c52", "shasum": "" }, "require": { @@ -4353,9 +4353,10 @@ "ext-xz": "*", "ext-zlib": "*", "ext-zstd": "*", - "php": ">=8.0", + "php": ">=8.1", "utopia-php/framework": "0.*.*", - "utopia-php/system": "0.*.*" + "utopia-php/system": "0.*.*", + "utopia-php/telemetry": "0.1.*" }, "require-dev": { "laravel/pint": "1.2.*", @@ -4382,9 +4383,9 @@ ], "support": { "issues": "https://github.com/utopia-php/storage/issues", - "source": "https://github.com/utopia-php/storage/tree/0.18.10" + "source": "https://github.com/utopia-php/storage/tree/0.18.11" }, - "time": "2025-03-03T10:47:54+00:00" + "time": "2025-05-14T16:00:30+00:00" }, { "name": "utopia-php/swoole", From 330c298c5874cfa83d04bf989934a98ef1796205 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Mon, 19 May 2025 12:10:42 +0530 Subject: [PATCH 011/219] add upsert route for a single document --- app/controllers/api/databases.php | 250 ++++++++++++++++++++++++++++++ 1 file changed, 250 insertions(+) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 62ddd41daa..20eb3075a5 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4202,6 +4202,256 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $response->dynamic($document, Response::MODEL_DOCUMENT); }); +App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId') + ->alias('/v1/database/collections/:collectionId/documents/:documentId') + ->desc('Create or update document') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].update') + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'document.update') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}/document/{response.$id}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', new Method( + namespace: 'databases', + group: 'documents', + name: 'updateDocument', + description: '/docs/references/databases/update-document.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DOCUMENT, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('documentId', '', new UID(), 'Document ID.') + ->param('data', [], new JSON(), 'Document data as JSON object. Include only attribute and value pairs to be updated.', true) + ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->inject('requestTimestamp') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->action(function (string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) { + $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array + + if (empty($data) && \is_null($permissions)) { + throw new Exception(Exception::DOCUMENT_MISSING_PAYLOAD); + } + + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + // Read permission should not be required for update + $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + if ($document->isEmpty()) { + throw new Exception(Exception::DOCUMENT_NOT_FOUND); + } + + // Map aggregate permissions into the multiple permissions they represent. + $permissions = Permission::aggregate($permissions, [ + Database::PERMISSION_READ, + Database::PERMISSION_UPDATE, + Database::PERMISSION_DELETE, + ]); + + // Users can only manage their own roles, API keys and Admin users can manage any + $roles = Authorization::getRoles(); + if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { + foreach (Database::PERMISSIONS as $type) { + foreach ($permissions as $permission) { + $permission = Permission::parse($permission); + if ($permission->getPermission() != $type) { + continue; + } + $role = (new Role( + $permission->getRole(), + $permission->getIdentifier(), + $permission->getDimension() + ))->toString(); + if (!Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); + } + } + } + } + + if (\is_null($permissions)) { + $permissions = $document->getPermissions() ?? []; + } + + $data['$id'] = $documentId; + $data['$permissions'] = $permissions; + $newDocument = new Document($data); + + $operations = 0; + + $setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database, &$operations) { + + $operations++; + + $relationships = \array_filter( + $collection->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $document->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + continue; + } + + $isList = \is_array($related) && \array_values($related) === $related; + + if ($isList) { + $relations = $related; + } else { + $relations = [$related]; + } + + $relatedCollectionId = $relationship->getAttribute('relatedCollection'); + $relatedCollection = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + ); + + foreach ($relations as &$relation) { + // If the relation is an array it can be either update or create a child document. + if ( + \is_array($relation) + && \array_values($relation) !== $relation + && !isset($relation['$id']) + ) { + $relation['$id'] = ID::unique(); + $relation = new Document($relation); + } + if ($relation instanceof Document) { + $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( + 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), + $relation->getId() + )); + $relation->removeAttribute('$collectionId'); + $relation->removeAttribute('$databaseId'); + // Attribute $collection is required for Utopia. + $relation->setAttribute( + '$collection', + 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId() + ); + + if ($oldDocument->isEmpty()) { + if (isset($relation['$id']) && $relation['$id'] === 'unique()') { + $relation['$id'] = ID::unique(); + } + } + $setCollection($relatedCollection, $relation); + } + } + + if ($isList) { + $document->setAttribute($relationship->getAttribute('key'), \array_values($relations)); + } else { + $document->setAttribute($relationship->getAttribute('key'), \reset($relations)); + } + } + }); + + $setCollection($collection, $newDocument); + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations)) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); + + $documents = [$documentId => $newDocument]; + $upserted = []; + try { + $modified = $dbForProject->createOrUpdateDocuments( + 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + $documents, + onNext: function (Document $document) use (&$upserted) { + $upserted[] = $document; + }, + ); + } catch (ConflictException) { + throw new Exception(Exception::DOCUMENT_UPDATE_CONFLICT); + } catch (DuplicateException) { + throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS); + } catch (RelationshipException $e) { + throw new Exception(Exception::RELATIONSHIP_VALUE_INVALID, $e->getMessage()); + } catch (StructureException $e) { + throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); + } + + $document = $upserted[0]; + // Add $collectionId and $databaseId for all documents + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { + $document->setAttribute('$databaseId', $database->getId()); + $document->setAttribute('$collectionId', $collection->getId()); + + $relationships = \array_filter( + $collection->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $document->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + continue; + } + if (!\is_array($related)) { + $related = [$related]; + } + + $relatedCollectionId = $relationship->getAttribute('relatedCollection'); + $relatedCollection = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + ); + + foreach ($related as $relation) { + if ($relation instanceof Document) { + $processDocument($relatedCollection, $relation); + } + } + } + }; + + $processDocument($collection, $document); + + $relationships = \array_map( + fn ($document) => $document->getAttribute('key'), + \array_filter( + $collection->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ) + ); + + $queueForEvents + ->setParam('databaseId', $databaseId) + ->setParam('collectionId', $collection->getId()) + ->setParam('documentId', $document->getId()) + ->setContext('collection', $collection) + ->setContext('database', $database) + ->setPayload($response->getPayload(), sensitive: $relationships); + + $response->dynamic($document, Response::MODEL_DOCUMENT); + }); + App::patch('/v1/databases/:databaseId/collections/:collectionId/documents') ->desc('Update documents') ->groups(['api', 'database']) From 08478b8d397873861ba81ef34f4fa31a4033499c Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Mon, 19 May 2025 13:56:11 +0530 Subject: [PATCH 012/219] removed document existence check for the document id updated labels added tests for upserts --- app/controllers/api/databases.php | 14 +--- .../e2e/Services/Databases/DatabasesBase.php | 65 +++++++++++++++++++ 2 files changed, 67 insertions(+), 12 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 20eb3075a5..29571c13f0 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4204,7 +4204,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId') ->alias('/v1/database/collections/:collectionId/documents/:documentId') - ->desc('Create or update document') + ->desc('upsert document') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].update') ->label('scope', 'documents.write') @@ -4217,7 +4217,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->label('sdk', new Method( namespace: 'databases', group: 'documents', - name: 'updateDocument', + name: 'upsertDocument', description: '/docs/references/databases/update-document.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], responses: [ @@ -4258,12 +4258,6 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::COLLECTION_NOT_FOUND); } - // Read permission should not be required for update - $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); - if ($document->isEmpty()) { - throw new Exception(Exception::DOCUMENT_NOT_FOUND); - } - // Map aggregate permissions into the multiple permissions they represent. $permissions = Permission::aggregate($permissions, [ Database::PERMISSION_READ, @@ -4292,10 +4286,6 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen } } - if (\is_null($permissions)) { - $permissions = $document->getPermissions() ?? []; - } - $data['$id'] = $documentId; $data['$permissions'] = $permissions; $newDocument = new Document($data); diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 2b60dee856..c1a0aa6391 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -14,6 +14,8 @@ use Utopia\Database\Query; use Utopia\Database\Validator\Datetime as DatetimeValidator; use Utopia\Validator\JSON; +use function PHPUnit\Framework\assertEquals; + trait DatabasesBase { public function testCreateDatabase(): array @@ -1683,6 +1685,69 @@ trait DatabasesBase return $data; } + /** + * @depends testCreateIndexes + */ + public function testUpsertDocument(array $data): void + { + $databaseId = $data['databaseId']; + $documentId = ID::unique(); + $document = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'title' => 'Thor: Ragnarok', + 'releaseYear' => 2000 + ], + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + ]); + + $this->assertEquals(200, $document['headers']['status-code']); + $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('Thor: Ragnarok', $document['body']['title']); + + $document = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'title' => 'Thor: Love and Thunder', + 'releaseYear' => 2000 + ], + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + ]); + + $this->assertEquals(200, $document['headers']['status-code']); + $this->assertEquals('Thor: Love and Thunder', $document['body']['title']); + + $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('Thor: Love and Thunder', $document['body']['title']); + + $document = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + + } + /** * @depends testCreateDocument */ From 1de778443f916c1388d802cfdaf7c510f6428c5f Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Mon, 19 May 2025 14:30:29 +0530 Subject: [PATCH 013/219] resolved comments for the api --- app/controllers/api/databases.php | 8 ++++---- docs/references/databases/upsert-document.md | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 docs/references/databases/upsert-document.md diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 29571c13f0..84c6e69113 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4204,12 +4204,12 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId') ->alias('/v1/database/collections/:collectionId/documents/:documentId') - ->desc('upsert document') + ->desc('Upsert document') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].update') ->label('scope', 'documents.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) - ->label('audits.event', 'document.update') + ->label('audits.event', 'document.upsert') ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}/document/{response.$id}') ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) @@ -4218,7 +4218,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen namespace: 'databases', group: 'documents', name: 'upsertDocument', - description: '/docs/references/databases/update-document.md', + description: '/docs/references/databases/upsert-document.md', auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], responses: [ new SDKResponse( @@ -4367,7 +4367,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations)) ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); - $documents = [$documentId => $newDocument]; + $documents = [$newDocument]; $upserted = []; try { $modified = $dbForProject->createOrUpdateDocuments( diff --git a/docs/references/databases/upsert-document.md b/docs/references/databases/upsert-document.md new file mode 100644 index 0000000000..a67694cfa6 --- /dev/null +++ b/docs/references/databases/upsert-document.md @@ -0,0 +1 @@ +Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection) API or directly from your database console. \ No newline at end of file From 256aa684a27e00c2122a1457128d248f6d53cb48 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Mon, 19 May 2025 15:59:38 +0530 Subject: [PATCH 014/219] updated tests --- app/controllers/api/databases.php | 5 +- .../e2e/Services/Databases/DatabasesBase.php | 50 ++++++++++++++++++- 2 files changed, 51 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 84c6e69113..d6794a5d0b 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4231,7 +4231,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') ->param('documentId', '', new UID(), 'Document ID.') - ->param('data', [], new JSON(), 'Document data as JSON object. Include only attribute and value pairs to be updated.', true) + ->param('data', [], new JSON(), 'Document data as JSON object. Include only attribute and value pairs to be updated.') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->inject('requestTimestamp') ->inject('response') @@ -4367,12 +4367,11 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations)) ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); - $documents = [$newDocument]; $upserted = []; try { $modified = $dbForProject->createOrUpdateDocuments( 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), - $documents, + [$newDocument], onNext: function (Document $document) use (&$upserted) { $upserted[] = $document; }, diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index c1a0aa6391..d8a26d2337 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -1708,6 +1708,7 @@ trait DatabasesBase ]); $this->assertEquals(200, $document['headers']['status-code']); + $this->assertCount(3, $document['body']['$permissions']); $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -1740,12 +1741,59 @@ trait DatabasesBase $this->assertEquals('Thor: Love and Thunder', $document['body']['title']); + // removing permission to read and delete + $document = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'title' => 'Thor: Love and Thunder', + 'releaseYear' => 2000 + ], + 'permissions' => [ + Permission::update(Role::users()) + ], + ]); + // shouldn't be able to read as no read permission + $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + switch ($this->getSide()) { + case 'client': + $this->assertEquals(404, $document['headers']['status-code']); + break; + case 'server': + $this->assertEquals(200, $document['headers']['status-code']); + break; + } + // shouldn't be able to delete as no delete permission $document = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - + $this->assertEquals(401, $document['headers']['status-code']); + // giving the delete permission + $document = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'title' => 'Thor: Love and Thunder', + 'releaseYear' => 2000 + ], + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()) + ], + ]); + $document = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(204, $document['headers']['status-code']); } /** From 559b6024bc5cb15a2e3d014960a7b62c6601285c Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Mon, 19 May 2025 16:00:38 +0530 Subject: [PATCH 015/219] linting --- tests/e2e/Services/Databases/DatabasesBase.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index d8a26d2337..a9ed01e97f 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -12,9 +12,6 @@ use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Query; use Utopia\Database\Validator\Datetime as DatetimeValidator; -use Utopia\Validator\JSON; - -use function PHPUnit\Framework\assertEquals; trait DatabasesBase { From 117717888572314130278089cb597ddee895b444 Mon Sep 17 00:00:00 2001 From: Fabian Gruber Date: Mon, 19 May 2025 12:40:11 +0200 Subject: [PATCH 016/219] fix: task coroutine hooks --- app/cli.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/cli.php b/app/cli.php index 9ade97e90c..0c91b3c34f 100644 --- a/app/cli.php +++ b/app/cli.php @@ -10,6 +10,7 @@ use Appwrite\Event\StatsUsage; use Appwrite\Platform\Appwrite; use Appwrite\Runtimes\Runtimes; use Executor\Executor; +use Swoole\Runtime; use Swoole\Timer; use Utopia\Cache\Adapter\Sharding; use Utopia\Cache\Cache; @@ -298,4 +299,6 @@ $cli $cli->shutdown()->action(fn () => Timer::clearAll()); +// Enable coroutines, but disable TCP hooks. These don't work until we use `\Utopia\Cache\Adapter\Pool` and `\Utopia\Database\Adapter\Pool`. +Runtime::enableCoroutine(SWOOLE_HOOK_ALL ^ SWOOLE_HOOK_TCP); run($cli->run(...)); From 14fe7a721725f5483def497a3757cf0f84399990 Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 19 May 2025 19:54:34 +0530 Subject: [PATCH 017/219] update: token desc. --- .../Modules/Tokens/Http/Tokens/Buckets/Files/Create.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php index 4b3b421696..360226eb25 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php @@ -48,7 +48,7 @@ class Create extends Action group: 'files', name: 'createFileToken', description: << Date: Mon, 19 May 2025 14:50:57 +0000 Subject: [PATCH 018/219] update 1.7.x and latest specs --- app/config/specs/open-api3-1.7.x-client.json | 23 +++++++++++++++ app/config/specs/open-api3-1.7.x-console.json | 24 ++++++++++++++-- app/config/specs/open-api3-1.7.x-server.json | 24 ++++++++++++++-- app/config/specs/open-api3-latest-client.json | 23 +++++++++++++++ .../specs/open-api3-latest-console.json | 24 ++++++++++++++-- app/config/specs/open-api3-latest-server.json | 24 ++++++++++++++-- app/config/specs/swagger2-1.7.x-client.json | 23 +++++++++++++++ app/config/specs/swagger2-1.7.x-console.json | 28 +++++++++++++++++-- app/config/specs/swagger2-1.7.x-server.json | 28 +++++++++++++++++-- app/config/specs/swagger2-latest-client.json | 23 +++++++++++++++ app/config/specs/swagger2-latest-console.json | 28 +++++++++++++++++-- app/config/specs/swagger2-latest-server.json | 28 +++++++++++++++++-- 12 files changed, 284 insertions(+), 16 deletions(-) diff --git a/app/config/specs/open-api3-1.7.x-client.json b/app/config/specs/open-api3-1.7.x-client.json index 92e64c7ba0..341eaa1eac 100644 --- a/app/config/specs/open-api3-1.7.x-client.json +++ b/app/config/specs/open-api3-1.7.x-client.json @@ -4490,6 +4490,29 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/components\/schemas\/documentList" + } + ], + "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { diff --git a/app/config/specs/open-api3-1.7.x-console.json b/app/config/specs/open-api3-1.7.x-console.json index 31d5016e85..c4f4f8e63a 100644 --- a/app/config/specs/open-api3-1.7.x-console.json +++ b/app/config/specs/open-api3-1.7.x-console.json @@ -9768,6 +9768,26 @@ "type": "string", "description": "Runtime specification for the function and builds.", "x-example": null + }, + "templateRepository": { + "type": "string", + "description": "Repository name of the template.", + "x-example": "" + }, + "templateOwner": { + "type": "string", + "description": "The name of the owner of the template.", + "x-example": "" + }, + "templateRootDirectory": { + "type": "string", + "description": "Path to function code in the template repo.", + "x-example": "" + }, + "templateVersion": { + "type": "string", + "description": "Version (tag) for the repo linked to the function template.", + "x-example": "" } }, "required": [ @@ -30695,7 +30715,7 @@ "tags": [ "tokens" ], - "description": "Create a new token. A token is linked to a file. Token can be passed as a header or request get parameter.", + "description": "Create a new token. A token is linked to a file. Token can be passed as a request parameter.", "responses": { "201": { "description": "ResourceToken", @@ -30716,7 +30736,7 @@ "type": "", "deprecated": false, "demo": "tokens\/create-file-token.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a header or request get parameter.", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request parameter.", "rate-limit": 60, "rate-time": 60, "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", diff --git a/app/config/specs/open-api3-1.7.x-server.json b/app/config/specs/open-api3-1.7.x-server.json index ac1c26d5b6..04742813d4 100644 --- a/app/config/specs/open-api3-1.7.x-server.json +++ b/app/config/specs/open-api3-1.7.x-server.json @@ -8843,6 +8843,26 @@ "type": "string", "description": "Runtime specification for the function and builds.", "x-example": null + }, + "templateRepository": { + "type": "string", + "description": "Repository name of the template.", + "x-example": "" + }, + "templateOwner": { + "type": "string", + "description": "The name of the owner of the template.", + "x-example": "" + }, + "templateRootDirectory": { + "type": "string", + "description": "Path to function code in the template repo.", + "x-example": "" + }, + "templateVersion": { + "type": "string", + "description": "Version (tag) for the repo linked to the function template.", + "x-example": "" } }, "required": [ @@ -21777,7 +21797,7 @@ "tags": [ "tokens" ], - "description": "Create a new token. A token is linked to a file. Token can be passed as a header or request get parameter.", + "description": "Create a new token. A token is linked to a file. Token can be passed as a request parameter.", "responses": { "201": { "description": "ResourceToken", @@ -21798,7 +21818,7 @@ "type": "", "deprecated": false, "demo": "tokens\/create-file-token.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a header or request get parameter.", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request parameter.", "rate-limit": 60, "rate-time": 60, "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index 92e64c7ba0..341eaa1eac 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -4490,6 +4490,29 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/components\/schemas\/documentList" + } + ], + "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 31d5016e85..c4f4f8e63a 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -9768,6 +9768,26 @@ "type": "string", "description": "Runtime specification for the function and builds.", "x-example": null + }, + "templateRepository": { + "type": "string", + "description": "Repository name of the template.", + "x-example": "" + }, + "templateOwner": { + "type": "string", + "description": "The name of the owner of the template.", + "x-example": "" + }, + "templateRootDirectory": { + "type": "string", + "description": "Path to function code in the template repo.", + "x-example": "" + }, + "templateVersion": { + "type": "string", + "description": "Version (tag) for the repo linked to the function template.", + "x-example": "" } }, "required": [ @@ -30695,7 +30715,7 @@ "tags": [ "tokens" ], - "description": "Create a new token. A token is linked to a file. Token can be passed as a header or request get parameter.", + "description": "Create a new token. A token is linked to a file. Token can be passed as a request parameter.", "responses": { "201": { "description": "ResourceToken", @@ -30716,7 +30736,7 @@ "type": "", "deprecated": false, "demo": "tokens\/create-file-token.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a header or request get parameter.", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request parameter.", "rate-limit": 60, "rate-time": 60, "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index ac1c26d5b6..04742813d4 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -8843,6 +8843,26 @@ "type": "string", "description": "Runtime specification for the function and builds.", "x-example": null + }, + "templateRepository": { + "type": "string", + "description": "Repository name of the template.", + "x-example": "" + }, + "templateOwner": { + "type": "string", + "description": "The name of the owner of the template.", + "x-example": "" + }, + "templateRootDirectory": { + "type": "string", + "description": "Path to function code in the template repo.", + "x-example": "" + }, + "templateVersion": { + "type": "string", + "description": "Version (tag) for the repo linked to the function template.", + "x-example": "" } }, "required": [ @@ -21777,7 +21797,7 @@ "tags": [ "tokens" ], - "description": "Create a new token. A token is linked to a file. Token can be passed as a header or request get parameter.", + "description": "Create a new token. A token is linked to a file. Token can be passed as a request parameter.", "responses": { "201": { "description": "ResourceToken", @@ -21798,7 +21818,7 @@ "type": "", "deprecated": false, "demo": "tokens\/create-file-token.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a header or request get parameter.", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request parameter.", "rate-limit": 60, "rate-time": 60, "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", diff --git a/app/config/specs/swagger2-1.7.x-client.json b/app/config/specs/swagger2-1.7.x-client.json index 9bfe261df1..e7a8ee5ee7 100644 --- a/app/config/specs/swagger2-1.7.x-client.json +++ b/app/config/specs/swagger2-1.7.x-client.json @@ -4630,6 +4630,29 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/definitions\/documentList" + } + ], + "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { diff --git a/app/config/specs/swagger2-1.7.x-console.json b/app/config/specs/swagger2-1.7.x-console.json index d7f8a4c9d1..6efa0843a4 100644 --- a/app/config/specs/swagger2-1.7.x-console.json +++ b/app/config/specs/swagger2-1.7.x-console.json @@ -9855,6 +9855,30 @@ "description": "Runtime specification for the function and builds.", "default": "s-1vcpu-512mb", "x-example": null + }, + "templateRepository": { + "type": "string", + "description": "Repository name of the template.", + "default": "", + "x-example": "" + }, + "templateOwner": { + "type": "string", + "description": "The name of the owner of the template.", + "default": "", + "x-example": "" + }, + "templateRootDirectory": { + "type": "string", + "description": "Path to function code in the template repo.", + "default": "", + "x-example": "" + }, + "templateVersion": { + "type": "string", + "description": "Version (tag) for the repo linked to the function template.", + "default": "", + "x-example": "" } }, "required": [ @@ -30922,7 +30946,7 @@ "tags": [ "tokens" ], - "description": "Create a new token. A token is linked to a file. Token can be passed as a header or request get parameter.", + "description": "Create a new token. A token is linked to a file. Token can be passed as a request parameter.", "responses": { "201": { "description": "ResourceToken", @@ -30939,7 +30963,7 @@ "type": "", "deprecated": false, "demo": "tokens\/create-file-token.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a header or request get parameter.", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request parameter.", "rate-limit": 60, "rate-time": 60, "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", diff --git a/app/config/specs/swagger2-1.7.x-server.json b/app/config/specs/swagger2-1.7.x-server.json index d2924041c0..d1fe406fff 100644 --- a/app/config/specs/swagger2-1.7.x-server.json +++ b/app/config/specs/swagger2-1.7.x-server.json @@ -8945,6 +8945,30 @@ "description": "Runtime specification for the function and builds.", "default": "s-1vcpu-512mb", "x-example": null + }, + "templateRepository": { + "type": "string", + "description": "Repository name of the template.", + "default": "", + "x-example": "" + }, + "templateOwner": { + "type": "string", + "description": "The name of the owner of the template.", + "default": "", + "x-example": "" + }, + "templateRootDirectory": { + "type": "string", + "description": "Path to function code in the template repo.", + "default": "", + "x-example": "" + }, + "templateVersion": { + "type": "string", + "description": "Version (tag) for the repo linked to the function template.", + "default": "", + "x-example": "" } }, "required": [ @@ -22062,7 +22086,7 @@ "tags": [ "tokens" ], - "description": "Create a new token. A token is linked to a file. Token can be passed as a header or request get parameter.", + "description": "Create a new token. A token is linked to a file. Token can be passed as a request parameter.", "responses": { "201": { "description": "ResourceToken", @@ -22079,7 +22103,7 @@ "type": "", "deprecated": false, "demo": "tokens\/create-file-token.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a header or request get parameter.", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request parameter.", "rate-limit": 60, "rate-time": 60, "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index 9bfe261df1..e7a8ee5ee7 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -4630,6 +4630,29 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/definitions\/documentList" + } + ], + "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index d7f8a4c9d1..6efa0843a4 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -9855,6 +9855,30 @@ "description": "Runtime specification for the function and builds.", "default": "s-1vcpu-512mb", "x-example": null + }, + "templateRepository": { + "type": "string", + "description": "Repository name of the template.", + "default": "", + "x-example": "" + }, + "templateOwner": { + "type": "string", + "description": "The name of the owner of the template.", + "default": "", + "x-example": "" + }, + "templateRootDirectory": { + "type": "string", + "description": "Path to function code in the template repo.", + "default": "", + "x-example": "" + }, + "templateVersion": { + "type": "string", + "description": "Version (tag) for the repo linked to the function template.", + "default": "", + "x-example": "" } }, "required": [ @@ -30922,7 +30946,7 @@ "tags": [ "tokens" ], - "description": "Create a new token. A token is linked to a file. Token can be passed as a header or request get parameter.", + "description": "Create a new token. A token is linked to a file. Token can be passed as a request parameter.", "responses": { "201": { "description": "ResourceToken", @@ -30939,7 +30963,7 @@ "type": "", "deprecated": false, "demo": "tokens\/create-file-token.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a header or request get parameter.", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request parameter.", "rate-limit": 60, "rate-time": 60, "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index d2924041c0..d1fe406fff 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -8945,6 +8945,30 @@ "description": "Runtime specification for the function and builds.", "default": "s-1vcpu-512mb", "x-example": null + }, + "templateRepository": { + "type": "string", + "description": "Repository name of the template.", + "default": "", + "x-example": "" + }, + "templateOwner": { + "type": "string", + "description": "The name of the owner of the template.", + "default": "", + "x-example": "" + }, + "templateRootDirectory": { + "type": "string", + "description": "Path to function code in the template repo.", + "default": "", + "x-example": "" + }, + "templateVersion": { + "type": "string", + "description": "Version (tag) for the repo linked to the function template.", + "default": "", + "x-example": "" } }, "required": [ @@ -22062,7 +22086,7 @@ "tags": [ "tokens" ], - "description": "Create a new token. A token is linked to a file. Token can be passed as a header or request get parameter.", + "description": "Create a new token. A token is linked to a file. Token can be passed as a request parameter.", "responses": { "201": { "description": "ResourceToken", @@ -22079,7 +22103,7 @@ "type": "", "deprecated": false, "demo": "tokens\/create-file-token.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a header or request get parameter.", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request parameter.", "rate-limit": 60, "rate-time": 60, "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", From 12bb74a58d2a439b5d2ac0528dcac4f4e1827c56 Mon Sep 17 00:00:00 2001 From: Aditya Oberai Date: Tue, 20 May 2025 00:11:03 +0530 Subject: [PATCH 019/219] Update src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matej Bačo --- .../Modules/Tokens/Http/Tokens/Buckets/Files/Create.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php index 360226eb25..fb96849ed2 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php @@ -48,7 +48,7 @@ class Create extends Action group: 'files', name: 'createFileToken', description: << Date: Mon, 19 May 2025 18:44:07 +0000 Subject: [PATCH 020/219] update specs --- app/config/specs/open-api3-1.7.x-console.json | 4 ++-- app/config/specs/open-api3-1.7.x-server.json | 4 ++-- app/config/specs/open-api3-latest-console.json | 4 ++-- app/config/specs/open-api3-latest-server.json | 4 ++-- app/config/specs/swagger2-1.7.x-console.json | 4 ++-- app/config/specs/swagger2-1.7.x-server.json | 4 ++-- app/config/specs/swagger2-latest-console.json | 4 ++-- app/config/specs/swagger2-latest-server.json | 4 ++-- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/app/config/specs/open-api3-1.7.x-console.json b/app/config/specs/open-api3-1.7.x-console.json index c4f4f8e63a..2cd5be9914 100644 --- a/app/config/specs/open-api3-1.7.x-console.json +++ b/app/config/specs/open-api3-1.7.x-console.json @@ -30715,7 +30715,7 @@ "tags": [ "tokens" ], - "description": "Create a new token. A token is linked to a file. Token can be passed as a request parameter.", + "description": "Create a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", "responses": { "201": { "description": "ResourceToken", @@ -30736,7 +30736,7 @@ "type": "", "deprecated": false, "demo": "tokens\/create-file-token.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request parameter.", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", "rate-limit": 60, "rate-time": 60, "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", diff --git a/app/config/specs/open-api3-1.7.x-server.json b/app/config/specs/open-api3-1.7.x-server.json index 04742813d4..36747a57db 100644 --- a/app/config/specs/open-api3-1.7.x-server.json +++ b/app/config/specs/open-api3-1.7.x-server.json @@ -21797,7 +21797,7 @@ "tags": [ "tokens" ], - "description": "Create a new token. A token is linked to a file. Token can be passed as a request parameter.", + "description": "Create a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", "responses": { "201": { "description": "ResourceToken", @@ -21818,7 +21818,7 @@ "type": "", "deprecated": false, "demo": "tokens\/create-file-token.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request parameter.", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", "rate-limit": 60, "rate-time": 60, "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index c4f4f8e63a..2cd5be9914 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -30715,7 +30715,7 @@ "tags": [ "tokens" ], - "description": "Create a new token. A token is linked to a file. Token can be passed as a request parameter.", + "description": "Create a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", "responses": { "201": { "description": "ResourceToken", @@ -30736,7 +30736,7 @@ "type": "", "deprecated": false, "demo": "tokens\/create-file-token.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request parameter.", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", "rate-limit": 60, "rate-time": 60, "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 04742813d4..36747a57db 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -21797,7 +21797,7 @@ "tags": [ "tokens" ], - "description": "Create a new token. A token is linked to a file. Token can be passed as a request parameter.", + "description": "Create a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", "responses": { "201": { "description": "ResourceToken", @@ -21818,7 +21818,7 @@ "type": "", "deprecated": false, "demo": "tokens\/create-file-token.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request parameter.", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", "rate-limit": 60, "rate-time": 60, "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", diff --git a/app/config/specs/swagger2-1.7.x-console.json b/app/config/specs/swagger2-1.7.x-console.json index 6efa0843a4..198f874730 100644 --- a/app/config/specs/swagger2-1.7.x-console.json +++ b/app/config/specs/swagger2-1.7.x-console.json @@ -30946,7 +30946,7 @@ "tags": [ "tokens" ], - "description": "Create a new token. A token is linked to a file. Token can be passed as a request parameter.", + "description": "Create a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", "responses": { "201": { "description": "ResourceToken", @@ -30963,7 +30963,7 @@ "type": "", "deprecated": false, "demo": "tokens\/create-file-token.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request parameter.", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", "rate-limit": 60, "rate-time": 60, "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", diff --git a/app/config/specs/swagger2-1.7.x-server.json b/app/config/specs/swagger2-1.7.x-server.json index d1fe406fff..60943ea807 100644 --- a/app/config/specs/swagger2-1.7.x-server.json +++ b/app/config/specs/swagger2-1.7.x-server.json @@ -22086,7 +22086,7 @@ "tags": [ "tokens" ], - "description": "Create a new token. A token is linked to a file. Token can be passed as a request parameter.", + "description": "Create a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", "responses": { "201": { "description": "ResourceToken", @@ -22103,7 +22103,7 @@ "type": "", "deprecated": false, "demo": "tokens\/create-file-token.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request parameter.", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", "rate-limit": 60, "rate-time": 60, "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 6efa0843a4..198f874730 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -30946,7 +30946,7 @@ "tags": [ "tokens" ], - "description": "Create a new token. A token is linked to a file. Token can be passed as a request parameter.", + "description": "Create a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", "responses": { "201": { "description": "ResourceToken", @@ -30963,7 +30963,7 @@ "type": "", "deprecated": false, "demo": "tokens\/create-file-token.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request parameter.", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", "rate-limit": 60, "rate-time": 60, "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index d1fe406fff..60943ea807 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -22086,7 +22086,7 @@ "tags": [ "tokens" ], - "description": "Create a new token. A token is linked to a file. Token can be passed as a request parameter.", + "description": "Create a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", "responses": { "201": { "description": "ResourceToken", @@ -22103,7 +22103,7 @@ "type": "", "deprecated": false, "demo": "tokens\/create-file-token.md", - "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request parameter.", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", "rate-limit": 60, "rate-time": 60, "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", From d2b0048a7fdfd170c46798bf8a0d4826bd30a20e Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Mon, 19 May 2025 16:04:04 -0700 Subject: [PATCH 021/219] fix: add _APP_DOMAIN_SITES variables.php so the env is initialized Without this, API calls to Appwrite can result in rule_not_found errors. --- app/config/variables.php | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/app/config/variables.php b/app/config/variables.php index da41666845..2f9a5ab41a 100644 --- a/app/config/variables.php +++ b/app/config/variables.php @@ -106,6 +106,15 @@ return [ 'question' => '', 'filter' => '' ], + [ + 'name' => '_APP_DOMAIN_SITES', + 'description' => 'A domain to use for site preview URLs.', + 'introduction' => '', + 'default' => 'sites.localhost', + 'required' => false, + 'question' => '', + 'filter' => '' + ], [ 'name' => '_APP_DOMAIN_TARGET', 'description' => 'Deprecated since 1.7.0. A DNS A record hostname to serve as a CNAME target for your Appwrite custom domains. You can use the same value as used for the Appwrite \'_APP_DOMAIN\' variable. The default value is \'localhost\'.', From 53e790d886e6209bb9915af1a54c15c440f0b2fb Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Tue, 20 May 2025 10:54:09 +0530 Subject: [PATCH 022/219] changed uid to custom id to allow unique values as well --- app/controllers/api/databases.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index d6794a5d0b..15eef93160 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4228,9 +4228,9 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ], contentType: ContentType::JSON )) - ->param('databaseId', '', new UID(), 'Database ID.') - ->param('collectionId', '', new UID(), 'Collection ID.') - ->param('documentId', '', new UID(), 'Document ID.') + ->param('databaseId', '', new CustomId(), 'Database ID.') + ->param('collectionId', '', new CustomId(), 'Collection ID.') + ->param('documentId', '', new CustomId(), 'Document ID.') ->param('data', [], new JSON(), 'Document data as JSON object. Include only attribute and value pairs to be updated.') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->inject('requestTimestamp') From b5d31d1b76cbe3848909688186e224fabf78b538 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Tue, 20 May 2025 12:11:41 +0530 Subject: [PATCH 023/219] updated the upsert test for the relationship --- .../e2e/Services/Databases/DatabasesBase.php | 188 ++++++++++++++++++ 1 file changed, 188 insertions(+) diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index a9ed01e97f..e9de5ad418 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -1791,6 +1791,194 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(204, $document['headers']['status-code']); + + // relationship behaviour + $person = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => 'person-upsert', + 'name' => 'person', + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + Permission::create(Role::users()), + ], + 'documentSecurity' => true, + ]); + + $this->assertEquals(201, $person['headers']['status-code']); + + $library = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => 'library-upsert', + 'name' => 'library', + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::create(Role::users()), + Permission::delete(Role::users()), + ], + 'documentSecurity' => true, + ]); + + $this->assertEquals(201, $library['headers']['status-code']); + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/attributes/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'fullName', + 'size' => 255, + 'required' => false, + ]); + + sleep(1); // Wait for worker + + $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/attributes/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedCollectionId' => 'library-upsert', + 'type' => Database::RELATION_ONE_TO_ONE, + 'key' => 'library', + 'twoWay' => true, + 'onDelete' => Database::RELATION_MUTATE_CASCADE, + ]); + + sleep(1); // Wait for worker + + $libraryName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $library['body']['$id'] . '/attributes/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'libraryName', + 'size' => 255, + 'required' => true, + ]); + + sleep(1); // Wait for worker + + $this->assertEquals(202, $libraryName['headers']['status-code']); + + // upserting values + $documentId = ID::unique(); + $person1 = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents/'.$documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'library' => [ + '$id' => 'library1', + '$permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + 'libraryName' => 'Library 1', + ], + ], + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ] + ]); + + $this->assertEquals('Library 1', $person1['body']['library']['libraryName']); + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::select(['fullName', 'library.*'])->toString(), + Query::equal('library', ['library1'])->toString(), + ], + ]); + + $this->assertEquals(1, $documents['body']['total']); + $this->assertEquals('Library 1', $documents['body']['documents'][0]['library']['libraryName']); + + + $person1 = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents/'.$documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'library' => [ + '$id' => 'library1', + '$permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + 'libraryName' => 'Library 2', + ], + ], + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ] + ]); + + // data should get updated + $this->assertEquals('Library 2', $person1['body']['library']['libraryName']); + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::select(['fullName', 'library.*'])->toString(), + Query::equal('library', ['library1'])->toString(), + ], + ]); + + $this->assertEquals(1, $documents['body']['total']); + $this->assertEquals('Library 2', $documents['body']['documents'][0]['library']['libraryName']); + + + // data should get added + $person1 = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents/'.ID::unique(), array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'library' => [ + '$id' => 'library2', + '$permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + 'libraryName' => 'Library 2', + ], + ], + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ] + ]); + + $this->assertEquals('Library 2', $person1['body']['library']['libraryName']); + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::select(['fullName', 'library.*'])->toString() + ], + ]); + $this->assertEquals(2, $documents['body']['total']); } /** From 2a99bd4bda5ddb205b70cd29ceb671bcdb0e7702 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 20 May 2025 19:26:26 +1200 Subject: [PATCH 024/219] Fix migrating functions with no deployments --- src/Appwrite/Migration/Version/V22.php | 35 +++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/src/Appwrite/Migration/Version/V22.php b/src/Appwrite/Migration/Version/V22.php index e485fb5bd0..50d5bdbb85 100644 --- a/src/Appwrite/Migration/Version/V22.php +++ b/src/Appwrite/Migration/Version/V22.php @@ -348,9 +348,21 @@ class V22 extends Migration if ($deploymentResourceType === 'function') { $project = $this->dbForProject->getDocument('projects', $document->getAttribute('projectId')); + + if ($project->isEmpty()) { + Console::warning("Project \"{$document->getAttribute('projectId')}\" not found for rule \"{$document->getId()}\""); + break; + } + $dbForOwnerProject = ($this->getProjectDB)($project); $function = $dbForOwnerProject->getDocument('functions', $resourceId); - $deploymentId = $function->getAttribute('deployment', $function->getAttribute('deploymentId', $document->getAttribute('deploymentId'))); + + if ($function->isEmpty()) { + Console::warning("Function \"{$resourceId}\" not found for rule \"{$document->getId()}\""); + break; + } + + $deploymentId = $function->getAttribute('deployment', $function->getAttribute('deploymentId', $document->getAttribute('deploymentId', ''))); $deploymentInternalId = $function->getAttribute('deploymentInternalId', $document->getAttribute('deploymentInternalId', '')); $document @@ -386,12 +398,19 @@ class V22 extends Migration 5. Fill latestDeploymentCreatedAt with latestDeployment's "$createdAt" 6. Fill latestDeploymentStatus with latestDeployment's build's "status" */ - if ($document->getAttribute('deployment')) { - $document->setAttribute('deploymentId', $document->getAttribute('deployment', $document->getAttribute('deploymentId', ''))); + if (empty($document->getAttribute('deployment'))) { + break; } + $document->setAttribute('deploymentId', $document->getAttribute('deployment', $document->getAttribute('deploymentId', ''))); $deploymentId = $document->getAttribute('deploymentId'); $deployment = $this->dbForProject->getDocument('deployments', $deploymentId); + + if ($deployment->isEmpty()) { + Console::warning("Deployment \"{$deploymentId}\" not found for function \"{$document->getId()}\""); + break; + } + $document->setAttribute('deploymentCreatedAt', $deployment->getCreatedAt()); $latestDeployment = $this->dbForProject->findOne('deployments', [ @@ -400,8 +419,18 @@ class V22 extends Migration Query::equal('resourceType', ['functions']), ]); + if ($latestDeployment->isEmpty()) { + Console::warning("Latest deployment not found for function \"{$document->getId()}\""); + break; + } + $latestBuild = $this->dbForProject->getDocument('builds', $latestDeployment->getAttribute('buildId', '')); + if ($latestBuild->isEmpty()) { + Console::warning("Build \"{$latestDeployment->getAttribute('buildId')}\" not found for deployment \"{$latestDeployment->getId()}\""); + break; + } + $document ->setAttribute('latestDeploymentId', $latestDeployment->getId()) ->setAttribute('latestDeploymentInternalId', $latestDeployment->getInternalId()) From 149dfb965153d8f51126017e1f3a2456fb53241c Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 20 May 2025 20:07:11 +1200 Subject: [PATCH 025/219] Update lock --- composer.lock | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/composer.lock b/composer.lock index c52ecba812..432676ca3e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "24b02f9535e6a202fde735137f0ec900", + "content-hash": "63feb1a7cf4cfa2cc7fa0870236e61ea", "packages": [ { "name": "adhocore/jwt", @@ -3499,16 +3499,16 @@ }, { "name": "utopia-php/database", - "version": "0.69.2", + "version": "0.69.5", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "60591ab073bb80bb9843338754b679bb8169e4ed" + "reference": "4abe53609dfc23b2ea82884d12b149df6a8af2f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/60591ab073bb80bb9843338754b679bb8169e4ed", - "reference": "60591ab073bb80bb9843338754b679bb8169e4ed", + "url": "https://api.github.com/repos/utopia-php/database/zipball/4abe53609dfc23b2ea82884d12b149df6a8af2f5", + "reference": "4abe53609dfc23b2ea82884d12b149df6a8af2f5", "shasum": "" }, "require": { @@ -3549,9 +3549,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.69.2" + "source": "https://github.com/utopia-php/database/tree/0.69.5" }, - "time": "2025-05-14T07:51:44+00:00" + "time": "2025-05-17T08:01:51+00:00" }, { "name": "utopia-php/domains", @@ -3701,16 +3701,16 @@ }, { "name": "utopia-php/framework", - "version": "0.33.19", + "version": "0.33.20", "source": { "type": "git", "url": "https://github.com/utopia-php/http.git", - "reference": "64c7b7bb8a8595ffe875fa8d4b7705684dbf46c0" + "reference": "e1c7ab4e0b5b0a9a70256b1e00912e101e76a131" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/http/zipball/64c7b7bb8a8595ffe875fa8d4b7705684dbf46c0", - "reference": "64c7b7bb8a8595ffe875fa8d4b7705684dbf46c0", + "url": "https://api.github.com/repos/utopia-php/http/zipball/e1c7ab4e0b5b0a9a70256b1e00912e101e76a131", + "reference": "e1c7ab4e0b5b0a9a70256b1e00912e101e76a131", "shasum": "" }, "require": { @@ -3742,9 +3742,9 @@ ], "support": { "issues": "https://github.com/utopia-php/http/issues", - "source": "https://github.com/utopia-php/http/tree/0.33.19" + "source": "https://github.com/utopia-php/http/tree/0.33.20" }, - "time": "2025-03-06T11:37:49+00:00" + "time": "2025-05-18T23:51:21+00:00" }, { "name": "utopia-php/image", @@ -4059,16 +4059,16 @@ }, { "name": "utopia-php/platform", - "version": "0.7.5", + "version": "0.7.6", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "8febd7b6e0c0f2cbd2f4289447bcca97496e4aaf" + "reference": "6bc7fbb43ec2b7f9ee5bdef5d4b5e4a81860950b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/8febd7b6e0c0f2cbd2f4289447bcca97496e4aaf", - "reference": "8febd7b6e0c0f2cbd2f4289447bcca97496e4aaf", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/6bc7fbb43ec2b7f9ee5bdef5d4b5e4a81860950b", + "reference": "6bc7fbb43ec2b7f9ee5bdef5d4b5e4a81860950b", "shasum": "" }, "require": { @@ -4103,9 +4103,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.7.5" + "source": "https://github.com/utopia-php/platform/tree/0.7.6" }, - "time": "2025-04-17T12:20:16+00:00" + "time": "2025-05-18T20:31:24+00:00" }, { "name": "utopia-php/pools", @@ -4771,16 +4771,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.40.16", + "version": "0.40.17", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "f1f506da74033f0cb5a11e3dffcfd1ee8daf237d" + "reference": "7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/f1f506da74033f0cb5a11e3dffcfd1ee8daf237d", - "reference": "f1f506da74033f0cb5a11e3dffcfd1ee8daf237d", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de", + "reference": "7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de", "shasum": "" }, "require": { @@ -4816,9 +4816,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.40.16" + "source": "https://github.com/appwrite/sdk-generator/tree/0.40.17" }, - "time": "2025-05-09T12:06:09+00:00" + "time": "2025-05-16T15:10:54+00:00" }, { "name": "doctrine/annotations", From 80e842444bc1bf9dc2fe1c617d4bdb8e798ef701 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Tue, 20 May 2025 14:28:16 +0530 Subject: [PATCH 026/219] updated test for upsertion --- tests/e2e/Services/Databases/DatabasesBase.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index e9de5ad418..7c0060ecaa 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -1769,8 +1769,11 @@ trait DatabasesBase 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - - $this->assertEquals(401, $document['headers']['status-code']); + // simulating for the client + // the document should not be allowed to be deleted as needed downward + if ($this->getSide() === 'client') { + $this->assertEquals(401, $document['headers']['status-code']); + } // giving the delete permission $document = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ 'content-type' => 'application/json', From cb97679553e701c2704e2a27a609e148c707e220 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 20 May 2025 11:50:36 +0200 Subject: [PATCH 027/219] Specs, SDKs and Docs fixes (deprecated params) --- app/config/specs/open-api3-1.7.x-console.json | 20 ------------ app/config/specs/open-api3-1.7.x-server.json | 20 ------------ .../specs/open-api3-latest-console.json | 20 ------------ app/config/specs/open-api3-latest-server.json | 20 ------------ app/config/specs/swagger2-1.7.x-console.json | 24 -------------- app/config/specs/swagger2-1.7.x-server.json | 24 -------------- app/config/specs/swagger2-latest-console.json | 24 -------------- app/config/specs/swagger2-latest-server.json | 24 -------------- composer.lock | 12 +++---- .../java/databases/create-documents.md | 24 ++++++++++++++ .../kotlin/databases/create-documents.md | 15 +++++++++ .../examples/databases/create-documents.md | 14 +++++++++ .../examples/databases/create-documents.md | 13 ++++++++ .../examples/databases/create-documents.md | 18 +++++++++++ .../examples/databases/create-documents.md | 15 +++++++++ .../examples/databases/create-documents.md | 11 +++++++ .../examples/databases/create-documents.md | 15 +++++++++ .../account/create-anonymous-session.md | 1 + .../account/create-email-password-session.md | 3 ++ .../examples/account/create-email-token.md | 4 +++ .../examples/account/create-j-w-t.md | 1 + .../account/create-magic-u-r-l-token.md | 5 +++ .../account/create-mfa-authenticator.md | 2 ++ .../examples/account/create-mfa-challenge.md | 2 ++ .../account/create-mfa-recovery-codes.md | 1 + .../examples/account/create-o-auth2session.md | 5 +++ .../examples/account/create-o-auth2token.md | 5 +++ .../examples/account/create-phone-token.md | 3 ++ .../account/create-phone-verification.md | 1 + .../examples/account/create-push-target.md | 4 +++ .../examples/account/create-recovery.md | 3 ++ .../examples/account/create-session.md | 3 ++ .../examples/account/create-verification.md | 2 ++ .../console-cli/examples/account/create.md | 5 +++ .../examples/account/delete-identity.md | 2 ++ .../account/delete-mfa-authenticator.md | 2 ++ .../examples/account/delete-push-target.md | 2 ++ .../examples/account/delete-session.md | 2 ++ .../examples/account/delete-sessions.md | 1 + .../console-cli/examples/account/delete.md | 1 + .../account/get-mfa-recovery-codes.md | 1 + .../console-cli/examples/account/get-prefs.md | 1 + .../examples/account/get-session.md | 2 ++ .../1.7.x/console-cli/examples/account/get.md | 1 + .../examples/account/list-identities.md | 2 ++ .../console-cli/examples/account/list-logs.md | 2 ++ .../examples/account/list-mfa-factors.md | 1 + .../examples/account/list-sessions.md | 1 + .../examples/account/update-email.md | 3 ++ .../examples/account/update-m-f-a.md | 2 ++ .../account/update-magic-u-r-l-session.md | 3 ++ .../account/update-mfa-authenticator.md | 3 ++ .../examples/account/update-mfa-challenge.md | 3 ++ .../account/update-mfa-recovery-codes.md | 1 + .../examples/account/update-name.md | 2 ++ .../examples/account/update-password.md | 3 ++ .../examples/account/update-phone-session.md | 3 ++ .../account/update-phone-verification.md | 3 ++ .../examples/account/update-phone.md | 3 ++ .../examples/account/update-prefs.md | 2 ++ .../examples/account/update-push-target.md | 3 ++ .../examples/account/update-recovery.md | 4 +++ .../examples/account/update-session.md | 2 ++ .../examples/account/update-status.md | 1 + .../examples/account/update-verification.md | 3 ++ .../console-cli/examples/assistant/chat.md | 2 ++ .../examples/avatars/get-browser.md | 5 +++ .../examples/avatars/get-credit-card.md | 5 +++ .../examples/avatars/get-favicon.md | 2 ++ .../console-cli/examples/avatars/get-flag.md | 5 +++ .../console-cli/examples/avatars/get-image.md | 4 +++ .../examples/avatars/get-initials.md | 5 +++ .../console-cli/examples/avatars/get-q-r.md | 5 +++ .../examples/console/get-resource.md | 3 ++ .../console-cli/examples/console/variables.md | 1 + .../databases/create-boolean-attribute.md | 7 +++++ .../examples/databases/create-collection.md | 7 +++++ .../databases/create-datetime-attribute.md | 7 +++++ .../examples/databases/create-document.md | 6 ++++ .../examples/databases/create-documents.md | 4 +++ .../databases/create-email-attribute.md | 7 +++++ .../databases/create-enum-attribute.md | 8 +++++ .../databases/create-float-attribute.md | 9 ++++++ .../examples/databases/create-index.md | 8 +++++ .../databases/create-integer-attribute.md | 9 ++++++ .../examples/databases/create-ip-attribute.md | 7 +++++ .../create-relationship-attribute.md | 9 ++++++ .../databases/create-string-attribute.md | 9 ++++++ .../databases/create-url-attribute.md | 7 +++++ .../console-cli/examples/databases/create.md | 4 +++ .../examples/databases/delete-attribute.md | 4 +++ .../examples/databases/delete-collection.md | 3 ++ .../examples/databases/delete-document.md | 4 +++ .../examples/databases/delete-documents.md | 4 +++ .../examples/databases/delete-index.md | 4 +++ .../console-cli/examples/databases/delete.md | 2 ++ .../examples/databases/get-attribute.md | 4 +++ .../databases/get-collection-usage.md | 4 +++ .../examples/databases/get-collection.md | 3 ++ .../examples/databases/get-database-usage.md | 3 ++ .../examples/databases/get-document.md | 5 +++ .../examples/databases/get-index.md | 4 +++ .../examples/databases/get-usage.md | 2 ++ .../console-cli/examples/databases/get.md | 2 ++ .../examples/databases/list-attributes.md | 4 +++ .../databases/list-collection-logs.md | 4 +++ .../examples/databases/list-collections.md | 4 +++ .../examples/databases/list-document-logs.md | 5 +++ .../examples/databases/list-documents.md | 4 +++ .../examples/databases/list-indexes.md | 4 +++ .../examples/databases/list-logs.md | 3 ++ .../console-cli/examples/databases/list.md | 3 ++ .../databases/update-boolean-attribute.md | 7 +++++ .../examples/databases/update-collection.md | 7 +++++ .../databases/update-datetime-attribute.md | 7 +++++ .../examples/databases/update-document.md | 6 ++++ .../examples/databases/update-documents.md | 5 +++ .../databases/update-email-attribute.md | 7 +++++ .../databases/update-enum-attribute.md | 8 +++++ .../databases/update-float-attribute.md | 9 ++++++ .../databases/update-integer-attribute.md | 9 ++++++ .../examples/databases/update-ip-attribute.md | 7 +++++ .../update-relationship-attribute.md | 6 ++++ .../databases/update-string-attribute.md | 8 +++++ .../databases/update-url-attribute.md | 7 +++++ .../console-cli/examples/databases/update.md | 4 +++ .../examples/databases/upsert-documents.md | 4 +++ .../examples/functions/create-deployment.md | 6 ++++ .../functions/create-duplicate-deployment.md | 4 +++ .../examples/functions/create-execution.md | 8 +++++ .../functions/create-template-deployment.md | 7 +++++ .../examples/functions/create-variable.md | 5 +++ .../functions/create-vcs-deployment.md | 5 +++ .../console-cli/examples/functions/create.md | 19 ++++++++++++ .../examples/functions/delete-deployment.md | 3 ++ .../examples/functions/delete-execution.md | 3 ++ .../examples/functions/delete-variable.md | 3 ++ .../console-cli/examples/functions/delete.md | 2 ++ .../functions/get-deployment-download.md | 4 +++ .../examples/functions/get-deployment.md | 3 ++ .../examples/functions/get-execution.md | 3 ++ .../examples/functions/get-template.md | 2 ++ .../examples/functions/get-usage.md | 3 ++ .../examples/functions/get-variable.md | 3 ++ .../console-cli/examples/functions/get.md | 2 ++ .../examples/functions/list-deployments.md | 4 +++ .../examples/functions/list-executions.md | 3 ++ .../examples/functions/list-runtimes.md | 1 + .../examples/functions/list-specifications.md | 1 + .../examples/functions/list-templates.md | 5 +++ .../examples/functions/list-usage.md | 2 ++ .../examples/functions/list-variables.md | 2 ++ .../console-cli/examples/functions/list.md | 3 ++ .../functions/update-deployment-status.md | 3 ++ .../functions/update-function-deployment.md | 3 ++ .../examples/functions/update-variable.md | 6 ++++ .../console-cli/examples/functions/update.md | 19 ++++++++++++ .../console-cli/examples/graphql/mutation.md | 2 ++ .../console-cli/examples/graphql/query.md | 2 ++ .../examples/health/get-antivirus.md | 1 + .../console-cli/examples/health/get-cache.md | 1 + .../examples/health/get-certificate.md | 2 ++ .../console-cli/examples/health/get-d-b.md | 1 + .../examples/health/get-failed-jobs.md | 3 ++ .../examples/health/get-pub-sub.md | 1 + .../examples/health/get-queue-builds.md | 2 ++ .../examples/health/get-queue-certificates.md | 2 ++ .../examples/health/get-queue-databases.md | 3 ++ .../examples/health/get-queue-deletes.md | 2 ++ .../examples/health/get-queue-functions.md | 2 ++ .../examples/health/get-queue-logs.md | 2 ++ .../examples/health/get-queue-mails.md | 2 ++ .../examples/health/get-queue-messaging.md | 2 ++ .../examples/health/get-queue-migrations.md | 2 ++ .../health/get-queue-stats-resources.md | 2 ++ .../examples/health/get-queue-usage.md | 2 ++ .../examples/health/get-queue-webhooks.md | 2 ++ .../examples/health/get-storage-local.md | 1 + .../examples/health/get-storage.md | 1 + .../console-cli/examples/health/get-time.md | 1 + .../1.7.x/console-cli/examples/health/get.md | 1 + .../1.7.x/console-cli/examples/locale/get.md | 1 + .../console-cli/examples/locale/list-codes.md | 1 + .../examples/locale/list-continents.md | 1 + .../examples/locale/list-countries-e-u.md | 1 + .../examples/locale/list-countries-phones.md | 1 + .../examples/locale/list-countries.md | 1 + .../examples/locale/list-currencies.md | 1 + .../examples/locale/list-languages.md | 1 + .../messaging/create-apns-provider.md | 9 ++++++ .../examples/messaging/create-email.md | 13 ++++++++ .../examples/messaging/create-fcm-provider.md | 5 +++ .../messaging/create-mailgun-provider.md | 11 +++++++ .../messaging/create-msg91provider.md | 7 +++++ .../examples/messaging/create-push.md | 20 ++++++++++++ .../messaging/create-sendgrid-provider.md | 9 ++++++ .../examples/messaging/create-sms.md | 8 +++++ .../messaging/create-smtp-provider.md | 15 +++++++++ .../examples/messaging/create-subscriber.md | 4 +++ .../messaging/create-telesign-provider.md | 7 +++++ .../messaging/create-textmagic-provider.md | 7 +++++ .../examples/messaging/create-topic.md | 4 +++ .../messaging/create-twilio-provider.md | 7 +++++ .../messaging/create-vonage-provider.md | 7 +++++ .../examples/messaging/delete-provider.md | 2 ++ .../examples/messaging/delete-subscriber.md | 3 ++ .../examples/messaging/delete-topic.md | 2 ++ .../console-cli/examples/messaging/delete.md | 2 ++ .../examples/messaging/get-message.md | 2 ++ .../examples/messaging/get-provider.md | 2 ++ .../examples/messaging/get-subscriber.md | 3 ++ .../examples/messaging/get-topic.md | 2 ++ .../examples/messaging/list-message-logs.md | 3 ++ .../examples/messaging/list-messages.md | 3 ++ .../examples/messaging/list-provider-logs.md | 3 ++ .../examples/messaging/list-providers.md | 3 ++ .../messaging/list-subscriber-logs.md | 3 ++ .../examples/messaging/list-subscribers.md | 4 +++ .../examples/messaging/list-targets.md | 3 ++ .../examples/messaging/list-topic-logs.md | 3 ++ .../examples/messaging/list-topics.md | 3 ++ .../messaging/update-apns-provider.md | 9 ++++++ .../examples/messaging/update-email.md | 13 ++++++++ .../examples/messaging/update-fcm-provider.md | 5 +++ .../messaging/update-mailgun-provider.md | 11 +++++++ .../messaging/update-msg91provider.md | 7 +++++ .../examples/messaging/update-push.md | 20 ++++++++++++ .../messaging/update-sendgrid-provider.md | 9 ++++++ .../examples/messaging/update-sms.md | 8 +++++ .../messaging/update-smtp-provider.md | 15 +++++++++ .../messaging/update-telesign-provider.md | 7 +++++ .../messaging/update-textmagic-provider.md | 7 +++++ .../examples/messaging/update-topic.md | 4 +++ .../messaging/update-twilio-provider.md | 7 +++++ .../messaging/update-vonage-provider.md | 7 +++++ .../migrations/create-appwrite-migration.md | 5 +++ .../migrations/create-csv-migration.md | 4 +++ .../migrations/create-firebase-migration.md | 3 ++ .../migrations/create-n-host-migration.md | 9 ++++++ .../migrations/create-supabase-migration.md | 8 +++++ .../console-cli/examples/migrations/delete.md | 2 ++ .../migrations/get-appwrite-report.md | 5 +++ .../migrations/get-firebase-report.md | 3 ++ .../examples/migrations/get-n-host-report.md | 9 ++++++ .../migrations/get-supabase-report.md | 8 +++++ .../console-cli/examples/migrations/get.md | 2 ++ .../console-cli/examples/migrations/list.md | 3 ++ .../console-cli/examples/migrations/retry.md | 2 ++ .../examples/project/create-variable.md | 4 +++ .../examples/project/delete-variable.md | 2 ++ .../console-cli/examples/project/get-usage.md | 4 +++ .../examples/project/get-variable.md | 2 ++ .../examples/project/list-variables.md | 1 + .../examples/project/update-variable.md | 5 +++ .../examples/projects/create-dev-key.md | 4 +++ .../examples/projects/create-j-w-t.md | 4 +++ .../examples/projects/create-key.md | 5 +++ .../examples/projects/create-platform.md | 7 +++++ .../examples/projects/create-smtp-test.md | 11 +++++++ .../examples/projects/create-webhook.md | 9 ++++++ .../console-cli/examples/projects/create.md | 14 +++++++++ .../examples/projects/delete-dev-key.md | 3 ++ .../projects/delete-email-template.md | 4 +++ .../examples/projects/delete-key.md | 3 ++ .../examples/projects/delete-platform.md | 3 ++ .../examples/projects/delete-sms-template.md | 4 +++ .../examples/projects/delete-webhook.md | 3 ++ .../console-cli/examples/projects/delete.md | 2 ++ .../examples/projects/get-dev-key.md | 3 ++ .../examples/projects/get-email-template.md | 4 +++ .../console-cli/examples/projects/get-key.md | 3 ++ .../examples/projects/get-platform.md | 3 ++ .../examples/projects/get-sms-template.md | 4 +++ .../examples/projects/get-webhook.md | 3 ++ .../console-cli/examples/projects/get.md | 2 ++ .../examples/projects/list-dev-keys.md | 3 ++ .../examples/projects/list-keys.md | 2 ++ .../examples/projects/list-platforms.md | 2 ++ .../examples/projects/list-webhooks.md | 2 ++ .../console-cli/examples/projects/list.md | 3 ++ .../projects/update-api-status-all.md | 3 ++ .../examples/projects/update-api-status.md | 4 +++ .../examples/projects/update-auth-duration.md | 3 ++ .../examples/projects/update-auth-limit.md | 3 ++ .../update-auth-password-dictionary.md | 3 ++ .../projects/update-auth-password-history.md | 3 ++ .../projects/update-auth-sessions-limit.md | 3 ++ .../examples/projects/update-auth-status.md | 4 +++ .../examples/projects/update-dev-key.md | 5 +++ .../projects/update-email-template.md | 9 ++++++ .../examples/projects/update-key.md | 6 ++++ .../projects/update-memberships-privacy.md | 5 +++ .../examples/projects/update-mock-numbers.md | 3 ++ .../examples/projects/update-o-auth2.md | 6 ++++ .../projects/update-personal-data-check.md | 3 ++ .../examples/projects/update-platform.md | 7 +++++ .../projects/update-service-status-all.md | 3 ++ .../projects/update-service-status.md | 4 +++ .../projects/update-session-alerts.md | 3 ++ .../examples/projects/update-sms-template.md | 5 +++ .../examples/projects/update-smtp.md | 11 +++++++ .../examples/projects/update-team.md | 3 ++ .../projects/update-webhook-signature.md | 3 ++ .../examples/projects/update-webhook.md | 10 ++++++ .../console-cli/examples/projects/update.md | 12 +++++++ .../examples/proxy/create-a-p-i-rule.md | 2 ++ .../examples/proxy/create-function-rule.md | 4 +++ .../examples/proxy/create-redirect-rule.md | 4 +++ .../examples/proxy/create-site-rule.md | 4 +++ .../console-cli/examples/proxy/delete-rule.md | 2 ++ .../console-cli/examples/proxy/get-rule.md | 2 ++ .../console-cli/examples/proxy/list-rules.md | 3 ++ .../proxy/update-rule-verification.md | 2 ++ .../examples/sites/create-deployment.md | 7 +++++ .../sites/create-duplicate-deployment.md | 3 ++ .../sites/create-template-deployment.md | 7 +++++ .../examples/sites/create-variable.md | 5 +++ .../examples/sites/create-vcs-deployment.md | 5 +++ .../console-cli/examples/sites/create.md | 19 ++++++++++++ .../examples/sites/delete-deployment.md | 3 ++ .../console-cli/examples/sites/delete-log.md | 3 ++ .../examples/sites/delete-variable.md | 3 ++ .../console-cli/examples/sites/delete.md | 2 ++ .../examples/sites/get-deployment-download.md | 4 +++ .../examples/sites/get-deployment.md | 3 ++ .../console-cli/examples/sites/get-log.md | 3 ++ .../examples/sites/get-template.md | 2 ++ .../console-cli/examples/sites/get-usage.md | 3 ++ .../examples/sites/get-variable.md | 3 ++ .../1.7.x/console-cli/examples/sites/get.md | 2 ++ .../examples/sites/list-deployments.md | 4 +++ .../examples/sites/list-frameworks.md | 1 + .../console-cli/examples/sites/list-logs.md | 3 ++ .../examples/sites/list-specifications.md | 1 + .../examples/sites/list-templates.md | 5 +++ .../console-cli/examples/sites/list-usage.md | 2 ++ .../examples/sites/list-variables.md | 2 ++ .../1.7.x/console-cli/examples/sites/list.md | 3 ++ .../sites/update-deployment-status.md | 3 ++ .../examples/sites/update-site-deployment.md | 3 ++ .../examples/sites/update-variable.md | 6 ++++ .../console-cli/examples/sites/update.md | 19 ++++++++++++ .../examples/storage/create-bucket.md | 11 +++++++ .../examples/storage/create-file.md | 5 +++ .../examples/storage/delete-bucket.md | 2 ++ .../examples/storage/delete-file.md | 3 ++ .../examples/storage/get-bucket-usage.md | 3 ++ .../examples/storage/get-bucket.md | 2 ++ .../examples/storage/get-file-download.md | 4 +++ .../examples/storage/get-file-preview.md | 15 +++++++++ .../examples/storage/get-file-view.md | 4 +++ .../console-cli/examples/storage/get-file.md | 3 ++ .../console-cli/examples/storage/get-usage.md | 2 ++ .../examples/storage/list-buckets.md | 3 ++ .../examples/storage/list-files.md | 4 +++ .../examples/storage/update-bucket.md | 11 +++++++ .../examples/storage/update-file.md | 5 +++ .../examples/teams/create-membership.md | 8 +++++ .../console-cli/examples/teams/create.md | 4 +++ .../examples/teams/delete-membership.md | 3 ++ .../console-cli/examples/teams/delete.md | 2 ++ .../examples/teams/get-membership.md | 3 ++ .../console-cli/examples/teams/get-prefs.md | 2 ++ .../1.7.x/console-cli/examples/teams/get.md | 2 ++ .../console-cli/examples/teams/list-logs.md | 3 ++ .../examples/teams/list-memberships.md | 4 +++ .../1.7.x/console-cli/examples/teams/list.md | 3 ++ .../teams/update-membership-status.md | 5 +++ .../examples/teams/update-membership.md | 4 +++ .../console-cli/examples/teams/update-name.md | 3 ++ .../examples/teams/update-prefs.md | 3 ++ .../examples/tokens/create-file-token.md | 4 +++ .../console-cli/examples/tokens/delete.md | 2 ++ .../1.7.x/console-cli/examples/tokens/get.md | 2 ++ .../1.7.x/console-cli/examples/tokens/list.md | 4 +++ .../console-cli/examples/tokens/update.md | 3 ++ .../examples/users/create-argon2user.md | 5 +++ .../examples/users/create-bcrypt-user.md | 5 +++ .../examples/users/create-j-w-t.md | 4 +++ .../examples/users/create-m-d5user.md | 5 +++ .../users/create-mfa-recovery-codes.md | 2 ++ .../examples/users/create-p-h-pass-user.md | 5 +++ .../examples/users/create-s-h-a-user.md | 6 ++++ .../users/create-scrypt-modified-user.md | 8 +++++ .../examples/users/create-scrypt-user.md | 10 ++++++ .../examples/users/create-session.md | 2 ++ .../examples/users/create-target.md | 7 +++++ .../examples/users/create-token.md | 4 +++ .../console-cli/examples/users/create.md | 6 ++++ .../examples/users/delete-identity.md | 2 ++ .../users/delete-mfa-authenticator.md | 3 ++ .../examples/users/delete-session.md | 3 ++ .../examples/users/delete-sessions.md | 2 ++ .../examples/users/delete-target.md | 3 ++ .../console-cli/examples/users/delete.md | 2 ++ .../examples/users/get-mfa-recovery-codes.md | 2 ++ .../console-cli/examples/users/get-prefs.md | 2 ++ .../console-cli/examples/users/get-target.md | 3 ++ .../console-cli/examples/users/get-usage.md | 2 ++ .../1.7.x/console-cli/examples/users/get.md | 2 ++ .../examples/users/list-identities.md | 3 ++ .../console-cli/examples/users/list-logs.md | 3 ++ .../examples/users/list-memberships.md | 4 +++ .../examples/users/list-mfa-factors.md | 2 ++ .../examples/users/list-sessions.md | 2 ++ .../examples/users/list-targets.md | 3 ++ .../1.7.x/console-cli/examples/users/list.md | 3 ++ .../users/update-email-verification.md | 3 ++ .../examples/users/update-email.md | 3 ++ .../examples/users/update-labels.md | 3 ++ .../users/update-mfa-recovery-codes.md | 2 ++ .../console-cli/examples/users/update-mfa.md | 3 ++ .../console-cli/examples/users/update-name.md | 3 ++ .../examples/users/update-password.md | 3 ++ .../users/update-phone-verification.md | 3 ++ .../examples/users/update-phone.md | 3 ++ .../examples/users/update-prefs.md | 3 ++ .../examples/users/update-status.md | 3 ++ .../examples/users/update-target.md | 6 ++++ .../vcs/create-repository-detection.md | 5 +++ .../examples/vcs/create-repository.md | 4 +++ .../examples/vcs/delete-installation.md | 2 ++ .../examples/vcs/get-installation.md | 2 ++ .../examples/vcs/get-repository-contents.md | 4 +++ .../examples/vcs/get-repository.md | 3 ++ .../examples/vcs/list-installations.md | 3 ++ .../examples/vcs/list-repositories.md | 4 +++ .../examples/vcs/list-repository-branches.md | 3 ++ .../vcs/update-external-deployments.md | 4 +++ .../account/create-anonymous-session.md | 11 +++++++ .../account/create-email-password-session.md | 14 +++++++++ .../examples/account/create-email-token.md | 15 +++++++++ .../examples/account/create-j-w-t.md | 11 +++++++ .../account/create-magic-u-r-l-token.md | 16 ++++++++++ .../account/create-mfa-authenticator.md | 13 ++++++++ .../examples/account/create-mfa-challenge.md | 13 ++++++++ .../account/create-mfa-recovery-codes.md | 11 +++++++ .../examples/account/create-o-auth2session.md | 15 +++++++++ .../examples/account/create-o-auth2token.md | 15 +++++++++ .../examples/account/create-phone-token.md | 14 +++++++++ .../account/create-phone-verification.md | 11 +++++++ .../examples/account/create-push-target.md | 15 +++++++++ .../examples/account/create-recovery.md | 14 +++++++++ .../examples/account/create-session.md | 14 +++++++++ .../examples/account/create-verification.md | 13 ++++++++ .../console-web/examples/account/create.md | 16 ++++++++++ .../examples/account/delete-identity.md | 13 ++++++++ .../account/delete-mfa-authenticator.md | 13 ++++++++ .../examples/account/delete-push-target.md | 13 ++++++++ .../examples/account/delete-session.md | 13 ++++++++ .../examples/account/delete-sessions.md | 11 +++++++ .../console-web/examples/account/delete.md | 11 +++++++ .../account/get-mfa-recovery-codes.md | 11 +++++++ .../console-web/examples/account/get-prefs.md | 11 +++++++ .../examples/account/get-session.md | 13 ++++++++ .../1.7.x/console-web/examples/account/get.md | 11 +++++++ .../examples/account/list-identities.md | 13 ++++++++ .../console-web/examples/account/list-logs.md | 13 ++++++++ .../examples/account/list-mfa-factors.md | 11 +++++++ .../examples/account/list-sessions.md | 11 +++++++ .../examples/account/update-email.md | 14 +++++++++ .../examples/account/update-m-f-a.md | 13 ++++++++ .../account/update-magic-u-r-l-session.md | 14 +++++++++ .../account/update-mfa-authenticator.md | 14 +++++++++ .../examples/account/update-mfa-challenge.md | 14 +++++++++ .../account/update-mfa-recovery-codes.md | 11 +++++++ .../examples/account/update-name.md | 13 ++++++++ .../examples/account/update-password.md | 14 +++++++++ .../examples/account/update-phone-session.md | 14 +++++++++ .../account/update-phone-verification.md | 14 +++++++++ .../examples/account/update-phone.md | 14 +++++++++ .../examples/account/update-prefs.md | 13 ++++++++ .../examples/account/update-push-target.md | 14 +++++++++ .../examples/account/update-recovery.md | 15 +++++++++ .../examples/account/update-session.md | 13 ++++++++ .../examples/account/update-status.md | 11 +++++++ .../examples/account/update-verification.md | 14 +++++++++ .../console-web/examples/assistant/chat.md | 13 ++++++++ .../examples/avatars/get-browser.md | 16 ++++++++++ .../examples/avatars/get-credit-card.md | 16 ++++++++++ .../examples/avatars/get-favicon.md | 13 ++++++++ .../console-web/examples/avatars/get-flag.md | 16 ++++++++++ .../console-web/examples/avatars/get-image.md | 15 +++++++++ .../examples/avatars/get-initials.md | 16 ++++++++++ .../console-web/examples/avatars/get-q-r.md | 16 ++++++++++ .../examples/console/get-resource.md | 14 +++++++++ .../console-web/examples/console/variables.md | 11 +++++++ .../databases/create-boolean-attribute.md | 18 +++++++++++ .../examples/databases/create-collection.md | 18 +++++++++++ .../databases/create-datetime-attribute.md | 18 +++++++++++ .../examples/databases/create-document.md | 19 ++++++++++++ .../examples/databases/create-documents.md | 15 +++++++++ .../databases/create-email-attribute.md | 18 +++++++++++ .../databases/create-enum-attribute.md | 19 ++++++++++++ .../databases/create-float-attribute.md | 20 ++++++++++++ .../examples/databases/create-index.md | 19 ++++++++++++ .../databases/create-integer-attribute.md | 20 ++++++++++++ .../examples/databases/create-ip-attribute.md | 18 +++++++++++ .../create-relationship-attribute.md | 20 ++++++++++++ .../databases/create-string-attribute.md | 20 ++++++++++++ .../databases/create-url-attribute.md | 18 +++++++++++ .../console-web/examples/databases/create.md | 15 +++++++++ .../examples/databases/delete-attribute.md | 15 +++++++++ .../examples/databases/delete-collection.md | 14 +++++++++ .../examples/databases/delete-document.md | 15 +++++++++ .../examples/databases/delete-documents.md | 15 +++++++++ .../examples/databases/delete-index.md | 15 +++++++++ .../console-web/examples/databases/delete.md | 13 ++++++++ .../examples/databases/get-attribute.md | 15 +++++++++ .../databases/get-collection-usage.md | 15 +++++++++ .../examples/databases/get-collection.md | 14 +++++++++ .../examples/databases/get-database-usage.md | 14 +++++++++ .../examples/databases/get-document.md | 16 ++++++++++ .../examples/databases/get-index.md | 15 +++++++++ .../examples/databases/get-usage.md | 13 ++++++++ .../console-web/examples/databases/get.md | 13 ++++++++ .../examples/databases/list-attributes.md | 15 +++++++++ .../databases/list-collection-logs.md | 15 +++++++++ .../examples/databases/list-collections.md | 15 +++++++++ .../examples/databases/list-document-logs.md | 16 ++++++++++ .../examples/databases/list-documents.md | 15 +++++++++ .../examples/databases/list-indexes.md | 15 +++++++++ .../examples/databases/list-logs.md | 14 +++++++++ .../console-web/examples/databases/list.md | 14 +++++++++ .../databases/update-boolean-attribute.md | 18 +++++++++++ .../examples/databases/update-collection.md | 18 +++++++++++ .../databases/update-datetime-attribute.md | 18 +++++++++++ .../examples/databases/update-document.md | 17 ++++++++++ .../examples/databases/update-documents.md | 16 ++++++++++ .../databases/update-email-attribute.md | 18 +++++++++++ .../databases/update-enum-attribute.md | 19 ++++++++++++ .../databases/update-float-attribute.md | 20 ++++++++++++ .../databases/update-integer-attribute.md | 20 ++++++++++++ .../examples/databases/update-ip-attribute.md | 18 +++++++++++ .../update-relationship-attribute.md | 17 ++++++++++ .../databases/update-string-attribute.md | 19 ++++++++++++ .../databases/update-url-attribute.md | 18 +++++++++++ .../console-web/examples/databases/update.md | 15 +++++++++ .../examples/databases/upsert-documents.md | 15 +++++++++ .../examples/functions/create-deployment.md | 17 ++++++++++ .../functions/create-duplicate-deployment.md | 15 +++++++++ .../examples/functions/create-execution.md | 19 ++++++++++++ .../functions/create-template-deployment.md | 18 +++++++++++ .../examples/functions/create-variable.md | 16 ++++++++++ .../functions/create-vcs-deployment.md | 16 ++++++++++ .../console-web/examples/functions/create.md | 30 ++++++++++++++++++ .../examples/functions/delete-deployment.md | 14 +++++++++ .../examples/functions/delete-execution.md | 14 +++++++++ .../examples/functions/delete-variable.md | 14 +++++++++ .../console-web/examples/functions/delete.md | 13 ++++++++ .../functions/get-deployment-download.md | 15 +++++++++ .../examples/functions/get-deployment.md | 14 +++++++++ .../examples/functions/get-execution.md | 14 +++++++++ .../examples/functions/get-template.md | 13 ++++++++ .../examples/functions/get-usage.md | 14 +++++++++ .../examples/functions/get-variable.md | 14 +++++++++ .../console-web/examples/functions/get.md | 13 ++++++++ .../examples/functions/list-deployments.md | 15 +++++++++ .../examples/functions/list-executions.md | 14 +++++++++ .../examples/functions/list-runtimes.md | 11 +++++++ .../examples/functions/list-specifications.md | 11 +++++++ .../examples/functions/list-templates.md | 16 ++++++++++ .../examples/functions/list-usage.md | 13 ++++++++ .../examples/functions/list-variables.md | 13 ++++++++ .../console-web/examples/functions/list.md | 14 +++++++++ .../functions/update-deployment-status.md | 14 +++++++++ .../functions/update-function-deployment.md | 14 +++++++++ .../examples/functions/update-variable.md | 17 ++++++++++ .../console-web/examples/functions/update.md | 30 ++++++++++++++++++ .../console-web/examples/graphql/mutation.md | 13 ++++++++ .../console-web/examples/graphql/query.md | 13 ++++++++ .../examples/health/get-antivirus.md | 11 +++++++ .../console-web/examples/health/get-cache.md | 11 +++++++ .../examples/health/get-certificate.md | 13 ++++++++ .../console-web/examples/health/get-d-b.md | 11 +++++++ .../examples/health/get-failed-jobs.md | 14 +++++++++ .../examples/health/get-pub-sub.md | 11 +++++++ .../examples/health/get-queue-builds.md | 13 ++++++++ .../examples/health/get-queue-certificates.md | 13 ++++++++ .../examples/health/get-queue-databases.md | 14 +++++++++ .../examples/health/get-queue-deletes.md | 13 ++++++++ .../examples/health/get-queue-functions.md | 13 ++++++++ .../examples/health/get-queue-logs.md | 13 ++++++++ .../examples/health/get-queue-mails.md | 13 ++++++++ .../examples/health/get-queue-messaging.md | 13 ++++++++ .../examples/health/get-queue-migrations.md | 13 ++++++++ .../health/get-queue-stats-resources.md | 13 ++++++++ .../examples/health/get-queue-usage.md | 13 ++++++++ .../examples/health/get-queue-webhooks.md | 13 ++++++++ .../examples/health/get-storage-local.md | 11 +++++++ .../examples/health/get-storage.md | 11 +++++++ .../console-web/examples/health/get-time.md | 11 +++++++ .../1.7.x/console-web/examples/health/get.md | 11 +++++++ .../1.7.x/console-web/examples/locale/get.md | 11 +++++++ .../console-web/examples/locale/list-codes.md | 11 +++++++ .../examples/locale/list-continents.md | 11 +++++++ .../examples/locale/list-countries-e-u.md | 11 +++++++ .../examples/locale/list-countries-phones.md | 11 +++++++ .../examples/locale/list-countries.md | 11 +++++++ .../examples/locale/list-currencies.md | 11 +++++++ .../examples/locale/list-languages.md | 11 +++++++ .../messaging/create-apns-provider.md | 20 ++++++++++++ .../examples/messaging/create-email.md | 24 ++++++++++++++ .../examples/messaging/create-fcm-provider.md | 16 ++++++++++ .../messaging/create-mailgun-provider.md | 22 +++++++++++++ .../messaging/create-msg91provider.md | 18 +++++++++++ .../examples/messaging/create-push.md | 31 +++++++++++++++++++ .../messaging/create-sendgrid-provider.md | 20 ++++++++++++ .../examples/messaging/create-sms.md | 19 ++++++++++++ .../messaging/create-smtp-provider.md | 26 ++++++++++++++++ .../examples/messaging/create-subscriber.md | 15 +++++++++ .../messaging/create-telesign-provider.md | 18 +++++++++++ .../messaging/create-textmagic-provider.md | 18 +++++++++++ .../examples/messaging/create-topic.md | 15 +++++++++ .../messaging/create-twilio-provider.md | 18 +++++++++++ .../messaging/create-vonage-provider.md | 18 +++++++++++ .../examples/messaging/delete-provider.md | 13 ++++++++ .../examples/messaging/delete-subscriber.md | 14 +++++++++ .../examples/messaging/delete-topic.md | 13 ++++++++ .../console-web/examples/messaging/delete.md | 13 ++++++++ .../examples/messaging/get-message.md | 13 ++++++++ .../examples/messaging/get-provider.md | 13 ++++++++ .../examples/messaging/get-subscriber.md | 14 +++++++++ .../examples/messaging/get-topic.md | 13 ++++++++ .../examples/messaging/list-message-logs.md | 14 +++++++++ .../examples/messaging/list-messages.md | 14 +++++++++ .../examples/messaging/list-provider-logs.md | 14 +++++++++ .../examples/messaging/list-providers.md | 14 +++++++++ .../messaging/list-subscriber-logs.md | 14 +++++++++ .../examples/messaging/list-subscribers.md | 15 +++++++++ .../examples/messaging/list-targets.md | 14 +++++++++ .../examples/messaging/list-topic-logs.md | 14 +++++++++ .../examples/messaging/list-topics.md | 14 +++++++++ .../messaging/update-apns-provider.md | 20 ++++++++++++ .../examples/messaging/update-email.md | 24 ++++++++++++++ .../examples/messaging/update-fcm-provider.md | 16 ++++++++++ .../messaging/update-mailgun-provider.md | 22 +++++++++++++ .../messaging/update-msg91provider.md | 18 +++++++++++ .../examples/messaging/update-push.md | 31 +++++++++++++++++++ .../messaging/update-sendgrid-provider.md | 20 ++++++++++++ .../examples/messaging/update-sms.md | 19 ++++++++++++ .../messaging/update-smtp-provider.md | 26 ++++++++++++++++ .../messaging/update-telesign-provider.md | 18 +++++++++++ .../messaging/update-textmagic-provider.md | 18 +++++++++++ .../examples/messaging/update-topic.md | 15 +++++++++ .../messaging/update-twilio-provider.md | 18 +++++++++++ .../messaging/update-vonage-provider.md | 18 +++++++++++ .../migrations/create-appwrite-migration.md | 16 ++++++++++ .../migrations/create-csv-migration.md | 15 +++++++++ .../migrations/create-firebase-migration.md | 14 +++++++++ .../migrations/create-n-host-migration.md | 20 ++++++++++++ .../migrations/create-supabase-migration.md | 19 ++++++++++++ .../console-web/examples/migrations/delete.md | 13 ++++++++ .../migrations/get-appwrite-report.md | 16 ++++++++++ .../migrations/get-firebase-report.md | 14 +++++++++ .../examples/migrations/get-n-host-report.md | 20 ++++++++++++ .../migrations/get-supabase-report.md | 19 ++++++++++++ .../console-web/examples/migrations/get.md | 13 ++++++++ .../console-web/examples/migrations/list.md | 14 +++++++++ .../console-web/examples/migrations/retry.md | 13 ++++++++ .../examples/project/create-variable.md | 15 +++++++++ .../examples/project/delete-variable.md | 13 ++++++++ .../console-web/examples/project/get-usage.md | 15 +++++++++ .../examples/project/get-variable.md | 13 ++++++++ .../examples/project/list-variables.md | 11 +++++++ .../examples/project/update-variable.md | 16 ++++++++++ .../examples/projects/create-dev-key.md | 15 +++++++++ .../examples/projects/create-j-w-t.md | 15 +++++++++ .../examples/projects/create-key.md | 16 ++++++++++ .../examples/projects/create-platform.md | 18 +++++++++++ .../examples/projects/create-smtp-test.md | 22 +++++++++++++ .../examples/projects/create-webhook.md | 20 ++++++++++++ .../console-web/examples/projects/create.md | 25 +++++++++++++++ .../examples/projects/delete-dev-key.md | 14 +++++++++ .../projects/delete-email-template.md | 15 +++++++++ .../examples/projects/delete-key.md | 14 +++++++++ .../examples/projects/delete-platform.md | 14 +++++++++ .../examples/projects/delete-sms-template.md | 15 +++++++++ .../examples/projects/delete-webhook.md | 14 +++++++++ .../console-web/examples/projects/delete.md | 13 ++++++++ .../examples/projects/get-dev-key.md | 14 +++++++++ .../examples/projects/get-email-template.md | 15 +++++++++ .../console-web/examples/projects/get-key.md | 14 +++++++++ .../examples/projects/get-platform.md | 14 +++++++++ .../examples/projects/get-sms-template.md | 15 +++++++++ .../examples/projects/get-webhook.md | 14 +++++++++ .../console-web/examples/projects/get.md | 13 ++++++++ .../examples/projects/list-dev-keys.md | 14 +++++++++ .../examples/projects/list-keys.md | 13 ++++++++ .../examples/projects/list-platforms.md | 13 ++++++++ .../examples/projects/list-webhooks.md | 13 ++++++++ .../console-web/examples/projects/list.md | 14 +++++++++ .../projects/update-api-status-all.md | 14 +++++++++ .../examples/projects/update-api-status.md | 15 +++++++++ .../examples/projects/update-auth-duration.md | 14 +++++++++ .../examples/projects/update-auth-limit.md | 14 +++++++++ .../update-auth-password-dictionary.md | 14 +++++++++ .../projects/update-auth-password-history.md | 14 +++++++++ .../projects/update-auth-sessions-limit.md | 14 +++++++++ .../examples/projects/update-auth-status.md | 15 +++++++++ .../examples/projects/update-dev-key.md | 16 ++++++++++ .../projects/update-email-template.md | 20 ++++++++++++ .../examples/projects/update-key.md | 17 ++++++++++ .../projects/update-memberships-privacy.md | 16 ++++++++++ .../examples/projects/update-mock-numbers.md | 14 +++++++++ .../examples/projects/update-o-auth2.md | 17 ++++++++++ .../projects/update-personal-data-check.md | 14 +++++++++ .../examples/projects/update-platform.md | 18 +++++++++++ .../projects/update-service-status-all.md | 14 +++++++++ .../projects/update-service-status.md | 15 +++++++++ .../projects/update-session-alerts.md | 14 +++++++++ .../examples/projects/update-sms-template.md | 16 ++++++++++ .../examples/projects/update-smtp.md | 22 +++++++++++++ .../examples/projects/update-team.md | 14 +++++++++ .../projects/update-webhook-signature.md | 14 +++++++++ .../examples/projects/update-webhook.md | 21 +++++++++++++ .../console-web/examples/projects/update.md | 23 ++++++++++++++ .../examples/proxy/create-a-p-i-rule.md | 13 ++++++++ .../examples/proxy/create-function-rule.md | 15 +++++++++ .../examples/proxy/create-redirect-rule.md | 15 +++++++++ .../examples/proxy/create-site-rule.md | 15 +++++++++ .../console-web/examples/proxy/delete-rule.md | 13 ++++++++ .../console-web/examples/proxy/get-rule.md | 13 ++++++++ .../console-web/examples/proxy/list-rules.md | 14 +++++++++ .../proxy/update-rule-verification.md | 13 ++++++++ .../examples/sites/create-deployment.md | 18 +++++++++++ .../sites/create-duplicate-deployment.md | 14 +++++++++ .../sites/create-template-deployment.md | 18 +++++++++++ .../examples/sites/create-variable.md | 16 ++++++++++ .../examples/sites/create-vcs-deployment.md | 16 ++++++++++ .../console-web/examples/sites/create.md | 30 ++++++++++++++++++ .../examples/sites/delete-deployment.md | 14 +++++++++ .../console-web/examples/sites/delete-log.md | 14 +++++++++ .../examples/sites/delete-variable.md | 14 +++++++++ .../console-web/examples/sites/delete.md | 13 ++++++++ .../examples/sites/get-deployment-download.md | 15 +++++++++ .../examples/sites/get-deployment.md | 14 +++++++++ .../console-web/examples/sites/get-log.md | 14 +++++++++ .../examples/sites/get-template.md | 13 ++++++++ .../console-web/examples/sites/get-usage.md | 14 +++++++++ .../examples/sites/get-variable.md | 14 +++++++++ .../1.7.x/console-web/examples/sites/get.md | 13 ++++++++ .../examples/sites/list-deployments.md | 15 +++++++++ .../examples/sites/list-frameworks.md | 11 +++++++ .../console-web/examples/sites/list-logs.md | 14 +++++++++ .../examples/sites/list-specifications.md | 11 +++++++ .../examples/sites/list-templates.md | 16 ++++++++++ .../console-web/examples/sites/list-usage.md | 13 ++++++++ .../examples/sites/list-variables.md | 13 ++++++++ .../1.7.x/console-web/examples/sites/list.md | 14 +++++++++ .../sites/update-deployment-status.md | 14 +++++++++ .../examples/sites/update-site-deployment.md | 14 +++++++++ .../examples/sites/update-variable.md | 17 ++++++++++ .../console-web/examples/sites/update.md | 30 ++++++++++++++++++ .../examples/storage/create-bucket.md | 22 +++++++++++++ .../examples/storage/create-file.md | 16 ++++++++++ .../examples/storage/delete-bucket.md | 13 ++++++++ .../examples/storage/delete-file.md | 14 +++++++++ .../examples/storage/get-bucket-usage.md | 14 +++++++++ .../examples/storage/get-bucket.md | 13 ++++++++ .../examples/storage/get-file-download.md | 15 +++++++++ .../examples/storage/get-file-preview.md | 26 ++++++++++++++++ .../examples/storage/get-file-view.md | 15 +++++++++ .../console-web/examples/storage/get-file.md | 14 +++++++++ .../console-web/examples/storage/get-usage.md | 13 ++++++++ .../examples/storage/list-buckets.md | 14 +++++++++ .../examples/storage/list-files.md | 15 +++++++++ .../examples/storage/update-bucket.md | 22 +++++++++++++ .../examples/storage/update-file.md | 16 ++++++++++ .../examples/teams/create-membership.md | 19 ++++++++++++ .../console-web/examples/teams/create.md | 15 +++++++++ .../examples/teams/delete-membership.md | 14 +++++++++ .../console-web/examples/teams/delete.md | 13 ++++++++ .../examples/teams/get-membership.md | 14 +++++++++ .../console-web/examples/teams/get-prefs.md | 13 ++++++++ .../1.7.x/console-web/examples/teams/get.md | 13 ++++++++ .../console-web/examples/teams/list-logs.md | 14 +++++++++ .../examples/teams/list-memberships.md | 15 +++++++++ .../1.7.x/console-web/examples/teams/list.md | 14 +++++++++ .../teams/update-membership-status.md | 16 ++++++++++ .../examples/teams/update-membership.md | 15 +++++++++ .../console-web/examples/teams/update-name.md | 14 +++++++++ .../examples/teams/update-prefs.md | 14 +++++++++ .../examples/tokens/create-file-token.md | 15 +++++++++ .../console-web/examples/tokens/delete.md | 13 ++++++++ .../1.7.x/console-web/examples/tokens/get.md | 13 ++++++++ .../1.7.x/console-web/examples/tokens/list.md | 15 +++++++++ .../console-web/examples/tokens/update.md | 14 +++++++++ .../examples/users/create-argon2user.md | 16 ++++++++++ .../examples/users/create-bcrypt-user.md | 16 ++++++++++ .../examples/users/create-j-w-t.md | 15 +++++++++ .../examples/users/create-m-d5user.md | 16 ++++++++++ .../users/create-mfa-recovery-codes.md | 13 ++++++++ .../examples/users/create-p-h-pass-user.md | 16 ++++++++++ .../examples/users/create-s-h-a-user.md | 17 ++++++++++ .../users/create-scrypt-modified-user.md | 19 ++++++++++++ .../examples/users/create-scrypt-user.md | 21 +++++++++++++ .../examples/users/create-session.md | 13 ++++++++ .../examples/users/create-target.md | 18 +++++++++++ .../examples/users/create-token.md | 15 +++++++++ .../console-web/examples/users/create.md | 17 ++++++++++ .../examples/users/delete-identity.md | 13 ++++++++ .../users/delete-mfa-authenticator.md | 14 +++++++++ .../examples/users/delete-session.md | 14 +++++++++ .../examples/users/delete-sessions.md | 13 ++++++++ .../examples/users/delete-target.md | 14 +++++++++ .../console-web/examples/users/delete.md | 13 ++++++++ .../examples/users/get-mfa-recovery-codes.md | 13 ++++++++ .../console-web/examples/users/get-prefs.md | 13 ++++++++ .../console-web/examples/users/get-target.md | 14 +++++++++ .../console-web/examples/users/get-usage.md | 13 ++++++++ .../1.7.x/console-web/examples/users/get.md | 13 ++++++++ .../examples/users/list-identities.md | 14 +++++++++ .../console-web/examples/users/list-logs.md | 14 +++++++++ .../examples/users/list-memberships.md | 15 +++++++++ .../examples/users/list-mfa-factors.md | 13 ++++++++ .../examples/users/list-sessions.md | 13 ++++++++ .../examples/users/list-targets.md | 14 +++++++++ .../1.7.x/console-web/examples/users/list.md | 14 +++++++++ .../users/update-email-verification.md | 14 +++++++++ .../examples/users/update-email.md | 14 +++++++++ .../examples/users/update-labels.md | 14 +++++++++ .../users/update-mfa-recovery-codes.md | 13 ++++++++ .../console-web/examples/users/update-mfa.md | 14 +++++++++ .../console-web/examples/users/update-name.md | 14 +++++++++ .../examples/users/update-password.md | 14 +++++++++ .../users/update-phone-verification.md | 14 +++++++++ .../examples/users/update-phone.md | 14 +++++++++ .../examples/users/update-prefs.md | 14 +++++++++ .../examples/users/update-status.md | 14 +++++++++ .../examples/users/update-target.md | 17 ++++++++++ .../vcs/create-repository-detection.md | 16 ++++++++++ .../examples/vcs/create-repository.md | 15 +++++++++ .../examples/vcs/delete-installation.md | 13 ++++++++ .../examples/vcs/get-installation.md | 13 ++++++++ .../examples/vcs/get-repository-contents.md | 15 +++++++++ .../examples/vcs/get-repository.md | 14 +++++++++ .../examples/vcs/list-installations.md | 14 +++++++++ .../examples/vcs/list-repositories.md | 15 +++++++++ .../examples/vcs/list-repository-branches.md | 14 +++++++++ .../vcs/update-external-deployments.md | 15 +++++++++ src/Appwrite/Platform/Tasks/SDKs.php | 2 -- .../SDK/Specification/Format/OpenAPI3.php | 2 +- .../SDK/Specification/Format/Swagger2.php | 2 +- 844 files changed, 8090 insertions(+), 186 deletions(-) create mode 100644 docs/examples/1.7.x/client-android/java/databases/create-documents.md create mode 100644 docs/examples/1.7.x/client-android/kotlin/databases/create-documents.md create mode 100644 docs/examples/1.7.x/client-apple/examples/databases/create-documents.md create mode 100644 docs/examples/1.7.x/client-flutter/examples/databases/create-documents.md create mode 100644 docs/examples/1.7.x/client-graphql/examples/databases/create-documents.md create mode 100644 docs/examples/1.7.x/client-react-native/examples/databases/create-documents.md create mode 100644 docs/examples/1.7.x/client-rest/examples/databases/create-documents.md create mode 100644 docs/examples/1.7.x/client-web/examples/databases/create-documents.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/create-anonymous-session.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/create-email-password-session.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/create-email-token.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/create-j-w-t.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/create-magic-u-r-l-token.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/create-mfa-authenticator.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/create-mfa-challenge.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/create-mfa-recovery-codes.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/create-o-auth2session.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/create-o-auth2token.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/create-phone-token.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/create-phone-verification.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/create-push-target.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/create-recovery.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/create-session.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/create-verification.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/create.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/delete-identity.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/delete-mfa-authenticator.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/delete-push-target.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/delete-session.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/delete-sessions.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/delete.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/get-mfa-recovery-codes.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/get-prefs.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/get-session.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/get.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/list-identities.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/list-logs.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/list-mfa-factors.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/list-sessions.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/update-email.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/update-m-f-a.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/update-magic-u-r-l-session.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/update-mfa-authenticator.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/update-mfa-challenge.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/update-mfa-recovery-codes.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/update-name.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/update-password.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/update-phone-session.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/update-phone-verification.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/update-phone.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/update-prefs.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/update-push-target.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/update-recovery.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/update-session.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/update-status.md create mode 100644 docs/examples/1.7.x/console-cli/examples/account/update-verification.md create mode 100644 docs/examples/1.7.x/console-cli/examples/assistant/chat.md create mode 100644 docs/examples/1.7.x/console-cli/examples/avatars/get-browser.md create mode 100644 docs/examples/1.7.x/console-cli/examples/avatars/get-credit-card.md create mode 100644 docs/examples/1.7.x/console-cli/examples/avatars/get-favicon.md create mode 100644 docs/examples/1.7.x/console-cli/examples/avatars/get-flag.md create mode 100644 docs/examples/1.7.x/console-cli/examples/avatars/get-image.md create mode 100644 docs/examples/1.7.x/console-cli/examples/avatars/get-initials.md create mode 100644 docs/examples/1.7.x/console-cli/examples/avatars/get-q-r.md create mode 100644 docs/examples/1.7.x/console-cli/examples/console/get-resource.md create mode 100644 docs/examples/1.7.x/console-cli/examples/console/variables.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/create-boolean-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/create-collection.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/create-datetime-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/create-document.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/create-documents.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/create-email-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/create-enum-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/create-float-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/create-index.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/create-integer-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/create-ip-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/create-relationship-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/create-string-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/create-url-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/create.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/delete-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/delete-collection.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/delete-document.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/delete-documents.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/delete-index.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/delete.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/get-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/get-collection-usage.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/get-collection.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/get-database-usage.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/get-document.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/get-index.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/get-usage.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/get.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/list-attributes.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/list-collection-logs.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/list-collections.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/list-document-logs.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/list-documents.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/list-indexes.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/list-logs.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/list.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/update-boolean-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/update-collection.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/update-datetime-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/update-document.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/update-documents.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/update-email-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/update-enum-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/update-float-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/update-integer-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/update-ip-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/update-relationship-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/update-string-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/update-url-attribute.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/update.md create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/upsert-documents.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/create-deployment.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/create-duplicate-deployment.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/create-execution.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/create-template-deployment.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/create-variable.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/create-vcs-deployment.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/create.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/delete-deployment.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/delete-execution.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/delete-variable.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/delete.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/get-deployment-download.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/get-deployment.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/get-execution.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/get-template.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/get-usage.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/get-variable.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/get.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/list-deployments.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/list-executions.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/list-runtimes.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/list-specifications.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/list-templates.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/list-usage.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/list-variables.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/list.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/update-deployment-status.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/update-function-deployment.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/update-variable.md create mode 100644 docs/examples/1.7.x/console-cli/examples/functions/update.md create mode 100644 docs/examples/1.7.x/console-cli/examples/graphql/mutation.md create mode 100644 docs/examples/1.7.x/console-cli/examples/graphql/query.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-antivirus.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-cache.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-certificate.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-d-b.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-failed-jobs.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-pub-sub.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-queue-builds.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-queue-certificates.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-queue-databases.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-queue-deletes.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-queue-functions.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-queue-logs.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-queue-mails.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-queue-messaging.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-queue-migrations.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-queue-stats-resources.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-queue-usage.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-queue-webhooks.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-storage-local.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-storage.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get-time.md create mode 100644 docs/examples/1.7.x/console-cli/examples/health/get.md create mode 100644 docs/examples/1.7.x/console-cli/examples/locale/get.md create mode 100644 docs/examples/1.7.x/console-cli/examples/locale/list-codes.md create mode 100644 docs/examples/1.7.x/console-cli/examples/locale/list-continents.md create mode 100644 docs/examples/1.7.x/console-cli/examples/locale/list-countries-e-u.md create mode 100644 docs/examples/1.7.x/console-cli/examples/locale/list-countries-phones.md create mode 100644 docs/examples/1.7.x/console-cli/examples/locale/list-countries.md create mode 100644 docs/examples/1.7.x/console-cli/examples/locale/list-currencies.md create mode 100644 docs/examples/1.7.x/console-cli/examples/locale/list-languages.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/create-apns-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/create-email.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/create-fcm-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/create-mailgun-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/create-msg91provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/create-push.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/create-sendgrid-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/create-sms.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/create-smtp-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/create-subscriber.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/create-telesign-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/create-textmagic-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/create-topic.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/create-twilio-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/create-vonage-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/delete-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/delete-subscriber.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/delete-topic.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/delete.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/get-message.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/get-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/get-subscriber.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/get-topic.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/list-message-logs.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/list-messages.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/list-provider-logs.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/list-providers.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/list-subscriber-logs.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/list-subscribers.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/list-targets.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/list-topic-logs.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/list-topics.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/update-apns-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/update-email.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/update-fcm-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/update-mailgun-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/update-msg91provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/update-push.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/update-sendgrid-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/update-sms.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/update-smtp-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/update-telesign-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/update-textmagic-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/update-topic.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/update-twilio-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/messaging/update-vonage-provider.md create mode 100644 docs/examples/1.7.x/console-cli/examples/migrations/create-appwrite-migration.md create mode 100644 docs/examples/1.7.x/console-cli/examples/migrations/create-csv-migration.md create mode 100644 docs/examples/1.7.x/console-cli/examples/migrations/create-firebase-migration.md create mode 100644 docs/examples/1.7.x/console-cli/examples/migrations/create-n-host-migration.md create mode 100644 docs/examples/1.7.x/console-cli/examples/migrations/create-supabase-migration.md create mode 100644 docs/examples/1.7.x/console-cli/examples/migrations/delete.md create mode 100644 docs/examples/1.7.x/console-cli/examples/migrations/get-appwrite-report.md create mode 100644 docs/examples/1.7.x/console-cli/examples/migrations/get-firebase-report.md create mode 100644 docs/examples/1.7.x/console-cli/examples/migrations/get-n-host-report.md create mode 100644 docs/examples/1.7.x/console-cli/examples/migrations/get-supabase-report.md create mode 100644 docs/examples/1.7.x/console-cli/examples/migrations/get.md create mode 100644 docs/examples/1.7.x/console-cli/examples/migrations/list.md create mode 100644 docs/examples/1.7.x/console-cli/examples/migrations/retry.md create mode 100644 docs/examples/1.7.x/console-cli/examples/project/create-variable.md create mode 100644 docs/examples/1.7.x/console-cli/examples/project/delete-variable.md create mode 100644 docs/examples/1.7.x/console-cli/examples/project/get-usage.md create mode 100644 docs/examples/1.7.x/console-cli/examples/project/get-variable.md create mode 100644 docs/examples/1.7.x/console-cli/examples/project/list-variables.md create mode 100644 docs/examples/1.7.x/console-cli/examples/project/update-variable.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/create-dev-key.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/create-j-w-t.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/create-key.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/create-platform.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/create-smtp-test.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/create-webhook.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/create.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/delete-dev-key.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/delete-email-template.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/delete-key.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/delete-platform.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/delete-sms-template.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/delete-webhook.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/delete.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/get-dev-key.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/get-email-template.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/get-key.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/get-platform.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/get-sms-template.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/get-webhook.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/get.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/list-dev-keys.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/list-keys.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/list-platforms.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/list-webhooks.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/list.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-api-status-all.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-api-status.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-auth-duration.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-auth-limit.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-auth-password-dictionary.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-auth-password-history.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-auth-sessions-limit.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-auth-status.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-dev-key.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-email-template.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-key.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-memberships-privacy.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-mock-numbers.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-o-auth2.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-personal-data-check.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-platform.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-service-status-all.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-service-status.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-session-alerts.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-sms-template.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-smtp.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-team.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-webhook-signature.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update-webhook.md create mode 100644 docs/examples/1.7.x/console-cli/examples/projects/update.md create mode 100644 docs/examples/1.7.x/console-cli/examples/proxy/create-a-p-i-rule.md create mode 100644 docs/examples/1.7.x/console-cli/examples/proxy/create-function-rule.md create mode 100644 docs/examples/1.7.x/console-cli/examples/proxy/create-redirect-rule.md create mode 100644 docs/examples/1.7.x/console-cli/examples/proxy/create-site-rule.md create mode 100644 docs/examples/1.7.x/console-cli/examples/proxy/delete-rule.md create mode 100644 docs/examples/1.7.x/console-cli/examples/proxy/get-rule.md create mode 100644 docs/examples/1.7.x/console-cli/examples/proxy/list-rules.md create mode 100644 docs/examples/1.7.x/console-cli/examples/proxy/update-rule-verification.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/create-deployment.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/create-duplicate-deployment.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/create-template-deployment.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/create-variable.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/create-vcs-deployment.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/create.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/delete-deployment.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/delete-log.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/delete-variable.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/delete.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/get-deployment-download.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/get-deployment.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/get-log.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/get-template.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/get-usage.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/get-variable.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/get.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/list-deployments.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/list-frameworks.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/list-logs.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/list-specifications.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/list-templates.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/list-usage.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/list-variables.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/list.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/update-deployment-status.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/update-site-deployment.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/update-variable.md create mode 100644 docs/examples/1.7.x/console-cli/examples/sites/update.md create mode 100644 docs/examples/1.7.x/console-cli/examples/storage/create-bucket.md create mode 100644 docs/examples/1.7.x/console-cli/examples/storage/create-file.md create mode 100644 docs/examples/1.7.x/console-cli/examples/storage/delete-bucket.md create mode 100644 docs/examples/1.7.x/console-cli/examples/storage/delete-file.md create mode 100644 docs/examples/1.7.x/console-cli/examples/storage/get-bucket-usage.md create mode 100644 docs/examples/1.7.x/console-cli/examples/storage/get-bucket.md create mode 100644 docs/examples/1.7.x/console-cli/examples/storage/get-file-download.md create mode 100644 docs/examples/1.7.x/console-cli/examples/storage/get-file-preview.md create mode 100644 docs/examples/1.7.x/console-cli/examples/storage/get-file-view.md create mode 100644 docs/examples/1.7.x/console-cli/examples/storage/get-file.md create mode 100644 docs/examples/1.7.x/console-cli/examples/storage/get-usage.md create mode 100644 docs/examples/1.7.x/console-cli/examples/storage/list-buckets.md create mode 100644 docs/examples/1.7.x/console-cli/examples/storage/list-files.md create mode 100644 docs/examples/1.7.x/console-cli/examples/storage/update-bucket.md create mode 100644 docs/examples/1.7.x/console-cli/examples/storage/update-file.md create mode 100644 docs/examples/1.7.x/console-cli/examples/teams/create-membership.md create mode 100644 docs/examples/1.7.x/console-cli/examples/teams/create.md create mode 100644 docs/examples/1.7.x/console-cli/examples/teams/delete-membership.md create mode 100644 docs/examples/1.7.x/console-cli/examples/teams/delete.md create mode 100644 docs/examples/1.7.x/console-cli/examples/teams/get-membership.md create mode 100644 docs/examples/1.7.x/console-cli/examples/teams/get-prefs.md create mode 100644 docs/examples/1.7.x/console-cli/examples/teams/get.md create mode 100644 docs/examples/1.7.x/console-cli/examples/teams/list-logs.md create mode 100644 docs/examples/1.7.x/console-cli/examples/teams/list-memberships.md create mode 100644 docs/examples/1.7.x/console-cli/examples/teams/list.md create mode 100644 docs/examples/1.7.x/console-cli/examples/teams/update-membership-status.md create mode 100644 docs/examples/1.7.x/console-cli/examples/teams/update-membership.md create mode 100644 docs/examples/1.7.x/console-cli/examples/teams/update-name.md create mode 100644 docs/examples/1.7.x/console-cli/examples/teams/update-prefs.md create mode 100644 docs/examples/1.7.x/console-cli/examples/tokens/create-file-token.md create mode 100644 docs/examples/1.7.x/console-cli/examples/tokens/delete.md create mode 100644 docs/examples/1.7.x/console-cli/examples/tokens/get.md create mode 100644 docs/examples/1.7.x/console-cli/examples/tokens/list.md create mode 100644 docs/examples/1.7.x/console-cli/examples/tokens/update.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/create-argon2user.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/create-bcrypt-user.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/create-j-w-t.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/create-m-d5user.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/create-mfa-recovery-codes.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/create-p-h-pass-user.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/create-s-h-a-user.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/create-scrypt-modified-user.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/create-scrypt-user.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/create-session.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/create-target.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/create-token.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/create.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/delete-identity.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/delete-mfa-authenticator.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/delete-session.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/delete-sessions.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/delete-target.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/delete.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/get-mfa-recovery-codes.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/get-prefs.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/get-target.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/get-usage.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/get.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/list-identities.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/list-logs.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/list-memberships.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/list-mfa-factors.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/list-sessions.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/list-targets.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/list.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/update-email-verification.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/update-email.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/update-labels.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/update-mfa-recovery-codes.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/update-mfa.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/update-name.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/update-password.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/update-phone-verification.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/update-phone.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/update-prefs.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/update-status.md create mode 100644 docs/examples/1.7.x/console-cli/examples/users/update-target.md create mode 100644 docs/examples/1.7.x/console-cli/examples/vcs/create-repository-detection.md create mode 100644 docs/examples/1.7.x/console-cli/examples/vcs/create-repository.md create mode 100644 docs/examples/1.7.x/console-cli/examples/vcs/delete-installation.md create mode 100644 docs/examples/1.7.x/console-cli/examples/vcs/get-installation.md create mode 100644 docs/examples/1.7.x/console-cli/examples/vcs/get-repository-contents.md create mode 100644 docs/examples/1.7.x/console-cli/examples/vcs/get-repository.md create mode 100644 docs/examples/1.7.x/console-cli/examples/vcs/list-installations.md create mode 100644 docs/examples/1.7.x/console-cli/examples/vcs/list-repositories.md create mode 100644 docs/examples/1.7.x/console-cli/examples/vcs/list-repository-branches.md create mode 100644 docs/examples/1.7.x/console-cli/examples/vcs/update-external-deployments.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/create-anonymous-session.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/create-email-password-session.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/create-email-token.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/create-j-w-t.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/create-magic-u-r-l-token.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/create-mfa-authenticator.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/create-mfa-challenge.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/create-mfa-recovery-codes.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/create-o-auth2session.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/create-o-auth2token.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/create-phone-token.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/create-phone-verification.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/create-push-target.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/create-recovery.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/create-session.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/create-verification.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/create.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/delete-identity.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/delete-mfa-authenticator.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/delete-push-target.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/delete-session.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/delete-sessions.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/delete.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/get-mfa-recovery-codes.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/get-prefs.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/get-session.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/get.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/list-identities.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/list-logs.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/list-mfa-factors.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/list-sessions.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/update-email.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/update-m-f-a.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/update-magic-u-r-l-session.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/update-mfa-authenticator.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/update-mfa-challenge.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/update-mfa-recovery-codes.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/update-name.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/update-password.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/update-phone-session.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/update-phone-verification.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/update-phone.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/update-prefs.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/update-push-target.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/update-recovery.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/update-session.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/update-status.md create mode 100644 docs/examples/1.7.x/console-web/examples/account/update-verification.md create mode 100644 docs/examples/1.7.x/console-web/examples/assistant/chat.md create mode 100644 docs/examples/1.7.x/console-web/examples/avatars/get-browser.md create mode 100644 docs/examples/1.7.x/console-web/examples/avatars/get-credit-card.md create mode 100644 docs/examples/1.7.x/console-web/examples/avatars/get-favicon.md create mode 100644 docs/examples/1.7.x/console-web/examples/avatars/get-flag.md create mode 100644 docs/examples/1.7.x/console-web/examples/avatars/get-image.md create mode 100644 docs/examples/1.7.x/console-web/examples/avatars/get-initials.md create mode 100644 docs/examples/1.7.x/console-web/examples/avatars/get-q-r.md create mode 100644 docs/examples/1.7.x/console-web/examples/console/get-resource.md create mode 100644 docs/examples/1.7.x/console-web/examples/console/variables.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/create-boolean-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/create-collection.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/create-datetime-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/create-document.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/create-documents.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/create-email-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/create-enum-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/create-float-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/create-index.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/create-integer-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/create-ip-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/create-relationship-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/create-string-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/create-url-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/create.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/delete-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/delete-collection.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/delete-document.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/delete-documents.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/delete-index.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/delete.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/get-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/get-collection-usage.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/get-collection.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/get-database-usage.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/get-document.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/get-index.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/get-usage.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/get.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/list-attributes.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/list-collection-logs.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/list-collections.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/list-document-logs.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/list-documents.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/list-indexes.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/list-logs.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/list.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/update-boolean-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/update-collection.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/update-datetime-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/update-document.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/update-documents.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/update-email-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/update-enum-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/update-float-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/update-integer-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/update-ip-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/update-relationship-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/update-string-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/update-url-attribute.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/update.md create mode 100644 docs/examples/1.7.x/console-web/examples/databases/upsert-documents.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/create-deployment.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/create-duplicate-deployment.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/create-execution.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/create-template-deployment.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/create-variable.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/create-vcs-deployment.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/create.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/delete-deployment.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/delete-execution.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/delete-variable.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/delete.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/get-deployment-download.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/get-deployment.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/get-execution.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/get-template.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/get-usage.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/get-variable.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/get.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/list-deployments.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/list-executions.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/list-runtimes.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/list-specifications.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/list-templates.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/list-usage.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/list-variables.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/list.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/update-deployment-status.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/update-function-deployment.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/update-variable.md create mode 100644 docs/examples/1.7.x/console-web/examples/functions/update.md create mode 100644 docs/examples/1.7.x/console-web/examples/graphql/mutation.md create mode 100644 docs/examples/1.7.x/console-web/examples/graphql/query.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-antivirus.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-cache.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-certificate.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-d-b.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-failed-jobs.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-pub-sub.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-queue-builds.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-queue-certificates.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-queue-databases.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-queue-deletes.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-queue-functions.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-queue-logs.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-queue-mails.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-queue-messaging.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-queue-migrations.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-queue-stats-resources.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-queue-usage.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-queue-webhooks.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-storage-local.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-storage.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get-time.md create mode 100644 docs/examples/1.7.x/console-web/examples/health/get.md create mode 100644 docs/examples/1.7.x/console-web/examples/locale/get.md create mode 100644 docs/examples/1.7.x/console-web/examples/locale/list-codes.md create mode 100644 docs/examples/1.7.x/console-web/examples/locale/list-continents.md create mode 100644 docs/examples/1.7.x/console-web/examples/locale/list-countries-e-u.md create mode 100644 docs/examples/1.7.x/console-web/examples/locale/list-countries-phones.md create mode 100644 docs/examples/1.7.x/console-web/examples/locale/list-countries.md create mode 100644 docs/examples/1.7.x/console-web/examples/locale/list-currencies.md create mode 100644 docs/examples/1.7.x/console-web/examples/locale/list-languages.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/create-apns-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/create-email.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/create-fcm-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/create-mailgun-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/create-msg91provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/create-push.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/create-sendgrid-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/create-sms.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/create-smtp-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/create-subscriber.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/create-telesign-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/create-textmagic-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/create-topic.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/create-twilio-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/create-vonage-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/delete-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/delete-subscriber.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/delete-topic.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/delete.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/get-message.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/get-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/get-subscriber.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/get-topic.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/list-message-logs.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/list-messages.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/list-provider-logs.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/list-providers.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/list-subscriber-logs.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/list-subscribers.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/list-targets.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/list-topic-logs.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/list-topics.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/update-apns-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/update-email.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/update-fcm-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/update-mailgun-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/update-msg91provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/update-push.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/update-sendgrid-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/update-sms.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/update-smtp-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/update-telesign-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/update-textmagic-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/update-topic.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/update-twilio-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/messaging/update-vonage-provider.md create mode 100644 docs/examples/1.7.x/console-web/examples/migrations/create-appwrite-migration.md create mode 100644 docs/examples/1.7.x/console-web/examples/migrations/create-csv-migration.md create mode 100644 docs/examples/1.7.x/console-web/examples/migrations/create-firebase-migration.md create mode 100644 docs/examples/1.7.x/console-web/examples/migrations/create-n-host-migration.md create mode 100644 docs/examples/1.7.x/console-web/examples/migrations/create-supabase-migration.md create mode 100644 docs/examples/1.7.x/console-web/examples/migrations/delete.md create mode 100644 docs/examples/1.7.x/console-web/examples/migrations/get-appwrite-report.md create mode 100644 docs/examples/1.7.x/console-web/examples/migrations/get-firebase-report.md create mode 100644 docs/examples/1.7.x/console-web/examples/migrations/get-n-host-report.md create mode 100644 docs/examples/1.7.x/console-web/examples/migrations/get-supabase-report.md create mode 100644 docs/examples/1.7.x/console-web/examples/migrations/get.md create mode 100644 docs/examples/1.7.x/console-web/examples/migrations/list.md create mode 100644 docs/examples/1.7.x/console-web/examples/migrations/retry.md create mode 100644 docs/examples/1.7.x/console-web/examples/project/create-variable.md create mode 100644 docs/examples/1.7.x/console-web/examples/project/delete-variable.md create mode 100644 docs/examples/1.7.x/console-web/examples/project/get-usage.md create mode 100644 docs/examples/1.7.x/console-web/examples/project/get-variable.md create mode 100644 docs/examples/1.7.x/console-web/examples/project/list-variables.md create mode 100644 docs/examples/1.7.x/console-web/examples/project/update-variable.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/create-dev-key.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/create-j-w-t.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/create-key.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/create-platform.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/create-smtp-test.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/create-webhook.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/create.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/delete-dev-key.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/delete-email-template.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/delete-key.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/delete-platform.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/delete-sms-template.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/delete-webhook.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/delete.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/get-dev-key.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/get-email-template.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/get-key.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/get-platform.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/get-sms-template.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/get-webhook.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/get.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/list-dev-keys.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/list-keys.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/list-platforms.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/list-webhooks.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/list.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-api-status-all.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-api-status.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-auth-duration.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-auth-limit.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-auth-password-dictionary.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-auth-password-history.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-auth-sessions-limit.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-auth-status.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-dev-key.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-email-template.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-key.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-memberships-privacy.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-mock-numbers.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-o-auth2.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-personal-data-check.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-platform.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-service-status-all.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-service-status.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-session-alerts.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-sms-template.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-smtp.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-team.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-webhook-signature.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update-webhook.md create mode 100644 docs/examples/1.7.x/console-web/examples/projects/update.md create mode 100644 docs/examples/1.7.x/console-web/examples/proxy/create-a-p-i-rule.md create mode 100644 docs/examples/1.7.x/console-web/examples/proxy/create-function-rule.md create mode 100644 docs/examples/1.7.x/console-web/examples/proxy/create-redirect-rule.md create mode 100644 docs/examples/1.7.x/console-web/examples/proxy/create-site-rule.md create mode 100644 docs/examples/1.7.x/console-web/examples/proxy/delete-rule.md create mode 100644 docs/examples/1.7.x/console-web/examples/proxy/get-rule.md create mode 100644 docs/examples/1.7.x/console-web/examples/proxy/list-rules.md create mode 100644 docs/examples/1.7.x/console-web/examples/proxy/update-rule-verification.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/create-deployment.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/create-duplicate-deployment.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/create-template-deployment.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/create-variable.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/create-vcs-deployment.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/create.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/delete-deployment.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/delete-log.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/delete-variable.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/delete.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/get-deployment-download.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/get-deployment.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/get-log.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/get-template.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/get-usage.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/get-variable.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/get.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/list-deployments.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/list-frameworks.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/list-logs.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/list-specifications.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/list-templates.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/list-usage.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/list-variables.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/list.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/update-deployment-status.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/update-site-deployment.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/update-variable.md create mode 100644 docs/examples/1.7.x/console-web/examples/sites/update.md create mode 100644 docs/examples/1.7.x/console-web/examples/storage/create-bucket.md create mode 100644 docs/examples/1.7.x/console-web/examples/storage/create-file.md create mode 100644 docs/examples/1.7.x/console-web/examples/storage/delete-bucket.md create mode 100644 docs/examples/1.7.x/console-web/examples/storage/delete-file.md create mode 100644 docs/examples/1.7.x/console-web/examples/storage/get-bucket-usage.md create mode 100644 docs/examples/1.7.x/console-web/examples/storage/get-bucket.md create mode 100644 docs/examples/1.7.x/console-web/examples/storage/get-file-download.md create mode 100644 docs/examples/1.7.x/console-web/examples/storage/get-file-preview.md create mode 100644 docs/examples/1.7.x/console-web/examples/storage/get-file-view.md create mode 100644 docs/examples/1.7.x/console-web/examples/storage/get-file.md create mode 100644 docs/examples/1.7.x/console-web/examples/storage/get-usage.md create mode 100644 docs/examples/1.7.x/console-web/examples/storage/list-buckets.md create mode 100644 docs/examples/1.7.x/console-web/examples/storage/list-files.md create mode 100644 docs/examples/1.7.x/console-web/examples/storage/update-bucket.md create mode 100644 docs/examples/1.7.x/console-web/examples/storage/update-file.md create mode 100644 docs/examples/1.7.x/console-web/examples/teams/create-membership.md create mode 100644 docs/examples/1.7.x/console-web/examples/teams/create.md create mode 100644 docs/examples/1.7.x/console-web/examples/teams/delete-membership.md create mode 100644 docs/examples/1.7.x/console-web/examples/teams/delete.md create mode 100644 docs/examples/1.7.x/console-web/examples/teams/get-membership.md create mode 100644 docs/examples/1.7.x/console-web/examples/teams/get-prefs.md create mode 100644 docs/examples/1.7.x/console-web/examples/teams/get.md create mode 100644 docs/examples/1.7.x/console-web/examples/teams/list-logs.md create mode 100644 docs/examples/1.7.x/console-web/examples/teams/list-memberships.md create mode 100644 docs/examples/1.7.x/console-web/examples/teams/list.md create mode 100644 docs/examples/1.7.x/console-web/examples/teams/update-membership-status.md create mode 100644 docs/examples/1.7.x/console-web/examples/teams/update-membership.md create mode 100644 docs/examples/1.7.x/console-web/examples/teams/update-name.md create mode 100644 docs/examples/1.7.x/console-web/examples/teams/update-prefs.md create mode 100644 docs/examples/1.7.x/console-web/examples/tokens/create-file-token.md create mode 100644 docs/examples/1.7.x/console-web/examples/tokens/delete.md create mode 100644 docs/examples/1.7.x/console-web/examples/tokens/get.md create mode 100644 docs/examples/1.7.x/console-web/examples/tokens/list.md create mode 100644 docs/examples/1.7.x/console-web/examples/tokens/update.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/create-argon2user.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/create-bcrypt-user.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/create-j-w-t.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/create-m-d5user.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/create-mfa-recovery-codes.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/create-p-h-pass-user.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/create-s-h-a-user.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/create-scrypt-modified-user.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/create-scrypt-user.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/create-session.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/create-target.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/create-token.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/create.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/delete-identity.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/delete-mfa-authenticator.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/delete-session.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/delete-sessions.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/delete-target.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/delete.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/get-mfa-recovery-codes.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/get-prefs.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/get-target.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/get-usage.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/get.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/list-identities.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/list-logs.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/list-memberships.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/list-mfa-factors.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/list-sessions.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/list-targets.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/list.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/update-email-verification.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/update-email.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/update-labels.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/update-mfa-recovery-codes.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/update-mfa.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/update-name.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/update-password.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/update-phone-verification.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/update-phone.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/update-prefs.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/update-status.md create mode 100644 docs/examples/1.7.x/console-web/examples/users/update-target.md create mode 100644 docs/examples/1.7.x/console-web/examples/vcs/create-repository-detection.md create mode 100644 docs/examples/1.7.x/console-web/examples/vcs/create-repository.md create mode 100644 docs/examples/1.7.x/console-web/examples/vcs/delete-installation.md create mode 100644 docs/examples/1.7.x/console-web/examples/vcs/get-installation.md create mode 100644 docs/examples/1.7.x/console-web/examples/vcs/get-repository-contents.md create mode 100644 docs/examples/1.7.x/console-web/examples/vcs/get-repository.md create mode 100644 docs/examples/1.7.x/console-web/examples/vcs/list-installations.md create mode 100644 docs/examples/1.7.x/console-web/examples/vcs/list-repositories.md create mode 100644 docs/examples/1.7.x/console-web/examples/vcs/list-repository-branches.md create mode 100644 docs/examples/1.7.x/console-web/examples/vcs/update-external-deployments.md diff --git a/app/config/specs/open-api3-1.7.x-console.json b/app/config/specs/open-api3-1.7.x-console.json index 2cd5be9914..6c003e8283 100644 --- a/app/config/specs/open-api3-1.7.x-console.json +++ b/app/config/specs/open-api3-1.7.x-console.json @@ -9768,26 +9768,6 @@ "type": "string", "description": "Runtime specification for the function and builds.", "x-example": null - }, - "templateRepository": { - "type": "string", - "description": "Repository name of the template.", - "x-example": "" - }, - "templateOwner": { - "type": "string", - "description": "The name of the owner of the template.", - "x-example": "" - }, - "templateRootDirectory": { - "type": "string", - "description": "Path to function code in the template repo.", - "x-example": "" - }, - "templateVersion": { - "type": "string", - "description": "Version (tag) for the repo linked to the function template.", - "x-example": "" } }, "required": [ diff --git a/app/config/specs/open-api3-1.7.x-server.json b/app/config/specs/open-api3-1.7.x-server.json index 36747a57db..216ab3e21d 100644 --- a/app/config/specs/open-api3-1.7.x-server.json +++ b/app/config/specs/open-api3-1.7.x-server.json @@ -8843,26 +8843,6 @@ "type": "string", "description": "Runtime specification for the function and builds.", "x-example": null - }, - "templateRepository": { - "type": "string", - "description": "Repository name of the template.", - "x-example": "" - }, - "templateOwner": { - "type": "string", - "description": "The name of the owner of the template.", - "x-example": "" - }, - "templateRootDirectory": { - "type": "string", - "description": "Path to function code in the template repo.", - "x-example": "" - }, - "templateVersion": { - "type": "string", - "description": "Version (tag) for the repo linked to the function template.", - "x-example": "" } }, "required": [ diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 2cd5be9914..6c003e8283 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -9768,26 +9768,6 @@ "type": "string", "description": "Runtime specification for the function and builds.", "x-example": null - }, - "templateRepository": { - "type": "string", - "description": "Repository name of the template.", - "x-example": "" - }, - "templateOwner": { - "type": "string", - "description": "The name of the owner of the template.", - "x-example": "" - }, - "templateRootDirectory": { - "type": "string", - "description": "Path to function code in the template repo.", - "x-example": "" - }, - "templateVersion": { - "type": "string", - "description": "Version (tag) for the repo linked to the function template.", - "x-example": "" } }, "required": [ diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 36747a57db..216ab3e21d 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -8843,26 +8843,6 @@ "type": "string", "description": "Runtime specification for the function and builds.", "x-example": null - }, - "templateRepository": { - "type": "string", - "description": "Repository name of the template.", - "x-example": "" - }, - "templateOwner": { - "type": "string", - "description": "The name of the owner of the template.", - "x-example": "" - }, - "templateRootDirectory": { - "type": "string", - "description": "Path to function code in the template repo.", - "x-example": "" - }, - "templateVersion": { - "type": "string", - "description": "Version (tag) for the repo linked to the function template.", - "x-example": "" } }, "required": [ diff --git a/app/config/specs/swagger2-1.7.x-console.json b/app/config/specs/swagger2-1.7.x-console.json index 198f874730..3b92eceebd 100644 --- a/app/config/specs/swagger2-1.7.x-console.json +++ b/app/config/specs/swagger2-1.7.x-console.json @@ -9855,30 +9855,6 @@ "description": "Runtime specification for the function and builds.", "default": "s-1vcpu-512mb", "x-example": null - }, - "templateRepository": { - "type": "string", - "description": "Repository name of the template.", - "default": "", - "x-example": "" - }, - "templateOwner": { - "type": "string", - "description": "The name of the owner of the template.", - "default": "", - "x-example": "" - }, - "templateRootDirectory": { - "type": "string", - "description": "Path to function code in the template repo.", - "default": "", - "x-example": "" - }, - "templateVersion": { - "type": "string", - "description": "Version (tag) for the repo linked to the function template.", - "default": "", - "x-example": "" } }, "required": [ diff --git a/app/config/specs/swagger2-1.7.x-server.json b/app/config/specs/swagger2-1.7.x-server.json index 60943ea807..07e1107789 100644 --- a/app/config/specs/swagger2-1.7.x-server.json +++ b/app/config/specs/swagger2-1.7.x-server.json @@ -8945,30 +8945,6 @@ "description": "Runtime specification for the function and builds.", "default": "s-1vcpu-512mb", "x-example": null - }, - "templateRepository": { - "type": "string", - "description": "Repository name of the template.", - "default": "", - "x-example": "" - }, - "templateOwner": { - "type": "string", - "description": "The name of the owner of the template.", - "default": "", - "x-example": "" - }, - "templateRootDirectory": { - "type": "string", - "description": "Path to function code in the template repo.", - "default": "", - "x-example": "" - }, - "templateVersion": { - "type": "string", - "description": "Version (tag) for the repo linked to the function template.", - "default": "", - "x-example": "" } }, "required": [ diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 198f874730..3b92eceebd 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -9855,30 +9855,6 @@ "description": "Runtime specification for the function and builds.", "default": "s-1vcpu-512mb", "x-example": null - }, - "templateRepository": { - "type": "string", - "description": "Repository name of the template.", - "default": "", - "x-example": "" - }, - "templateOwner": { - "type": "string", - "description": "The name of the owner of the template.", - "default": "", - "x-example": "" - }, - "templateRootDirectory": { - "type": "string", - "description": "Path to function code in the template repo.", - "default": "", - "x-example": "" - }, - "templateVersion": { - "type": "string", - "description": "Version (tag) for the repo linked to the function template.", - "default": "", - "x-example": "" } }, "required": [ diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 60943ea807..07e1107789 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -8945,30 +8945,6 @@ "description": "Runtime specification for the function and builds.", "default": "s-1vcpu-512mb", "x-example": null - }, - "templateRepository": { - "type": "string", - "description": "Repository name of the template.", - "default": "", - "x-example": "" - }, - "templateOwner": { - "type": "string", - "description": "The name of the owner of the template.", - "default": "", - "x-example": "" - }, - "templateRootDirectory": { - "type": "string", - "description": "Path to function code in the template repo.", - "default": "", - "x-example": "" - }, - "templateVersion": { - "type": "string", - "description": "Version (tag) for the repo linked to the function template.", - "default": "", - "x-example": "" } }, "required": [ diff --git a/composer.lock b/composer.lock index c058f036fc..f36b815777 100644 --- a/composer.lock +++ b/composer.lock @@ -4105,16 +4105,16 @@ }, { "name": "utopia-php/platform", - "version": "0.7.6", + "version": "0.7.7", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "6bc7fbb43ec2b7f9ee5bdef5d4b5e4a81860950b" + "reference": "8c43cd866148a7c4c495e3401268429e338004b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/6bc7fbb43ec2b7f9ee5bdef5d4b5e4a81860950b", - "reference": "6bc7fbb43ec2b7f9ee5bdef5d4b5e4a81860950b", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/8c43cd866148a7c4c495e3401268429e338004b3", + "reference": "8c43cd866148a7c4c495e3401268429e338004b3", "shasum": "" }, "require": { @@ -4149,9 +4149,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.7.6" + "source": "https://github.com/utopia-php/platform/tree/0.7.7" }, - "time": "2025-05-18T20:31:24+00:00" + "time": "2025-05-20T09:23:44+00:00" }, { "name": "utopia-php/pools", diff --git a/docs/examples/1.7.x/client-android/java/databases/create-documents.md b/docs/examples/1.7.x/client-android/java/databases/create-documents.md new file mode 100644 index 0000000000..dbdc64f111 --- /dev/null +++ b/docs/examples/1.7.x/client-android/java/databases/create-documents.md @@ -0,0 +1,24 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Databases; + +Client client = new Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setKey(""); // + +Databases databases = new Databases(client); + +databases.createDocuments( + "", // databaseId + "", // collectionId + listOf(), // documents + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + Log.d("Appwrite", result.toString()); + }) +); + diff --git a/docs/examples/1.7.x/client-android/kotlin/databases/create-documents.md b/docs/examples/1.7.x/client-android/kotlin/databases/create-documents.md new file mode 100644 index 0000000000..33635b4e4c --- /dev/null +++ b/docs/examples/1.7.x/client-android/kotlin/databases/create-documents.md @@ -0,0 +1,15 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Databases + +val client = Client(context) + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setKey("") // + +val databases = Databases(client) + +val result = databases.createDocuments( + databaseId = "", + collectionId = "", + documents = listOf(), +) \ No newline at end of file diff --git a/docs/examples/1.7.x/client-apple/examples/databases/create-documents.md b/docs/examples/1.7.x/client-apple/examples/databases/create-documents.md new file mode 100644 index 0000000000..b47247a359 --- /dev/null +++ b/docs/examples/1.7.x/client-apple/examples/databases/create-documents.md @@ -0,0 +1,14 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://.cloud.appwrite.io/v1") // Your API Endpoint + .setKey("") // + +let databases = Databases(client) + +let documentList = try await databases.createDocuments( + databaseId: "", + collectionId: "", + documents: [] +) + diff --git a/docs/examples/1.7.x/client-flutter/examples/databases/create-documents.md b/docs/examples/1.7.x/client-flutter/examples/databases/create-documents.md new file mode 100644 index 0000000000..953553749a --- /dev/null +++ b/docs/examples/1.7.x/client-flutter/examples/databases/create-documents.md @@ -0,0 +1,13 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setKey(''); // + +Databases databases = Databases(client); + +DocumentList result = await databases.createDocuments( + databaseId: '', + collectionId: '', + documents: [], +); diff --git a/docs/examples/1.7.x/client-graphql/examples/databases/create-documents.md b/docs/examples/1.7.x/client-graphql/examples/databases/create-documents.md new file mode 100644 index 0000000000..3e3a50f3ab --- /dev/null +++ b/docs/examples/1.7.x/client-graphql/examples/databases/create-documents.md @@ -0,0 +1,18 @@ +mutation { + databasesCreateDocuments( + databaseId: "", + collectionId: "", + documents: [] + ) { + total + documents { + _id + _collectionId + _databaseId + _createdAt + _updatedAt + _permissions + data + } + } +} diff --git a/docs/examples/1.7.x/client-react-native/examples/databases/create-documents.md b/docs/examples/1.7.x/client-react-native/examples/databases/create-documents.md new file mode 100644 index 0000000000..08663b6dbe --- /dev/null +++ b/docs/examples/1.7.x/client-react-native/examples/databases/create-documents.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "react-native-appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setKey(''); // + +const databases = new Databases(client); + +const result = await databases.createDocuments( + '', // databaseId + '', // collectionId + [] // documents +); + +console.log(result); diff --git a/docs/examples/1.7.x/client-rest/examples/databases/create-documents.md b/docs/examples/1.7.x/client-rest/examples/databases/create-documents.md new file mode 100644 index 0000000000..e4d2b956e0 --- /dev/null +++ b/docs/examples/1.7.x/client-rest/examples/databases/create-documents.md @@ -0,0 +1,11 @@ +POST /v1/databases/{databaseId}/collections/{collectionId}/documents HTTP/1.1 +Host: cloud.appwrite.io +Content-Type: application/json +X-Appwrite-Response-Format: 1.7.0 +X-Appwrite-Project: +X-Appwrite-Session: +X-Appwrite-JWT: + +{ + "documents": [] +} diff --git a/docs/examples/1.7.x/client-web/examples/databases/create-documents.md b/docs/examples/1.7.x/client-web/examples/databases/create-documents.md new file mode 100644 index 0000000000..ec6bdf244a --- /dev/null +++ b/docs/examples/1.7.x/client-web/examples/databases/create-documents.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "appwrite"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setKey(''); // + +const databases = new Databases(client); + +const result = await databases.createDocuments( + '', // databaseId + '', // collectionId + [] // documents +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-cli/examples/account/create-anonymous-session.md b/docs/examples/1.7.x/console-cli/examples/account/create-anonymous-session.md new file mode 100644 index 0000000000..a7eb9c5be3 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/create-anonymous-session.md @@ -0,0 +1 @@ +appwrite account createAnonymousSession diff --git a/docs/examples/1.7.x/console-cli/examples/account/create-email-password-session.md b/docs/examples/1.7.x/console-cli/examples/account/create-email-password-session.md new file mode 100644 index 0000000000..951293b4b2 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/create-email-password-session.md @@ -0,0 +1,3 @@ +appwrite account createEmailPasswordSession \ + --email email@example.com \ + --password password diff --git a/docs/examples/1.7.x/console-cli/examples/account/create-email-token.md b/docs/examples/1.7.x/console-cli/examples/account/create-email-token.md new file mode 100644 index 0000000000..0aaf2476c9 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/create-email-token.md @@ -0,0 +1,4 @@ +appwrite account createEmailToken \ + --userId \ + --email email@example.com \ + diff --git a/docs/examples/1.7.x/console-cli/examples/account/create-j-w-t.md b/docs/examples/1.7.x/console-cli/examples/account/create-j-w-t.md new file mode 100644 index 0000000000..7b5337993d --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/create-j-w-t.md @@ -0,0 +1 @@ +appwrite account createJWT diff --git a/docs/examples/1.7.x/console-cli/examples/account/create-magic-u-r-l-token.md b/docs/examples/1.7.x/console-cli/examples/account/create-magic-u-r-l-token.md new file mode 100644 index 0000000000..69203b085d --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/create-magic-u-r-l-token.md @@ -0,0 +1,5 @@ +appwrite account createMagicURLToken \ + --userId \ + --email email@example.com \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/account/create-mfa-authenticator.md b/docs/examples/1.7.x/console-cli/examples/account/create-mfa-authenticator.md new file mode 100644 index 0000000000..7634217700 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/create-mfa-authenticator.md @@ -0,0 +1,2 @@ +appwrite account createMfaAuthenticator \ + --type totp diff --git a/docs/examples/1.7.x/console-cli/examples/account/create-mfa-challenge.md b/docs/examples/1.7.x/console-cli/examples/account/create-mfa-challenge.md new file mode 100644 index 0000000000..8696be7ec1 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/create-mfa-challenge.md @@ -0,0 +1,2 @@ +appwrite account createMfaChallenge \ + --factor email diff --git a/docs/examples/1.7.x/console-cli/examples/account/create-mfa-recovery-codes.md b/docs/examples/1.7.x/console-cli/examples/account/create-mfa-recovery-codes.md new file mode 100644 index 0000000000..0ef25446fd --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/create-mfa-recovery-codes.md @@ -0,0 +1 @@ +appwrite account createMfaRecoveryCodes diff --git a/docs/examples/1.7.x/console-cli/examples/account/create-o-auth2session.md b/docs/examples/1.7.x/console-cli/examples/account/create-o-auth2session.md new file mode 100644 index 0000000000..9159b8f25f --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/create-o-auth2session.md @@ -0,0 +1,5 @@ +appwrite account createOAuth2Session \ + --provider amazon \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/account/create-o-auth2token.md b/docs/examples/1.7.x/console-cli/examples/account/create-o-auth2token.md new file mode 100644 index 0000000000..b36f350d99 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/create-o-auth2token.md @@ -0,0 +1,5 @@ +appwrite account createOAuth2Token \ + --provider amazon \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/account/create-phone-token.md b/docs/examples/1.7.x/console-cli/examples/account/create-phone-token.md new file mode 100644 index 0000000000..23f7f19cac --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/create-phone-token.md @@ -0,0 +1,3 @@ +appwrite account createPhoneToken \ + --userId \ + --phone +12065550100 diff --git a/docs/examples/1.7.x/console-cli/examples/account/create-phone-verification.md b/docs/examples/1.7.x/console-cli/examples/account/create-phone-verification.md new file mode 100644 index 0000000000..3c4402ba1f --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/create-phone-verification.md @@ -0,0 +1 @@ +appwrite account createPhoneVerification diff --git a/docs/examples/1.7.x/console-cli/examples/account/create-push-target.md b/docs/examples/1.7.x/console-cli/examples/account/create-push-target.md new file mode 100644 index 0000000000..41c380b288 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/create-push-target.md @@ -0,0 +1,4 @@ +appwrite account createPushTarget \ + --targetId \ + --identifier \ + diff --git a/docs/examples/1.7.x/console-cli/examples/account/create-recovery.md b/docs/examples/1.7.x/console-cli/examples/account/create-recovery.md new file mode 100644 index 0000000000..ea8c145abb --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/create-recovery.md @@ -0,0 +1,3 @@ +appwrite account createRecovery \ + --email email@example.com \ + --url https://example.com diff --git a/docs/examples/1.7.x/console-cli/examples/account/create-session.md b/docs/examples/1.7.x/console-cli/examples/account/create-session.md new file mode 100644 index 0000000000..426713ef50 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/create-session.md @@ -0,0 +1,3 @@ +appwrite account createSession \ + --userId \ + --secret diff --git a/docs/examples/1.7.x/console-cli/examples/account/create-verification.md b/docs/examples/1.7.x/console-cli/examples/account/create-verification.md new file mode 100644 index 0000000000..402038b4b6 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/create-verification.md @@ -0,0 +1,2 @@ +appwrite account createVerification \ + --url https://example.com diff --git a/docs/examples/1.7.x/console-cli/examples/account/create.md b/docs/examples/1.7.x/console-cli/examples/account/create.md new file mode 100644 index 0000000000..09686a2454 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/create.md @@ -0,0 +1,5 @@ +appwrite account create \ + --userId \ + --email email@example.com \ + --password '' \ + diff --git a/docs/examples/1.7.x/console-cli/examples/account/delete-identity.md b/docs/examples/1.7.x/console-cli/examples/account/delete-identity.md new file mode 100644 index 0000000000..acd8511dfb --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/delete-identity.md @@ -0,0 +1,2 @@ +appwrite account deleteIdentity \ + --identityId diff --git a/docs/examples/1.7.x/console-cli/examples/account/delete-mfa-authenticator.md b/docs/examples/1.7.x/console-cli/examples/account/delete-mfa-authenticator.md new file mode 100644 index 0000000000..d4664855b5 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/delete-mfa-authenticator.md @@ -0,0 +1,2 @@ +appwrite account deleteMfaAuthenticator \ + --type totp diff --git a/docs/examples/1.7.x/console-cli/examples/account/delete-push-target.md b/docs/examples/1.7.x/console-cli/examples/account/delete-push-target.md new file mode 100644 index 0000000000..610ea232d8 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/delete-push-target.md @@ -0,0 +1,2 @@ +appwrite account deletePushTarget \ + --targetId diff --git a/docs/examples/1.7.x/console-cli/examples/account/delete-session.md b/docs/examples/1.7.x/console-cli/examples/account/delete-session.md new file mode 100644 index 0000000000..9774552408 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/delete-session.md @@ -0,0 +1,2 @@ +appwrite account deleteSession \ + --sessionId diff --git a/docs/examples/1.7.x/console-cli/examples/account/delete-sessions.md b/docs/examples/1.7.x/console-cli/examples/account/delete-sessions.md new file mode 100644 index 0000000000..dd11877a5d --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/delete-sessions.md @@ -0,0 +1 @@ +appwrite account deleteSessions diff --git a/docs/examples/1.7.x/console-cli/examples/account/delete.md b/docs/examples/1.7.x/console-cli/examples/account/delete.md new file mode 100644 index 0000000000..dac412f7c2 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/delete.md @@ -0,0 +1 @@ +appwrite account delete diff --git a/docs/examples/1.7.x/console-cli/examples/account/get-mfa-recovery-codes.md b/docs/examples/1.7.x/console-cli/examples/account/get-mfa-recovery-codes.md new file mode 100644 index 0000000000..0e61d658de --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/get-mfa-recovery-codes.md @@ -0,0 +1 @@ +appwrite account getMfaRecoveryCodes diff --git a/docs/examples/1.7.x/console-cli/examples/account/get-prefs.md b/docs/examples/1.7.x/console-cli/examples/account/get-prefs.md new file mode 100644 index 0000000000..6569925d99 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/get-prefs.md @@ -0,0 +1 @@ +appwrite account getPrefs diff --git a/docs/examples/1.7.x/console-cli/examples/account/get-session.md b/docs/examples/1.7.x/console-cli/examples/account/get-session.md new file mode 100644 index 0000000000..120dc8277f --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/get-session.md @@ -0,0 +1,2 @@ +appwrite account getSession \ + --sessionId diff --git a/docs/examples/1.7.x/console-cli/examples/account/get.md b/docs/examples/1.7.x/console-cli/examples/account/get.md new file mode 100644 index 0000000000..c8b46e34c7 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/get.md @@ -0,0 +1 @@ +appwrite account get diff --git a/docs/examples/1.7.x/console-cli/examples/account/list-identities.md b/docs/examples/1.7.x/console-cli/examples/account/list-identities.md new file mode 100644 index 0000000000..877b443ea8 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/list-identities.md @@ -0,0 +1,2 @@ +appwrite account listIdentities \ + diff --git a/docs/examples/1.7.x/console-cli/examples/account/list-logs.md b/docs/examples/1.7.x/console-cli/examples/account/list-logs.md new file mode 100644 index 0000000000..e92f49063a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/list-logs.md @@ -0,0 +1,2 @@ +appwrite account listLogs \ + diff --git a/docs/examples/1.7.x/console-cli/examples/account/list-mfa-factors.md b/docs/examples/1.7.x/console-cli/examples/account/list-mfa-factors.md new file mode 100644 index 0000000000..a29f287d24 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/list-mfa-factors.md @@ -0,0 +1 @@ +appwrite account listMfaFactors diff --git a/docs/examples/1.7.x/console-cli/examples/account/list-sessions.md b/docs/examples/1.7.x/console-cli/examples/account/list-sessions.md new file mode 100644 index 0000000000..87cbab0f66 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/list-sessions.md @@ -0,0 +1 @@ +appwrite account listSessions diff --git a/docs/examples/1.7.x/console-cli/examples/account/update-email.md b/docs/examples/1.7.x/console-cli/examples/account/update-email.md new file mode 100644 index 0000000000..81938ff3a9 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/update-email.md @@ -0,0 +1,3 @@ +appwrite account updateEmail \ + --email email@example.com \ + --password password diff --git a/docs/examples/1.7.x/console-cli/examples/account/update-m-f-a.md b/docs/examples/1.7.x/console-cli/examples/account/update-m-f-a.md new file mode 100644 index 0000000000..f714d4dbe9 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/update-m-f-a.md @@ -0,0 +1,2 @@ +appwrite account updateMFA \ + --mfa false diff --git a/docs/examples/1.7.x/console-cli/examples/account/update-magic-u-r-l-session.md b/docs/examples/1.7.x/console-cli/examples/account/update-magic-u-r-l-session.md new file mode 100644 index 0000000000..919bd70a30 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/update-magic-u-r-l-session.md @@ -0,0 +1,3 @@ +appwrite account updateMagicURLSession \ + --userId \ + --secret diff --git a/docs/examples/1.7.x/console-cli/examples/account/update-mfa-authenticator.md b/docs/examples/1.7.x/console-cli/examples/account/update-mfa-authenticator.md new file mode 100644 index 0000000000..b51796a79e --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/update-mfa-authenticator.md @@ -0,0 +1,3 @@ +appwrite account updateMfaAuthenticator \ + --type totp \ + --otp diff --git a/docs/examples/1.7.x/console-cli/examples/account/update-mfa-challenge.md b/docs/examples/1.7.x/console-cli/examples/account/update-mfa-challenge.md new file mode 100644 index 0000000000..37e09ef4e8 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/update-mfa-challenge.md @@ -0,0 +1,3 @@ +appwrite account updateMfaChallenge \ + --challengeId \ + --otp diff --git a/docs/examples/1.7.x/console-cli/examples/account/update-mfa-recovery-codes.md b/docs/examples/1.7.x/console-cli/examples/account/update-mfa-recovery-codes.md new file mode 100644 index 0000000000..a129ca6f98 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/update-mfa-recovery-codes.md @@ -0,0 +1 @@ +appwrite account updateMfaRecoveryCodes diff --git a/docs/examples/1.7.x/console-cli/examples/account/update-name.md b/docs/examples/1.7.x/console-cli/examples/account/update-name.md new file mode 100644 index 0000000000..6f3b5977f4 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/update-name.md @@ -0,0 +1,2 @@ +appwrite account updateName \ + --name diff --git a/docs/examples/1.7.x/console-cli/examples/account/update-password.md b/docs/examples/1.7.x/console-cli/examples/account/update-password.md new file mode 100644 index 0000000000..340baec562 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/update-password.md @@ -0,0 +1,3 @@ +appwrite account updatePassword \ + --password '' \ + diff --git a/docs/examples/1.7.x/console-cli/examples/account/update-phone-session.md b/docs/examples/1.7.x/console-cli/examples/account/update-phone-session.md new file mode 100644 index 0000000000..d70f33fab5 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/update-phone-session.md @@ -0,0 +1,3 @@ +appwrite account updatePhoneSession \ + --userId \ + --secret diff --git a/docs/examples/1.7.x/console-cli/examples/account/update-phone-verification.md b/docs/examples/1.7.x/console-cli/examples/account/update-phone-verification.md new file mode 100644 index 0000000000..cef2b5a40d --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/update-phone-verification.md @@ -0,0 +1,3 @@ +appwrite account updatePhoneVerification \ + --userId \ + --secret diff --git a/docs/examples/1.7.x/console-cli/examples/account/update-phone.md b/docs/examples/1.7.x/console-cli/examples/account/update-phone.md new file mode 100644 index 0000000000..93a619a801 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/update-phone.md @@ -0,0 +1,3 @@ +appwrite account updatePhone \ + --phone +12065550100 \ + --password password diff --git a/docs/examples/1.7.x/console-cli/examples/account/update-prefs.md b/docs/examples/1.7.x/console-cli/examples/account/update-prefs.md new file mode 100644 index 0000000000..568ac66e48 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/update-prefs.md @@ -0,0 +1,2 @@ +appwrite account updatePrefs \ + --prefs '{ "key": "value" }' diff --git a/docs/examples/1.7.x/console-cli/examples/account/update-push-target.md b/docs/examples/1.7.x/console-cli/examples/account/update-push-target.md new file mode 100644 index 0000000000..f3aa1a906a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/update-push-target.md @@ -0,0 +1,3 @@ +appwrite account updatePushTarget \ + --targetId \ + --identifier diff --git a/docs/examples/1.7.x/console-cli/examples/account/update-recovery.md b/docs/examples/1.7.x/console-cli/examples/account/update-recovery.md new file mode 100644 index 0000000000..903a99cc99 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/update-recovery.md @@ -0,0 +1,4 @@ +appwrite account updateRecovery \ + --userId \ + --secret \ + --password '' diff --git a/docs/examples/1.7.x/console-cli/examples/account/update-session.md b/docs/examples/1.7.x/console-cli/examples/account/update-session.md new file mode 100644 index 0000000000..5fb6a2e8d5 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/update-session.md @@ -0,0 +1,2 @@ +appwrite account updateSession \ + --sessionId diff --git a/docs/examples/1.7.x/console-cli/examples/account/update-status.md b/docs/examples/1.7.x/console-cli/examples/account/update-status.md new file mode 100644 index 0000000000..8886dbbc6a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/update-status.md @@ -0,0 +1 @@ +appwrite account updateStatus diff --git a/docs/examples/1.7.x/console-cli/examples/account/update-verification.md b/docs/examples/1.7.x/console-cli/examples/account/update-verification.md new file mode 100644 index 0000000000..afdfaa8372 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/account/update-verification.md @@ -0,0 +1,3 @@ +appwrite account updateVerification \ + --userId \ + --secret diff --git a/docs/examples/1.7.x/console-cli/examples/assistant/chat.md b/docs/examples/1.7.x/console-cli/examples/assistant/chat.md new file mode 100644 index 0000000000..cf62d30515 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/assistant/chat.md @@ -0,0 +1,2 @@ +appwrite assistant chat \ + --prompt diff --git a/docs/examples/1.7.x/console-cli/examples/avatars/get-browser.md b/docs/examples/1.7.x/console-cli/examples/avatars/get-browser.md new file mode 100644 index 0000000000..6b4f0b8007 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/avatars/get-browser.md @@ -0,0 +1,5 @@ +appwrite avatars getBrowser \ + --code aa \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/avatars/get-credit-card.md b/docs/examples/1.7.x/console-cli/examples/avatars/get-credit-card.md new file mode 100644 index 0000000000..365568ba19 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/avatars/get-credit-card.md @@ -0,0 +1,5 @@ +appwrite avatars getCreditCard \ + --code amex \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/avatars/get-favicon.md b/docs/examples/1.7.x/console-cli/examples/avatars/get-favicon.md new file mode 100644 index 0000000000..c658f1a483 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/avatars/get-favicon.md @@ -0,0 +1,2 @@ +appwrite avatars getFavicon \ + --url https://example.com diff --git a/docs/examples/1.7.x/console-cli/examples/avatars/get-flag.md b/docs/examples/1.7.x/console-cli/examples/avatars/get-flag.md new file mode 100644 index 0000000000..9f11fef840 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/avatars/get-flag.md @@ -0,0 +1,5 @@ +appwrite avatars getFlag \ + --code af \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/avatars/get-image.md b/docs/examples/1.7.x/console-cli/examples/avatars/get-image.md new file mode 100644 index 0000000000..7df150610c --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/avatars/get-image.md @@ -0,0 +1,4 @@ +appwrite avatars getImage \ + --url https://example.com \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/avatars/get-initials.md b/docs/examples/1.7.x/console-cli/examples/avatars/get-initials.md new file mode 100644 index 0000000000..b0b3da71c9 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/avatars/get-initials.md @@ -0,0 +1,5 @@ +appwrite avatars getInitials \ + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/avatars/get-q-r.md b/docs/examples/1.7.x/console-cli/examples/avatars/get-q-r.md new file mode 100644 index 0000000000..01e5085732 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/avatars/get-q-r.md @@ -0,0 +1,5 @@ +appwrite avatars getQR \ + --text \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/console/get-resource.md b/docs/examples/1.7.x/console-cli/examples/console/get-resource.md new file mode 100644 index 0000000000..3e55163966 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/console/get-resource.md @@ -0,0 +1,3 @@ +appwrite console getResource \ + --value \ + --type rules diff --git a/docs/examples/1.7.x/console-cli/examples/console/variables.md b/docs/examples/1.7.x/console-cli/examples/console/variables.md new file mode 100644 index 0000000000..1c67cf5ad8 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/console/variables.md @@ -0,0 +1 @@ +appwrite console variables diff --git a/docs/examples/1.7.x/console-cli/examples/databases/create-boolean-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/create-boolean-attribute.md new file mode 100644 index 0000000000..6babbfb5af --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/create-boolean-attribute.md @@ -0,0 +1,7 @@ +appwrite databases createBooleanAttribute \ + --databaseId \ + --collectionId \ + --key '' \ + --required false \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/create-collection.md b/docs/examples/1.7.x/console-cli/examples/databases/create-collection.md new file mode 100644 index 0000000000..d97c424d16 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/create-collection.md @@ -0,0 +1,7 @@ +appwrite databases createCollection \ + --databaseId \ + --collectionId \ + --name \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/create-datetime-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/create-datetime-attribute.md new file mode 100644 index 0000000000..f6aaf54fa2 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/create-datetime-attribute.md @@ -0,0 +1,7 @@ +appwrite databases createDatetimeAttribute \ + --databaseId \ + --collectionId \ + --key '' \ + --required false \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/create-document.md b/docs/examples/1.7.x/console-cli/examples/databases/create-document.md new file mode 100644 index 0000000000..513cfc4f33 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/create-document.md @@ -0,0 +1,6 @@ +appwrite databases createDocument \ + --databaseId \ + --collectionId \ + --documentId \ + --data '{ "key": "value" }' \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/create-documents.md b/docs/examples/1.7.x/console-cli/examples/databases/create-documents.md new file mode 100644 index 0000000000..e9e65b5c3c --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/create-documents.md @@ -0,0 +1,4 @@ +appwrite databases createDocuments \ + --databaseId \ + --collectionId \ + --documents one two three diff --git a/docs/examples/1.7.x/console-cli/examples/databases/create-email-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/create-email-attribute.md new file mode 100644 index 0000000000..5c23f940de --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/create-email-attribute.md @@ -0,0 +1,7 @@ +appwrite databases createEmailAttribute \ + --databaseId \ + --collectionId \ + --key '' \ + --required false \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/create-enum-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/create-enum-attribute.md new file mode 100644 index 0000000000..5d3c614410 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/create-enum-attribute.md @@ -0,0 +1,8 @@ +appwrite databases createEnumAttribute \ + --databaseId \ + --collectionId \ + --key '' \ + --elements one two three \ + --required false \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/create-float-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/create-float-attribute.md new file mode 100644 index 0000000000..5a6ef4e4ef --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/create-float-attribute.md @@ -0,0 +1,9 @@ +appwrite databases createFloatAttribute \ + --databaseId \ + --collectionId \ + --key '' \ + --required false \ + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/create-index.md b/docs/examples/1.7.x/console-cli/examples/databases/create-index.md new file mode 100644 index 0000000000..2dc95ea921 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/create-index.md @@ -0,0 +1,8 @@ +appwrite databases createIndex \ + --databaseId \ + --collectionId \ + --key '' \ + --type key \ + --attributes one two three \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/create-integer-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/create-integer-attribute.md new file mode 100644 index 0000000000..791f3770c9 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/create-integer-attribute.md @@ -0,0 +1,9 @@ +appwrite databases createIntegerAttribute \ + --databaseId \ + --collectionId \ + --key '' \ + --required false \ + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/create-ip-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/create-ip-attribute.md new file mode 100644 index 0000000000..4f39d84bab --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/create-ip-attribute.md @@ -0,0 +1,7 @@ +appwrite databases createIpAttribute \ + --databaseId \ + --collectionId \ + --key '' \ + --required false \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/create-relationship-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/create-relationship-attribute.md new file mode 100644 index 0000000000..c7d8ae568a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/create-relationship-attribute.md @@ -0,0 +1,9 @@ +appwrite databases createRelationshipAttribute \ + --databaseId \ + --collectionId \ + --relatedCollectionId \ + --type oneToOne \ + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/create-string-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/create-string-attribute.md new file mode 100644 index 0000000000..37b1db644a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/create-string-attribute.md @@ -0,0 +1,9 @@ +appwrite databases createStringAttribute \ + --databaseId \ + --collectionId \ + --key '' \ + --size 1 \ + --required false \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/create-url-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/create-url-attribute.md new file mode 100644 index 0000000000..4406ed7879 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/create-url-attribute.md @@ -0,0 +1,7 @@ +appwrite databases createUrlAttribute \ + --databaseId \ + --collectionId \ + --key '' \ + --required false \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/create.md b/docs/examples/1.7.x/console-cli/examples/databases/create.md new file mode 100644 index 0000000000..9e7523974f --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/create.md @@ -0,0 +1,4 @@ +appwrite databases create \ + --databaseId \ + --name \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/delete-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/delete-attribute.md new file mode 100644 index 0000000000..88e7df985f --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/delete-attribute.md @@ -0,0 +1,4 @@ +appwrite databases deleteAttribute \ + --databaseId \ + --collectionId \ + --key '' diff --git a/docs/examples/1.7.x/console-cli/examples/databases/delete-collection.md b/docs/examples/1.7.x/console-cli/examples/databases/delete-collection.md new file mode 100644 index 0000000000..0db185a7d7 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/delete-collection.md @@ -0,0 +1,3 @@ +appwrite databases deleteCollection \ + --databaseId \ + --collectionId diff --git a/docs/examples/1.7.x/console-cli/examples/databases/delete-document.md b/docs/examples/1.7.x/console-cli/examples/databases/delete-document.md new file mode 100644 index 0000000000..3a96d35798 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/delete-document.md @@ -0,0 +1,4 @@ +appwrite databases deleteDocument \ + --databaseId \ + --collectionId \ + --documentId diff --git a/docs/examples/1.7.x/console-cli/examples/databases/delete-documents.md b/docs/examples/1.7.x/console-cli/examples/databases/delete-documents.md new file mode 100644 index 0000000000..6f3463cbf9 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/delete-documents.md @@ -0,0 +1,4 @@ +appwrite databases deleteDocuments \ + --databaseId \ + --collectionId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/delete-index.md b/docs/examples/1.7.x/console-cli/examples/databases/delete-index.md new file mode 100644 index 0000000000..56485e7a78 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/delete-index.md @@ -0,0 +1,4 @@ +appwrite databases deleteIndex \ + --databaseId \ + --collectionId \ + --key '' diff --git a/docs/examples/1.7.x/console-cli/examples/databases/delete.md b/docs/examples/1.7.x/console-cli/examples/databases/delete.md new file mode 100644 index 0000000000..a24a3a04d3 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/delete.md @@ -0,0 +1,2 @@ +appwrite databases delete \ + --databaseId diff --git a/docs/examples/1.7.x/console-cli/examples/databases/get-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/get-attribute.md new file mode 100644 index 0000000000..821698011f --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/get-attribute.md @@ -0,0 +1,4 @@ +appwrite databases getAttribute \ + --databaseId \ + --collectionId \ + --key '' diff --git a/docs/examples/1.7.x/console-cli/examples/databases/get-collection-usage.md b/docs/examples/1.7.x/console-cli/examples/databases/get-collection-usage.md new file mode 100644 index 0000000000..b57e6c92a9 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/get-collection-usage.md @@ -0,0 +1,4 @@ +appwrite databases getCollectionUsage \ + --databaseId \ + --collectionId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/get-collection.md b/docs/examples/1.7.x/console-cli/examples/databases/get-collection.md new file mode 100644 index 0000000000..e763b5bbfb --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/get-collection.md @@ -0,0 +1,3 @@ +appwrite databases getCollection \ + --databaseId \ + --collectionId diff --git a/docs/examples/1.7.x/console-cli/examples/databases/get-database-usage.md b/docs/examples/1.7.x/console-cli/examples/databases/get-database-usage.md new file mode 100644 index 0000000000..1001e9cd11 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/get-database-usage.md @@ -0,0 +1,3 @@ +appwrite databases getDatabaseUsage \ + --databaseId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/get-document.md b/docs/examples/1.7.x/console-cli/examples/databases/get-document.md new file mode 100644 index 0000000000..35d9615503 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/get-document.md @@ -0,0 +1,5 @@ +appwrite databases getDocument \ + --databaseId \ + --collectionId \ + --documentId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/get-index.md b/docs/examples/1.7.x/console-cli/examples/databases/get-index.md new file mode 100644 index 0000000000..0071834a8c --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/get-index.md @@ -0,0 +1,4 @@ +appwrite databases getIndex \ + --databaseId \ + --collectionId \ + --key '' diff --git a/docs/examples/1.7.x/console-cli/examples/databases/get-usage.md b/docs/examples/1.7.x/console-cli/examples/databases/get-usage.md new file mode 100644 index 0000000000..53c85fc849 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/get-usage.md @@ -0,0 +1,2 @@ +appwrite databases getUsage \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/get.md b/docs/examples/1.7.x/console-cli/examples/databases/get.md new file mode 100644 index 0000000000..35480b64cc --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/get.md @@ -0,0 +1,2 @@ +appwrite databases get \ + --databaseId diff --git a/docs/examples/1.7.x/console-cli/examples/databases/list-attributes.md b/docs/examples/1.7.x/console-cli/examples/databases/list-attributes.md new file mode 100644 index 0000000000..a2382feb3a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/list-attributes.md @@ -0,0 +1,4 @@ +appwrite databases listAttributes \ + --databaseId \ + --collectionId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/list-collection-logs.md b/docs/examples/1.7.x/console-cli/examples/databases/list-collection-logs.md new file mode 100644 index 0000000000..eadac47a6b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/list-collection-logs.md @@ -0,0 +1,4 @@ +appwrite databases listCollectionLogs \ + --databaseId \ + --collectionId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/list-collections.md b/docs/examples/1.7.x/console-cli/examples/databases/list-collections.md new file mode 100644 index 0000000000..b05c330be2 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/list-collections.md @@ -0,0 +1,4 @@ +appwrite databases listCollections \ + --databaseId \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/list-document-logs.md b/docs/examples/1.7.x/console-cli/examples/databases/list-document-logs.md new file mode 100644 index 0000000000..63b5394647 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/list-document-logs.md @@ -0,0 +1,5 @@ +appwrite databases listDocumentLogs \ + --databaseId \ + --collectionId \ + --documentId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/list-documents.md b/docs/examples/1.7.x/console-cli/examples/databases/list-documents.md new file mode 100644 index 0000000000..98e389579d --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/list-documents.md @@ -0,0 +1,4 @@ +appwrite databases listDocuments \ + --databaseId \ + --collectionId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/list-indexes.md b/docs/examples/1.7.x/console-cli/examples/databases/list-indexes.md new file mode 100644 index 0000000000..50acb4d7ad --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/list-indexes.md @@ -0,0 +1,4 @@ +appwrite databases listIndexes \ + --databaseId \ + --collectionId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/list-logs.md b/docs/examples/1.7.x/console-cli/examples/databases/list-logs.md new file mode 100644 index 0000000000..38547c7c3c --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/list-logs.md @@ -0,0 +1,3 @@ +appwrite databases listLogs \ + --databaseId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/list.md b/docs/examples/1.7.x/console-cli/examples/databases/list.md new file mode 100644 index 0000000000..e723bc32ec --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/list.md @@ -0,0 +1,3 @@ +appwrite databases list \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/update-boolean-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/update-boolean-attribute.md new file mode 100644 index 0000000000..f5adb497ec --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/update-boolean-attribute.md @@ -0,0 +1,7 @@ +appwrite databases updateBooleanAttribute \ + --databaseId \ + --collectionId \ + --key '' \ + --required false \ + --default false \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/update-collection.md b/docs/examples/1.7.x/console-cli/examples/databases/update-collection.md new file mode 100644 index 0000000000..eab3617c80 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/update-collection.md @@ -0,0 +1,7 @@ +appwrite databases updateCollection \ + --databaseId \ + --collectionId \ + --name \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/update-datetime-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/update-datetime-attribute.md new file mode 100644 index 0000000000..fe4a462664 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/update-datetime-attribute.md @@ -0,0 +1,7 @@ +appwrite databases updateDatetimeAttribute \ + --databaseId \ + --collectionId \ + --key '' \ + --required false \ + --default '' \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/update-document.md b/docs/examples/1.7.x/console-cli/examples/databases/update-document.md new file mode 100644 index 0000000000..a4ac55bf6b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/update-document.md @@ -0,0 +1,6 @@ +appwrite databases updateDocument \ + --databaseId \ + --collectionId \ + --documentId \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/update-documents.md b/docs/examples/1.7.x/console-cli/examples/databases/update-documents.md new file mode 100644 index 0000000000..935f664440 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/update-documents.md @@ -0,0 +1,5 @@ +appwrite databases updateDocuments \ + --databaseId \ + --collectionId \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/update-email-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/update-email-attribute.md new file mode 100644 index 0000000000..58510a6f8e --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/update-email-attribute.md @@ -0,0 +1,7 @@ +appwrite databases updateEmailAttribute \ + --databaseId \ + --collectionId \ + --key '' \ + --required false \ + --default email@example.com \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/update-enum-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/update-enum-attribute.md new file mode 100644 index 0000000000..21d56d3e64 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/update-enum-attribute.md @@ -0,0 +1,8 @@ +appwrite databases updateEnumAttribute \ + --databaseId \ + --collectionId \ + --key '' \ + --elements one two three \ + --required false \ + --default \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/update-float-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/update-float-attribute.md new file mode 100644 index 0000000000..a9bba3eb5e --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/update-float-attribute.md @@ -0,0 +1,9 @@ +appwrite databases updateFloatAttribute \ + --databaseId \ + --collectionId \ + --key '' \ + --required false \ + --default null \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/update-integer-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/update-integer-attribute.md new file mode 100644 index 0000000000..660cd4d148 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/update-integer-attribute.md @@ -0,0 +1,9 @@ +appwrite databases updateIntegerAttribute \ + --databaseId \ + --collectionId \ + --key '' \ + --required false \ + --default null \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/update-ip-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/update-ip-attribute.md new file mode 100644 index 0000000000..a400eadc1e --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/update-ip-attribute.md @@ -0,0 +1,7 @@ +appwrite databases updateIpAttribute \ + --databaseId \ + --collectionId \ + --key '' \ + --required false \ + --default '' \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/update-relationship-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/update-relationship-attribute.md new file mode 100644 index 0000000000..6e2dbd927d --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/update-relationship-attribute.md @@ -0,0 +1,6 @@ +appwrite databases updateRelationshipAttribute \ + --databaseId \ + --collectionId \ + --key '' \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/update-string-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/update-string-attribute.md new file mode 100644 index 0000000000..526ece0b72 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/update-string-attribute.md @@ -0,0 +1,8 @@ +appwrite databases updateStringAttribute \ + --databaseId \ + --collectionId \ + --key '' \ + --required false \ + --default \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/update-url-attribute.md b/docs/examples/1.7.x/console-cli/examples/databases/update-url-attribute.md new file mode 100644 index 0000000000..e6f401b8ca --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/update-url-attribute.md @@ -0,0 +1,7 @@ +appwrite databases updateUrlAttribute \ + --databaseId \ + --collectionId \ + --key '' \ + --required false \ + --default https://example.com \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/update.md b/docs/examples/1.7.x/console-cli/examples/databases/update.md new file mode 100644 index 0000000000..a1e0a844e5 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/update.md @@ -0,0 +1,4 @@ +appwrite databases update \ + --databaseId \ + --name \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/upsert-documents.md b/docs/examples/1.7.x/console-cli/examples/databases/upsert-documents.md new file mode 100644 index 0000000000..3d0bd165d5 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/upsert-documents.md @@ -0,0 +1,4 @@ +appwrite databases upsertDocuments \ + --databaseId \ + --collectionId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/functions/create-deployment.md b/docs/examples/1.7.x/console-cli/examples/functions/create-deployment.md new file mode 100644 index 0000000000..6ac80bd73a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/create-deployment.md @@ -0,0 +1,6 @@ +appwrite functions createDeployment \ + --functionId \ + --code 'path/to/file.png' \ + --activate false \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/functions/create-duplicate-deployment.md b/docs/examples/1.7.x/console-cli/examples/functions/create-duplicate-deployment.md new file mode 100644 index 0000000000..4839155bd2 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/create-duplicate-deployment.md @@ -0,0 +1,4 @@ +appwrite functions createDuplicateDeployment \ + --functionId \ + --deploymentId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/functions/create-execution.md b/docs/examples/1.7.x/console-cli/examples/functions/create-execution.md new file mode 100644 index 0000000000..febe88c541 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/create-execution.md @@ -0,0 +1,8 @@ +appwrite functions createExecution \ + --functionId \ + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/functions/create-template-deployment.md b/docs/examples/1.7.x/console-cli/examples/functions/create-template-deployment.md new file mode 100644 index 0000000000..a6164a3d0b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/create-template-deployment.md @@ -0,0 +1,7 @@ +appwrite functions createTemplateDeployment \ + --functionId \ + --repository \ + --owner \ + --rootDirectory \ + --version \ + diff --git a/docs/examples/1.7.x/console-cli/examples/functions/create-variable.md b/docs/examples/1.7.x/console-cli/examples/functions/create-variable.md new file mode 100644 index 0000000000..f35f228d41 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/create-variable.md @@ -0,0 +1,5 @@ +appwrite functions createVariable \ + --functionId \ + --key \ + --value \ + diff --git a/docs/examples/1.7.x/console-cli/examples/functions/create-vcs-deployment.md b/docs/examples/1.7.x/console-cli/examples/functions/create-vcs-deployment.md new file mode 100644 index 0000000000..89f4caca66 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/create-vcs-deployment.md @@ -0,0 +1,5 @@ +appwrite functions createVcsDeployment \ + --functionId \ + --type branch \ + --reference \ + diff --git a/docs/examples/1.7.x/console-cli/examples/functions/create.md b/docs/examples/1.7.x/console-cli/examples/functions/create.md new file mode 100644 index 0000000000..ebca5741ed --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/create.md @@ -0,0 +1,19 @@ +appwrite functions create \ + --functionId \ + --name \ + --runtime node-14.5 \ + + + + + + + + + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/functions/delete-deployment.md b/docs/examples/1.7.x/console-cli/examples/functions/delete-deployment.md new file mode 100644 index 0000000000..2c9a6aa04a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/delete-deployment.md @@ -0,0 +1,3 @@ +appwrite functions deleteDeployment \ + --functionId \ + --deploymentId diff --git a/docs/examples/1.7.x/console-cli/examples/functions/delete-execution.md b/docs/examples/1.7.x/console-cli/examples/functions/delete-execution.md new file mode 100644 index 0000000000..2926b5aaf1 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/delete-execution.md @@ -0,0 +1,3 @@ +appwrite functions deleteExecution \ + --functionId \ + --executionId diff --git a/docs/examples/1.7.x/console-cli/examples/functions/delete-variable.md b/docs/examples/1.7.x/console-cli/examples/functions/delete-variable.md new file mode 100644 index 0000000000..835d125dc6 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/delete-variable.md @@ -0,0 +1,3 @@ +appwrite functions deleteVariable \ + --functionId \ + --variableId diff --git a/docs/examples/1.7.x/console-cli/examples/functions/delete.md b/docs/examples/1.7.x/console-cli/examples/functions/delete.md new file mode 100644 index 0000000000..0eea41c849 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/delete.md @@ -0,0 +1,2 @@ +appwrite functions delete \ + --functionId diff --git a/docs/examples/1.7.x/console-cli/examples/functions/get-deployment-download.md b/docs/examples/1.7.x/console-cli/examples/functions/get-deployment-download.md new file mode 100644 index 0000000000..485b608623 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/get-deployment-download.md @@ -0,0 +1,4 @@ +appwrite functions getDeploymentDownload \ + --functionId \ + --deploymentId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/functions/get-deployment.md b/docs/examples/1.7.x/console-cli/examples/functions/get-deployment.md new file mode 100644 index 0000000000..3da1605fea --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/get-deployment.md @@ -0,0 +1,3 @@ +appwrite functions getDeployment \ + --functionId \ + --deploymentId diff --git a/docs/examples/1.7.x/console-cli/examples/functions/get-execution.md b/docs/examples/1.7.x/console-cli/examples/functions/get-execution.md new file mode 100644 index 0000000000..d593f07c43 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/get-execution.md @@ -0,0 +1,3 @@ +appwrite functions getExecution \ + --functionId \ + --executionId diff --git a/docs/examples/1.7.x/console-cli/examples/functions/get-template.md b/docs/examples/1.7.x/console-cli/examples/functions/get-template.md new file mode 100644 index 0000000000..15c6068f35 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/get-template.md @@ -0,0 +1,2 @@ +appwrite functions getTemplate \ + --templateId diff --git a/docs/examples/1.7.x/console-cli/examples/functions/get-usage.md b/docs/examples/1.7.x/console-cli/examples/functions/get-usage.md new file mode 100644 index 0000000000..469db0f171 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/get-usage.md @@ -0,0 +1,3 @@ +appwrite functions getUsage \ + --functionId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/functions/get-variable.md b/docs/examples/1.7.x/console-cli/examples/functions/get-variable.md new file mode 100644 index 0000000000..241a91d936 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/get-variable.md @@ -0,0 +1,3 @@ +appwrite functions getVariable \ + --functionId \ + --variableId diff --git a/docs/examples/1.7.x/console-cli/examples/functions/get.md b/docs/examples/1.7.x/console-cli/examples/functions/get.md new file mode 100644 index 0000000000..f678ef7663 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/get.md @@ -0,0 +1,2 @@ +appwrite functions get \ + --functionId diff --git a/docs/examples/1.7.x/console-cli/examples/functions/list-deployments.md b/docs/examples/1.7.x/console-cli/examples/functions/list-deployments.md new file mode 100644 index 0000000000..2befb86abc --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/list-deployments.md @@ -0,0 +1,4 @@ +appwrite functions listDeployments \ + --functionId \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/functions/list-executions.md b/docs/examples/1.7.x/console-cli/examples/functions/list-executions.md new file mode 100644 index 0000000000..8d3136e6a4 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/list-executions.md @@ -0,0 +1,3 @@ +appwrite functions listExecutions \ + --functionId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/functions/list-runtimes.md b/docs/examples/1.7.x/console-cli/examples/functions/list-runtimes.md new file mode 100644 index 0000000000..15dc019c44 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/list-runtimes.md @@ -0,0 +1 @@ +appwrite functions listRuntimes diff --git a/docs/examples/1.7.x/console-cli/examples/functions/list-specifications.md b/docs/examples/1.7.x/console-cli/examples/functions/list-specifications.md new file mode 100644 index 0000000000..1d64bc68e7 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/list-specifications.md @@ -0,0 +1 @@ +appwrite functions listSpecifications diff --git a/docs/examples/1.7.x/console-cli/examples/functions/list-templates.md b/docs/examples/1.7.x/console-cli/examples/functions/list-templates.md new file mode 100644 index 0000000000..b48bab53e1 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/list-templates.md @@ -0,0 +1,5 @@ +appwrite functions listTemplates \ + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/functions/list-usage.md b/docs/examples/1.7.x/console-cli/examples/functions/list-usage.md new file mode 100644 index 0000000000..8ae7855f45 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/list-usage.md @@ -0,0 +1,2 @@ +appwrite functions listUsage \ + diff --git a/docs/examples/1.7.x/console-cli/examples/functions/list-variables.md b/docs/examples/1.7.x/console-cli/examples/functions/list-variables.md new file mode 100644 index 0000000000..21bf2eb506 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/list-variables.md @@ -0,0 +1,2 @@ +appwrite functions listVariables \ + --functionId diff --git a/docs/examples/1.7.x/console-cli/examples/functions/list.md b/docs/examples/1.7.x/console-cli/examples/functions/list.md new file mode 100644 index 0000000000..3b7551266e --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/list.md @@ -0,0 +1,3 @@ +appwrite functions list \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/functions/update-deployment-status.md b/docs/examples/1.7.x/console-cli/examples/functions/update-deployment-status.md new file mode 100644 index 0000000000..06d2dcdcf0 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/update-deployment-status.md @@ -0,0 +1,3 @@ +appwrite functions updateDeploymentStatus \ + --functionId \ + --deploymentId diff --git a/docs/examples/1.7.x/console-cli/examples/functions/update-function-deployment.md b/docs/examples/1.7.x/console-cli/examples/functions/update-function-deployment.md new file mode 100644 index 0000000000..652bfe809e --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/update-function-deployment.md @@ -0,0 +1,3 @@ +appwrite functions updateFunctionDeployment \ + --functionId \ + --deploymentId diff --git a/docs/examples/1.7.x/console-cli/examples/functions/update-variable.md b/docs/examples/1.7.x/console-cli/examples/functions/update-variable.md new file mode 100644 index 0000000000..a2b10491c6 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/update-variable.md @@ -0,0 +1,6 @@ +appwrite functions updateVariable \ + --functionId \ + --variableId \ + --key \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/functions/update.md b/docs/examples/1.7.x/console-cli/examples/functions/update.md new file mode 100644 index 0000000000..7ac63e0cd1 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/functions/update.md @@ -0,0 +1,19 @@ +appwrite functions update \ + --functionId \ + --name \ + + + + + + + + + + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/graphql/mutation.md b/docs/examples/1.7.x/console-cli/examples/graphql/mutation.md new file mode 100644 index 0000000000..f6127a175c --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/graphql/mutation.md @@ -0,0 +1,2 @@ +appwrite graphql mutation \ + --query '{ "key": "value" }' diff --git a/docs/examples/1.7.x/console-cli/examples/graphql/query.md b/docs/examples/1.7.x/console-cli/examples/graphql/query.md new file mode 100644 index 0000000000..1d84bcaa6a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/graphql/query.md @@ -0,0 +1,2 @@ +appwrite graphql query \ + --query '{ "key": "value" }' diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-antivirus.md b/docs/examples/1.7.x/console-cli/examples/health/get-antivirus.md new file mode 100644 index 0000000000..96dd7e78b2 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-antivirus.md @@ -0,0 +1 @@ +appwrite health getAntivirus diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-cache.md b/docs/examples/1.7.x/console-cli/examples/health/get-cache.md new file mode 100644 index 0000000000..ad1111ccf0 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-cache.md @@ -0,0 +1 @@ +appwrite health getCache diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-certificate.md b/docs/examples/1.7.x/console-cli/examples/health/get-certificate.md new file mode 100644 index 0000000000..4659415822 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-certificate.md @@ -0,0 +1,2 @@ +appwrite health getCertificate \ + diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-d-b.md b/docs/examples/1.7.x/console-cli/examples/health/get-d-b.md new file mode 100644 index 0000000000..b0ea2d3eac --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-d-b.md @@ -0,0 +1 @@ +appwrite health getDB diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-failed-jobs.md b/docs/examples/1.7.x/console-cli/examples/health/get-failed-jobs.md new file mode 100644 index 0000000000..724299e384 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-failed-jobs.md @@ -0,0 +1,3 @@ +appwrite health getFailedJobs \ + --name v1-database \ + diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-pub-sub.md b/docs/examples/1.7.x/console-cli/examples/health/get-pub-sub.md new file mode 100644 index 0000000000..aa1773b35b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-pub-sub.md @@ -0,0 +1 @@ +appwrite health getPubSub diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-queue-builds.md b/docs/examples/1.7.x/console-cli/examples/health/get-queue-builds.md new file mode 100644 index 0000000000..7204c2c896 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-queue-builds.md @@ -0,0 +1,2 @@ +appwrite health getQueueBuilds \ + diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-queue-certificates.md b/docs/examples/1.7.x/console-cli/examples/health/get-queue-certificates.md new file mode 100644 index 0000000000..203e8650cc --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-queue-certificates.md @@ -0,0 +1,2 @@ +appwrite health getQueueCertificates \ + diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-queue-databases.md b/docs/examples/1.7.x/console-cli/examples/health/get-queue-databases.md new file mode 100644 index 0000000000..f30b941cbc --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-queue-databases.md @@ -0,0 +1,3 @@ +appwrite health getQueueDatabases \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-queue-deletes.md b/docs/examples/1.7.x/console-cli/examples/health/get-queue-deletes.md new file mode 100644 index 0000000000..1d44146dc4 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-queue-deletes.md @@ -0,0 +1,2 @@ +appwrite health getQueueDeletes \ + diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-queue-functions.md b/docs/examples/1.7.x/console-cli/examples/health/get-queue-functions.md new file mode 100644 index 0000000000..4aca467306 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-queue-functions.md @@ -0,0 +1,2 @@ +appwrite health getQueueFunctions \ + diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-queue-logs.md b/docs/examples/1.7.x/console-cli/examples/health/get-queue-logs.md new file mode 100644 index 0000000000..3f1386b73a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-queue-logs.md @@ -0,0 +1,2 @@ +appwrite health getQueueLogs \ + diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-queue-mails.md b/docs/examples/1.7.x/console-cli/examples/health/get-queue-mails.md new file mode 100644 index 0000000000..a41f4c308b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-queue-mails.md @@ -0,0 +1,2 @@ +appwrite health getQueueMails \ + diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-queue-messaging.md b/docs/examples/1.7.x/console-cli/examples/health/get-queue-messaging.md new file mode 100644 index 0000000000..11b7ff832b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-queue-messaging.md @@ -0,0 +1,2 @@ +appwrite health getQueueMessaging \ + diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-queue-migrations.md b/docs/examples/1.7.x/console-cli/examples/health/get-queue-migrations.md new file mode 100644 index 0000000000..2f17bb56f4 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-queue-migrations.md @@ -0,0 +1,2 @@ +appwrite health getQueueMigrations \ + diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-queue-stats-resources.md b/docs/examples/1.7.x/console-cli/examples/health/get-queue-stats-resources.md new file mode 100644 index 0000000000..9cce963748 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-queue-stats-resources.md @@ -0,0 +1,2 @@ +appwrite health getQueueStatsResources \ + diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-queue-usage.md b/docs/examples/1.7.x/console-cli/examples/health/get-queue-usage.md new file mode 100644 index 0000000000..d021a3faa1 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-queue-usage.md @@ -0,0 +1,2 @@ +appwrite health getQueueUsage \ + diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-queue-webhooks.md b/docs/examples/1.7.x/console-cli/examples/health/get-queue-webhooks.md new file mode 100644 index 0000000000..471175bbe4 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-queue-webhooks.md @@ -0,0 +1,2 @@ +appwrite health getQueueWebhooks \ + diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-storage-local.md b/docs/examples/1.7.x/console-cli/examples/health/get-storage-local.md new file mode 100644 index 0000000000..b5df39fae0 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-storage-local.md @@ -0,0 +1 @@ +appwrite health getStorageLocal diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-storage.md b/docs/examples/1.7.x/console-cli/examples/health/get-storage.md new file mode 100644 index 0000000000..eccd21acc3 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-storage.md @@ -0,0 +1 @@ +appwrite health getStorage diff --git a/docs/examples/1.7.x/console-cli/examples/health/get-time.md b/docs/examples/1.7.x/console-cli/examples/health/get-time.md new file mode 100644 index 0000000000..067e5daf9e --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get-time.md @@ -0,0 +1 @@ +appwrite health getTime diff --git a/docs/examples/1.7.x/console-cli/examples/health/get.md b/docs/examples/1.7.x/console-cli/examples/health/get.md new file mode 100644 index 0000000000..94c08e5aa3 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/health/get.md @@ -0,0 +1 @@ +appwrite health get diff --git a/docs/examples/1.7.x/console-cli/examples/locale/get.md b/docs/examples/1.7.x/console-cli/examples/locale/get.md new file mode 100644 index 0000000000..2002a06c20 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/locale/get.md @@ -0,0 +1 @@ +appwrite locale get diff --git a/docs/examples/1.7.x/console-cli/examples/locale/list-codes.md b/docs/examples/1.7.x/console-cli/examples/locale/list-codes.md new file mode 100644 index 0000000000..5586d1566c --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/locale/list-codes.md @@ -0,0 +1 @@ +appwrite locale listCodes diff --git a/docs/examples/1.7.x/console-cli/examples/locale/list-continents.md b/docs/examples/1.7.x/console-cli/examples/locale/list-continents.md new file mode 100644 index 0000000000..775af5d9df --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/locale/list-continents.md @@ -0,0 +1 @@ +appwrite locale listContinents diff --git a/docs/examples/1.7.x/console-cli/examples/locale/list-countries-e-u.md b/docs/examples/1.7.x/console-cli/examples/locale/list-countries-e-u.md new file mode 100644 index 0000000000..43b7eff7ad --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/locale/list-countries-e-u.md @@ -0,0 +1 @@ +appwrite locale listCountriesEU diff --git a/docs/examples/1.7.x/console-cli/examples/locale/list-countries-phones.md b/docs/examples/1.7.x/console-cli/examples/locale/list-countries-phones.md new file mode 100644 index 0000000000..072516bf71 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/locale/list-countries-phones.md @@ -0,0 +1 @@ +appwrite locale listCountriesPhones diff --git a/docs/examples/1.7.x/console-cli/examples/locale/list-countries.md b/docs/examples/1.7.x/console-cli/examples/locale/list-countries.md new file mode 100644 index 0000000000..ee7101df68 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/locale/list-countries.md @@ -0,0 +1 @@ +appwrite locale listCountries diff --git a/docs/examples/1.7.x/console-cli/examples/locale/list-currencies.md b/docs/examples/1.7.x/console-cli/examples/locale/list-currencies.md new file mode 100644 index 0000000000..01b1b3c4b2 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/locale/list-currencies.md @@ -0,0 +1 @@ +appwrite locale listCurrencies diff --git a/docs/examples/1.7.x/console-cli/examples/locale/list-languages.md b/docs/examples/1.7.x/console-cli/examples/locale/list-languages.md new file mode 100644 index 0000000000..d47622c570 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/locale/list-languages.md @@ -0,0 +1 @@ +appwrite locale listLanguages diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/create-apns-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/create-apns-provider.md new file mode 100644 index 0000000000..8b369f403d --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/create-apns-provider.md @@ -0,0 +1,9 @@ +appwrite messaging createApnsProvider \ + --providerId \ + --name \ + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/create-email.md b/docs/examples/1.7.x/console-cli/examples/messaging/create-email.md new file mode 100644 index 0000000000..2a8e03b7da --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/create-email.md @@ -0,0 +1,13 @@ +appwrite messaging createEmail \ + --messageId \ + --subject \ + --content \ + + + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/create-fcm-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/create-fcm-provider.md new file mode 100644 index 0000000000..a19dcbe28c --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/create-fcm-provider.md @@ -0,0 +1,5 @@ +appwrite messaging createFcmProvider \ + --providerId \ + --name \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/create-mailgun-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/create-mailgun-provider.md new file mode 100644 index 0000000000..6b07359194 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/create-mailgun-provider.md @@ -0,0 +1,11 @@ +appwrite messaging createMailgunProvider \ + --providerId \ + --name \ + + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/create-msg91provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/create-msg91provider.md new file mode 100644 index 0000000000..f687e36472 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/create-msg91provider.md @@ -0,0 +1,7 @@ +appwrite messaging createMsg91Provider \ + --providerId \ + --name \ + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/create-push.md b/docs/examples/1.7.x/console-cli/examples/messaging/create-push.md new file mode 100644 index 0000000000..18d8ec5aec --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/create-push.md @@ -0,0 +1,20 @@ +appwrite messaging createPush \ + --messageId \ + + + + + + + + + + + + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/create-sendgrid-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/create-sendgrid-provider.md new file mode 100644 index 0000000000..de8d059abb --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/create-sendgrid-provider.md @@ -0,0 +1,9 @@ +appwrite messaging createSendgridProvider \ + --providerId \ + --name \ + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/create-sms.md b/docs/examples/1.7.x/console-cli/examples/messaging/create-sms.md new file mode 100644 index 0000000000..dfc9b27ff3 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/create-sms.md @@ -0,0 +1,8 @@ +appwrite messaging createSms \ + --messageId \ + --content \ + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/create-smtp-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/create-smtp-provider.md new file mode 100644 index 0000000000..13f04fe648 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/create-smtp-provider.md @@ -0,0 +1,15 @@ +appwrite messaging createSmtpProvider \ + --providerId \ + --name \ + --host \ + + + + + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/create-subscriber.md b/docs/examples/1.7.x/console-cli/examples/messaging/create-subscriber.md new file mode 100644 index 0000000000..5e65c36df7 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/create-subscriber.md @@ -0,0 +1,4 @@ +appwrite messaging createSubscriber \ + --topicId \ + --subscriberId \ + --targetId diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/create-telesign-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/create-telesign-provider.md new file mode 100644 index 0000000000..783f7594fd --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/create-telesign-provider.md @@ -0,0 +1,7 @@ +appwrite messaging createTelesignProvider \ + --providerId \ + --name \ + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/create-textmagic-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/create-textmagic-provider.md new file mode 100644 index 0000000000..77185c71de --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/create-textmagic-provider.md @@ -0,0 +1,7 @@ +appwrite messaging createTextmagicProvider \ + --providerId \ + --name \ + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/create-topic.md b/docs/examples/1.7.x/console-cli/examples/messaging/create-topic.md new file mode 100644 index 0000000000..1d57e1cee0 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/create-topic.md @@ -0,0 +1,4 @@ +appwrite messaging createTopic \ + --topicId \ + --name \ + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/create-twilio-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/create-twilio-provider.md new file mode 100644 index 0000000000..91fdaae96b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/create-twilio-provider.md @@ -0,0 +1,7 @@ +appwrite messaging createTwilioProvider \ + --providerId \ + --name \ + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/create-vonage-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/create-vonage-provider.md new file mode 100644 index 0000000000..1939d1c04b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/create-vonage-provider.md @@ -0,0 +1,7 @@ +appwrite messaging createVonageProvider \ + --providerId \ + --name \ + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/delete-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/delete-provider.md new file mode 100644 index 0000000000..a93885573c --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/delete-provider.md @@ -0,0 +1,2 @@ +appwrite messaging deleteProvider \ + --providerId diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/delete-subscriber.md b/docs/examples/1.7.x/console-cli/examples/messaging/delete-subscriber.md new file mode 100644 index 0000000000..c535154df6 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/delete-subscriber.md @@ -0,0 +1,3 @@ +appwrite messaging deleteSubscriber \ + --topicId \ + --subscriberId diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/delete-topic.md b/docs/examples/1.7.x/console-cli/examples/messaging/delete-topic.md new file mode 100644 index 0000000000..1fa387c6ab --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/delete-topic.md @@ -0,0 +1,2 @@ +appwrite messaging deleteTopic \ + --topicId diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/delete.md b/docs/examples/1.7.x/console-cli/examples/messaging/delete.md new file mode 100644 index 0000000000..82ff141b03 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/delete.md @@ -0,0 +1,2 @@ +appwrite messaging delete \ + --messageId diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/get-message.md b/docs/examples/1.7.x/console-cli/examples/messaging/get-message.md new file mode 100644 index 0000000000..0144f79699 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/get-message.md @@ -0,0 +1,2 @@ +appwrite messaging getMessage \ + --messageId diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/get-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/get-provider.md new file mode 100644 index 0000000000..9da9f2d864 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/get-provider.md @@ -0,0 +1,2 @@ +appwrite messaging getProvider \ + --providerId diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/get-subscriber.md b/docs/examples/1.7.x/console-cli/examples/messaging/get-subscriber.md new file mode 100644 index 0000000000..02f8bc0e57 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/get-subscriber.md @@ -0,0 +1,3 @@ +appwrite messaging getSubscriber \ + --topicId \ + --subscriberId diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/get-topic.md b/docs/examples/1.7.x/console-cli/examples/messaging/get-topic.md new file mode 100644 index 0000000000..feb2dc66b6 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/get-topic.md @@ -0,0 +1,2 @@ +appwrite messaging getTopic \ + --topicId diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/list-message-logs.md b/docs/examples/1.7.x/console-cli/examples/messaging/list-message-logs.md new file mode 100644 index 0000000000..91366f35f7 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/list-message-logs.md @@ -0,0 +1,3 @@ +appwrite messaging listMessageLogs \ + --messageId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/list-messages.md b/docs/examples/1.7.x/console-cli/examples/messaging/list-messages.md new file mode 100644 index 0000000000..6ab04b0fd2 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/list-messages.md @@ -0,0 +1,3 @@ +appwrite messaging listMessages \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/list-provider-logs.md b/docs/examples/1.7.x/console-cli/examples/messaging/list-provider-logs.md new file mode 100644 index 0000000000..0dee2e3f4b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/list-provider-logs.md @@ -0,0 +1,3 @@ +appwrite messaging listProviderLogs \ + --providerId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/list-providers.md b/docs/examples/1.7.x/console-cli/examples/messaging/list-providers.md new file mode 100644 index 0000000000..0a2ce47a3f --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/list-providers.md @@ -0,0 +1,3 @@ +appwrite messaging listProviders \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/list-subscriber-logs.md b/docs/examples/1.7.x/console-cli/examples/messaging/list-subscriber-logs.md new file mode 100644 index 0000000000..4a04ac4373 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/list-subscriber-logs.md @@ -0,0 +1,3 @@ +appwrite messaging listSubscriberLogs \ + --subscriberId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/list-subscribers.md b/docs/examples/1.7.x/console-cli/examples/messaging/list-subscribers.md new file mode 100644 index 0000000000..2eed8bd3f0 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/list-subscribers.md @@ -0,0 +1,4 @@ +appwrite messaging listSubscribers \ + --topicId \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/list-targets.md b/docs/examples/1.7.x/console-cli/examples/messaging/list-targets.md new file mode 100644 index 0000000000..7efa50ee3b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/list-targets.md @@ -0,0 +1,3 @@ +appwrite messaging listTargets \ + --messageId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/list-topic-logs.md b/docs/examples/1.7.x/console-cli/examples/messaging/list-topic-logs.md new file mode 100644 index 0000000000..f23c10aba6 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/list-topic-logs.md @@ -0,0 +1,3 @@ +appwrite messaging listTopicLogs \ + --topicId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/list-topics.md b/docs/examples/1.7.x/console-cli/examples/messaging/list-topics.md new file mode 100644 index 0000000000..1810a7bd7b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/list-topics.md @@ -0,0 +1,3 @@ +appwrite messaging listTopics \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/update-apns-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/update-apns-provider.md new file mode 100644 index 0000000000..9e895a066a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/update-apns-provider.md @@ -0,0 +1,9 @@ +appwrite messaging updateApnsProvider \ + --providerId \ + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/update-email.md b/docs/examples/1.7.x/console-cli/examples/messaging/update-email.md new file mode 100644 index 0000000000..934fd29213 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/update-email.md @@ -0,0 +1,13 @@ +appwrite messaging updateEmail \ + --messageId \ + + + + + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/update-fcm-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/update-fcm-provider.md new file mode 100644 index 0000000000..000022361f --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/update-fcm-provider.md @@ -0,0 +1,5 @@ +appwrite messaging updateFcmProvider \ + --providerId \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/update-mailgun-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/update-mailgun-provider.md new file mode 100644 index 0000000000..f35c5e9157 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/update-mailgun-provider.md @@ -0,0 +1,11 @@ +appwrite messaging updateMailgunProvider \ + --providerId \ + + + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/update-msg91provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/update-msg91provider.md new file mode 100644 index 0000000000..8e2d604a19 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/update-msg91provider.md @@ -0,0 +1,7 @@ +appwrite messaging updateMsg91Provider \ + --providerId \ + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/update-push.md b/docs/examples/1.7.x/console-cli/examples/messaging/update-push.md new file mode 100644 index 0000000000..1f4427cee7 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/update-push.md @@ -0,0 +1,20 @@ +appwrite messaging updatePush \ + --messageId \ + + + + + + + + + + + + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/update-sendgrid-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/update-sendgrid-provider.md new file mode 100644 index 0000000000..7f2e97dbf7 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/update-sendgrid-provider.md @@ -0,0 +1,9 @@ +appwrite messaging updateSendgridProvider \ + --providerId \ + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/update-sms.md b/docs/examples/1.7.x/console-cli/examples/messaging/update-sms.md new file mode 100644 index 0000000000..a30ff43d0c --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/update-sms.md @@ -0,0 +1,8 @@ +appwrite messaging updateSms \ + --messageId \ + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/update-smtp-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/update-smtp-provider.md new file mode 100644 index 0000000000..4e0f7b6b8d --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/update-smtp-provider.md @@ -0,0 +1,15 @@ +appwrite messaging updateSmtpProvider \ + --providerId \ + + + + + + + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/update-telesign-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/update-telesign-provider.md new file mode 100644 index 0000000000..0a92f2cacd --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/update-telesign-provider.md @@ -0,0 +1,7 @@ +appwrite messaging updateTelesignProvider \ + --providerId \ + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/update-textmagic-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/update-textmagic-provider.md new file mode 100644 index 0000000000..79160b2461 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/update-textmagic-provider.md @@ -0,0 +1,7 @@ +appwrite messaging updateTextmagicProvider \ + --providerId \ + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/update-topic.md b/docs/examples/1.7.x/console-cli/examples/messaging/update-topic.md new file mode 100644 index 0000000000..d10b0edde3 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/update-topic.md @@ -0,0 +1,4 @@ +appwrite messaging updateTopic \ + --topicId \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/update-twilio-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/update-twilio-provider.md new file mode 100644 index 0000000000..c967d724af --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/update-twilio-provider.md @@ -0,0 +1,7 @@ +appwrite messaging updateTwilioProvider \ + --providerId \ + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/messaging/update-vonage-provider.md b/docs/examples/1.7.x/console-cli/examples/messaging/update-vonage-provider.md new file mode 100644 index 0000000000..11f7963be2 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/messaging/update-vonage-provider.md @@ -0,0 +1,7 @@ +appwrite messaging updateVonageProvider \ + --providerId \ + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/migrations/create-appwrite-migration.md b/docs/examples/1.7.x/console-cli/examples/migrations/create-appwrite-migration.md new file mode 100644 index 0000000000..73e9ee62d8 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/migrations/create-appwrite-migration.md @@ -0,0 +1,5 @@ +appwrite migrations createAppwriteMigration \ + --resources one two three \ + --endpoint https://example.com \ + --projectId \ + --apiKey diff --git a/docs/examples/1.7.x/console-cli/examples/migrations/create-csv-migration.md b/docs/examples/1.7.x/console-cli/examples/migrations/create-csv-migration.md new file mode 100644 index 0000000000..594bc85052 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/migrations/create-csv-migration.md @@ -0,0 +1,4 @@ +appwrite migrations createCsvMigration \ + --bucketId \ + --fileId \ + --resourceId [ID1:ID2] diff --git a/docs/examples/1.7.x/console-cli/examples/migrations/create-firebase-migration.md b/docs/examples/1.7.x/console-cli/examples/migrations/create-firebase-migration.md new file mode 100644 index 0000000000..3dfb3aeac6 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/migrations/create-firebase-migration.md @@ -0,0 +1,3 @@ +appwrite migrations createFirebaseMigration \ + --resources one two three \ + --serviceAccount diff --git a/docs/examples/1.7.x/console-cli/examples/migrations/create-n-host-migration.md b/docs/examples/1.7.x/console-cli/examples/migrations/create-n-host-migration.md new file mode 100644 index 0000000000..d959897109 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/migrations/create-n-host-migration.md @@ -0,0 +1,9 @@ +appwrite migrations createNHostMigration \ + --resources one two three \ + --subdomain \ + --region \ + --adminSecret \ + --database \ + --username \ + --password \ + diff --git a/docs/examples/1.7.x/console-cli/examples/migrations/create-supabase-migration.md b/docs/examples/1.7.x/console-cli/examples/migrations/create-supabase-migration.md new file mode 100644 index 0000000000..0620f3ba2e --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/migrations/create-supabase-migration.md @@ -0,0 +1,8 @@ +appwrite migrations createSupabaseMigration \ + --resources one two three \ + --endpoint https://example.com \ + --apiKey \ + --databaseHost \ + --username \ + --password \ + diff --git a/docs/examples/1.7.x/console-cli/examples/migrations/delete.md b/docs/examples/1.7.x/console-cli/examples/migrations/delete.md new file mode 100644 index 0000000000..9dac1aa3db --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/migrations/delete.md @@ -0,0 +1,2 @@ +appwrite migrations delete \ + --migrationId diff --git a/docs/examples/1.7.x/console-cli/examples/migrations/get-appwrite-report.md b/docs/examples/1.7.x/console-cli/examples/migrations/get-appwrite-report.md new file mode 100644 index 0000000000..745e9fb98c --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/migrations/get-appwrite-report.md @@ -0,0 +1,5 @@ +appwrite migrations getAppwriteReport \ + --resources one two three \ + --endpoint https://example.com \ + --projectID \ + --key diff --git a/docs/examples/1.7.x/console-cli/examples/migrations/get-firebase-report.md b/docs/examples/1.7.x/console-cli/examples/migrations/get-firebase-report.md new file mode 100644 index 0000000000..73c7e1ca14 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/migrations/get-firebase-report.md @@ -0,0 +1,3 @@ +appwrite migrations getFirebaseReport \ + --resources one two three \ + --serviceAccount diff --git a/docs/examples/1.7.x/console-cli/examples/migrations/get-n-host-report.md b/docs/examples/1.7.x/console-cli/examples/migrations/get-n-host-report.md new file mode 100644 index 0000000000..6b7e2eaff2 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/migrations/get-n-host-report.md @@ -0,0 +1,9 @@ +appwrite migrations getNHostReport \ + --resources one two three \ + --subdomain \ + --region \ + --adminSecret \ + --database \ + --username \ + --password \ + diff --git a/docs/examples/1.7.x/console-cli/examples/migrations/get-supabase-report.md b/docs/examples/1.7.x/console-cli/examples/migrations/get-supabase-report.md new file mode 100644 index 0000000000..9754f38e24 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/migrations/get-supabase-report.md @@ -0,0 +1,8 @@ +appwrite migrations getSupabaseReport \ + --resources one two three \ + --endpoint https://example.com \ + --apiKey \ + --databaseHost \ + --username \ + --password \ + diff --git a/docs/examples/1.7.x/console-cli/examples/migrations/get.md b/docs/examples/1.7.x/console-cli/examples/migrations/get.md new file mode 100644 index 0000000000..8810646c7e --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/migrations/get.md @@ -0,0 +1,2 @@ +appwrite migrations get \ + --migrationId diff --git a/docs/examples/1.7.x/console-cli/examples/migrations/list.md b/docs/examples/1.7.x/console-cli/examples/migrations/list.md new file mode 100644 index 0000000000..c120a61e80 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/migrations/list.md @@ -0,0 +1,3 @@ +appwrite migrations list \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/migrations/retry.md b/docs/examples/1.7.x/console-cli/examples/migrations/retry.md new file mode 100644 index 0000000000..518f86cee7 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/migrations/retry.md @@ -0,0 +1,2 @@ +appwrite migrations retry \ + --migrationId diff --git a/docs/examples/1.7.x/console-cli/examples/project/create-variable.md b/docs/examples/1.7.x/console-cli/examples/project/create-variable.md new file mode 100644 index 0000000000..253d6ddf75 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/project/create-variable.md @@ -0,0 +1,4 @@ +appwrite project createVariable \ + --key \ + --value \ + diff --git a/docs/examples/1.7.x/console-cli/examples/project/delete-variable.md b/docs/examples/1.7.x/console-cli/examples/project/delete-variable.md new file mode 100644 index 0000000000..7fdda874fd --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/project/delete-variable.md @@ -0,0 +1,2 @@ +appwrite project deleteVariable \ + --variableId diff --git a/docs/examples/1.7.x/console-cli/examples/project/get-usage.md b/docs/examples/1.7.x/console-cli/examples/project/get-usage.md new file mode 100644 index 0000000000..9b4c296a8c --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/project/get-usage.md @@ -0,0 +1,4 @@ +appwrite project getUsage \ + --startDate '' \ + --endDate '' \ + diff --git a/docs/examples/1.7.x/console-cli/examples/project/get-variable.md b/docs/examples/1.7.x/console-cli/examples/project/get-variable.md new file mode 100644 index 0000000000..b2d482586b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/project/get-variable.md @@ -0,0 +1,2 @@ +appwrite project getVariable \ + --variableId diff --git a/docs/examples/1.7.x/console-cli/examples/project/list-variables.md b/docs/examples/1.7.x/console-cli/examples/project/list-variables.md new file mode 100644 index 0000000000..bd26c7db6b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/project/list-variables.md @@ -0,0 +1 @@ +appwrite project listVariables diff --git a/docs/examples/1.7.x/console-cli/examples/project/update-variable.md b/docs/examples/1.7.x/console-cli/examples/project/update-variable.md new file mode 100644 index 0000000000..4365b64888 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/project/update-variable.md @@ -0,0 +1,5 @@ +appwrite project updateVariable \ + --variableId \ + --key \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/projects/create-dev-key.md b/docs/examples/1.7.x/console-cli/examples/projects/create-dev-key.md new file mode 100644 index 0000000000..8b9ec8969a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/create-dev-key.md @@ -0,0 +1,4 @@ +appwrite projects createDevKey \ + --projectId \ + --name \ + --expire '' diff --git a/docs/examples/1.7.x/console-cli/examples/projects/create-j-w-t.md b/docs/examples/1.7.x/console-cli/examples/projects/create-j-w-t.md new file mode 100644 index 0000000000..d703d36b65 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/create-j-w-t.md @@ -0,0 +1,4 @@ +appwrite projects createJWT \ + --projectId \ + --scopes one two three \ + diff --git a/docs/examples/1.7.x/console-cli/examples/projects/create-key.md b/docs/examples/1.7.x/console-cli/examples/projects/create-key.md new file mode 100644 index 0000000000..fb986dcebc --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/create-key.md @@ -0,0 +1,5 @@ +appwrite projects createKey \ + --projectId \ + --name \ + --scopes one two three \ + diff --git a/docs/examples/1.7.x/console-cli/examples/projects/create-platform.md b/docs/examples/1.7.x/console-cli/examples/projects/create-platform.md new file mode 100644 index 0000000000..8727d21d64 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/create-platform.md @@ -0,0 +1,7 @@ +appwrite projects createPlatform \ + --projectId \ + --type web \ + --name \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/projects/create-smtp-test.md b/docs/examples/1.7.x/console-cli/examples/projects/create-smtp-test.md new file mode 100644 index 0000000000..66ce5880aa --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/create-smtp-test.md @@ -0,0 +1,11 @@ +appwrite projects createSmtpTest \ + --projectId \ + --emails one two three \ + --senderName \ + --senderEmail email@example.com \ + --host '' \ + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/projects/create-webhook.md b/docs/examples/1.7.x/console-cli/examples/projects/create-webhook.md new file mode 100644 index 0000000000..03ecf4110d --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/create-webhook.md @@ -0,0 +1,9 @@ +appwrite projects createWebhook \ + --projectId \ + --name \ + --events one two three \ + --url '' \ + --security false \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/projects/create.md b/docs/examples/1.7.x/console-cli/examples/projects/create.md new file mode 100644 index 0000000000..0504785503 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/create.md @@ -0,0 +1,14 @@ +appwrite projects create \ + --projectId '' \ + --name \ + --teamId \ + + + + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/projects/delete-dev-key.md b/docs/examples/1.7.x/console-cli/examples/projects/delete-dev-key.md new file mode 100644 index 0000000000..2859a3309f --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/delete-dev-key.md @@ -0,0 +1,3 @@ +appwrite projects deleteDevKey \ + --projectId \ + --keyId diff --git a/docs/examples/1.7.x/console-cli/examples/projects/delete-email-template.md b/docs/examples/1.7.x/console-cli/examples/projects/delete-email-template.md new file mode 100644 index 0000000000..01ce0fac68 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/delete-email-template.md @@ -0,0 +1,4 @@ +appwrite projects deleteEmailTemplate \ + --projectId \ + --type verification \ + --locale af diff --git a/docs/examples/1.7.x/console-cli/examples/projects/delete-key.md b/docs/examples/1.7.x/console-cli/examples/projects/delete-key.md new file mode 100644 index 0000000000..6baf05706e --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/delete-key.md @@ -0,0 +1,3 @@ +appwrite projects deleteKey \ + --projectId \ + --keyId diff --git a/docs/examples/1.7.x/console-cli/examples/projects/delete-platform.md b/docs/examples/1.7.x/console-cli/examples/projects/delete-platform.md new file mode 100644 index 0000000000..a85bd865ba --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/delete-platform.md @@ -0,0 +1,3 @@ +appwrite projects deletePlatform \ + --projectId \ + --platformId diff --git a/docs/examples/1.7.x/console-cli/examples/projects/delete-sms-template.md b/docs/examples/1.7.x/console-cli/examples/projects/delete-sms-template.md new file mode 100644 index 0000000000..3afcf649c7 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/delete-sms-template.md @@ -0,0 +1,4 @@ +appwrite projects deleteSmsTemplate \ + --projectId \ + --type verification \ + --locale af diff --git a/docs/examples/1.7.x/console-cli/examples/projects/delete-webhook.md b/docs/examples/1.7.x/console-cli/examples/projects/delete-webhook.md new file mode 100644 index 0000000000..a67301ef07 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/delete-webhook.md @@ -0,0 +1,3 @@ +appwrite projects deleteWebhook \ + --projectId \ + --webhookId diff --git a/docs/examples/1.7.x/console-cli/examples/projects/delete.md b/docs/examples/1.7.x/console-cli/examples/projects/delete.md new file mode 100644 index 0000000000..a4ffc70c91 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/delete.md @@ -0,0 +1,2 @@ +appwrite projects delete \ + --projectId diff --git a/docs/examples/1.7.x/console-cli/examples/projects/get-dev-key.md b/docs/examples/1.7.x/console-cli/examples/projects/get-dev-key.md new file mode 100644 index 0000000000..cfc37ed437 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/get-dev-key.md @@ -0,0 +1,3 @@ +appwrite projects getDevKey \ + --projectId \ + --keyId diff --git a/docs/examples/1.7.x/console-cli/examples/projects/get-email-template.md b/docs/examples/1.7.x/console-cli/examples/projects/get-email-template.md new file mode 100644 index 0000000000..6e4c21e52b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/get-email-template.md @@ -0,0 +1,4 @@ +appwrite projects getEmailTemplate \ + --projectId \ + --type verification \ + --locale af diff --git a/docs/examples/1.7.x/console-cli/examples/projects/get-key.md b/docs/examples/1.7.x/console-cli/examples/projects/get-key.md new file mode 100644 index 0000000000..f69b51bbe2 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/get-key.md @@ -0,0 +1,3 @@ +appwrite projects getKey \ + --projectId \ + --keyId diff --git a/docs/examples/1.7.x/console-cli/examples/projects/get-platform.md b/docs/examples/1.7.x/console-cli/examples/projects/get-platform.md new file mode 100644 index 0000000000..67648be035 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/get-platform.md @@ -0,0 +1,3 @@ +appwrite projects getPlatform \ + --projectId \ + --platformId diff --git a/docs/examples/1.7.x/console-cli/examples/projects/get-sms-template.md b/docs/examples/1.7.x/console-cli/examples/projects/get-sms-template.md new file mode 100644 index 0000000000..c655953c8e --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/get-sms-template.md @@ -0,0 +1,4 @@ +appwrite projects getSmsTemplate \ + --projectId \ + --type verification \ + --locale af diff --git a/docs/examples/1.7.x/console-cli/examples/projects/get-webhook.md b/docs/examples/1.7.x/console-cli/examples/projects/get-webhook.md new file mode 100644 index 0000000000..890bf37069 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/get-webhook.md @@ -0,0 +1,3 @@ +appwrite projects getWebhook \ + --projectId \ + --webhookId diff --git a/docs/examples/1.7.x/console-cli/examples/projects/get.md b/docs/examples/1.7.x/console-cli/examples/projects/get.md new file mode 100644 index 0000000000..919321b81d --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/get.md @@ -0,0 +1,2 @@ +appwrite projects get \ + --projectId diff --git a/docs/examples/1.7.x/console-cli/examples/projects/list-dev-keys.md b/docs/examples/1.7.x/console-cli/examples/projects/list-dev-keys.md new file mode 100644 index 0000000000..d552cb3bca --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/list-dev-keys.md @@ -0,0 +1,3 @@ +appwrite projects listDevKeys \ + --projectId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/projects/list-keys.md b/docs/examples/1.7.x/console-cli/examples/projects/list-keys.md new file mode 100644 index 0000000000..cc37680b5b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/list-keys.md @@ -0,0 +1,2 @@ +appwrite projects listKeys \ + --projectId diff --git a/docs/examples/1.7.x/console-cli/examples/projects/list-platforms.md b/docs/examples/1.7.x/console-cli/examples/projects/list-platforms.md new file mode 100644 index 0000000000..5fc2ea4106 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/list-platforms.md @@ -0,0 +1,2 @@ +appwrite projects listPlatforms \ + --projectId diff --git a/docs/examples/1.7.x/console-cli/examples/projects/list-webhooks.md b/docs/examples/1.7.x/console-cli/examples/projects/list-webhooks.md new file mode 100644 index 0000000000..dcf9953f80 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/list-webhooks.md @@ -0,0 +1,2 @@ +appwrite projects listWebhooks \ + --projectId diff --git a/docs/examples/1.7.x/console-cli/examples/projects/list.md b/docs/examples/1.7.x/console-cli/examples/projects/list.md new file mode 100644 index 0000000000..0d3dd7a539 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/list.md @@ -0,0 +1,3 @@ +appwrite projects list \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-api-status-all.md b/docs/examples/1.7.x/console-cli/examples/projects/update-api-status-all.md new file mode 100644 index 0000000000..e5f63c59a3 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-api-status-all.md @@ -0,0 +1,3 @@ +appwrite projects updateApiStatusAll \ + --projectId \ + --status false diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-api-status.md b/docs/examples/1.7.x/console-cli/examples/projects/update-api-status.md new file mode 100644 index 0000000000..01120957af --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-api-status.md @@ -0,0 +1,4 @@ +appwrite projects updateApiStatus \ + --projectId \ + --api rest \ + --status false diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-auth-duration.md b/docs/examples/1.7.x/console-cli/examples/projects/update-auth-duration.md new file mode 100644 index 0000000000..ad6f8ac97c --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-auth-duration.md @@ -0,0 +1,3 @@ +appwrite projects updateAuthDuration \ + --projectId \ + --duration 0 diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-auth-limit.md b/docs/examples/1.7.x/console-cli/examples/projects/update-auth-limit.md new file mode 100644 index 0000000000..9d01fa5a1a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-auth-limit.md @@ -0,0 +1,3 @@ +appwrite projects updateAuthLimit \ + --projectId \ + --limit 0 diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-auth-password-dictionary.md b/docs/examples/1.7.x/console-cli/examples/projects/update-auth-password-dictionary.md new file mode 100644 index 0000000000..f477bba56d --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-auth-password-dictionary.md @@ -0,0 +1,3 @@ +appwrite projects updateAuthPasswordDictionary \ + --projectId \ + --enabled false diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-auth-password-history.md b/docs/examples/1.7.x/console-cli/examples/projects/update-auth-password-history.md new file mode 100644 index 0000000000..8b9b90a32a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-auth-password-history.md @@ -0,0 +1,3 @@ +appwrite projects updateAuthPasswordHistory \ + --projectId \ + --limit 0 diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-auth-sessions-limit.md b/docs/examples/1.7.x/console-cli/examples/projects/update-auth-sessions-limit.md new file mode 100644 index 0000000000..2a1294d17b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-auth-sessions-limit.md @@ -0,0 +1,3 @@ +appwrite projects updateAuthSessionsLimit \ + --projectId \ + --limit 1 diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-auth-status.md b/docs/examples/1.7.x/console-cli/examples/projects/update-auth-status.md new file mode 100644 index 0000000000..848987b2f8 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-auth-status.md @@ -0,0 +1,4 @@ +appwrite projects updateAuthStatus \ + --projectId \ + --method email-password \ + --status false diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-dev-key.md b/docs/examples/1.7.x/console-cli/examples/projects/update-dev-key.md new file mode 100644 index 0000000000..cc95030389 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-dev-key.md @@ -0,0 +1,5 @@ +appwrite projects updateDevKey \ + --projectId \ + --keyId \ + --name \ + --expire '' diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-email-template.md b/docs/examples/1.7.x/console-cli/examples/projects/update-email-template.md new file mode 100644 index 0000000000..a3acd066ec --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-email-template.md @@ -0,0 +1,9 @@ +appwrite projects updateEmailTemplate \ + --projectId \ + --type verification \ + --locale af \ + --subject \ + --message \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-key.md b/docs/examples/1.7.x/console-cli/examples/projects/update-key.md new file mode 100644 index 0000000000..6d3dc198da --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-key.md @@ -0,0 +1,6 @@ +appwrite projects updateKey \ + --projectId \ + --keyId \ + --name \ + --scopes one two three \ + diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-memberships-privacy.md b/docs/examples/1.7.x/console-cli/examples/projects/update-memberships-privacy.md new file mode 100644 index 0000000000..6c811ccfce --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-memberships-privacy.md @@ -0,0 +1,5 @@ +appwrite projects updateMembershipsPrivacy \ + --projectId \ + --userName false \ + --userEmail false \ + --mfa false diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-mock-numbers.md b/docs/examples/1.7.x/console-cli/examples/projects/update-mock-numbers.md new file mode 100644 index 0000000000..733cc16887 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-mock-numbers.md @@ -0,0 +1,3 @@ +appwrite projects updateMockNumbers \ + --projectId \ + --numbers one two three diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-o-auth2.md b/docs/examples/1.7.x/console-cli/examples/projects/update-o-auth2.md new file mode 100644 index 0000000000..92f6718962 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-o-auth2.md @@ -0,0 +1,6 @@ +appwrite projects updateOAuth2 \ + --projectId \ + --provider amazon \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-personal-data-check.md b/docs/examples/1.7.x/console-cli/examples/projects/update-personal-data-check.md new file mode 100644 index 0000000000..21dca78369 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-personal-data-check.md @@ -0,0 +1,3 @@ +appwrite projects updatePersonalDataCheck \ + --projectId \ + --enabled false diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-platform.md b/docs/examples/1.7.x/console-cli/examples/projects/update-platform.md new file mode 100644 index 0000000000..05b1602ae9 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-platform.md @@ -0,0 +1,7 @@ +appwrite projects updatePlatform \ + --projectId \ + --platformId \ + --name \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-service-status-all.md b/docs/examples/1.7.x/console-cli/examples/projects/update-service-status-all.md new file mode 100644 index 0000000000..1ffb77e085 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-service-status-all.md @@ -0,0 +1,3 @@ +appwrite projects updateServiceStatusAll \ + --projectId \ + --status false diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-service-status.md b/docs/examples/1.7.x/console-cli/examples/projects/update-service-status.md new file mode 100644 index 0000000000..03963a1214 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-service-status.md @@ -0,0 +1,4 @@ +appwrite projects updateServiceStatus \ + --projectId \ + --service account \ + --status false diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-session-alerts.md b/docs/examples/1.7.x/console-cli/examples/projects/update-session-alerts.md new file mode 100644 index 0000000000..bd23b7417a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-session-alerts.md @@ -0,0 +1,3 @@ +appwrite projects updateSessionAlerts \ + --projectId \ + --alerts false diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-sms-template.md b/docs/examples/1.7.x/console-cli/examples/projects/update-sms-template.md new file mode 100644 index 0000000000..fc8310eb25 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-sms-template.md @@ -0,0 +1,5 @@ +appwrite projects updateSmsTemplate \ + --projectId \ + --type verification \ + --locale af \ + --message diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-smtp.md b/docs/examples/1.7.x/console-cli/examples/projects/update-smtp.md new file mode 100644 index 0000000000..0afbe9cec9 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-smtp.md @@ -0,0 +1,11 @@ +appwrite projects updateSmtp \ + --projectId \ + --enabled false \ + + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-team.md b/docs/examples/1.7.x/console-cli/examples/projects/update-team.md new file mode 100644 index 0000000000..49214ad9f3 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-team.md @@ -0,0 +1,3 @@ +appwrite projects updateTeam \ + --projectId \ + --teamId diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-webhook-signature.md b/docs/examples/1.7.x/console-cli/examples/projects/update-webhook-signature.md new file mode 100644 index 0000000000..6034ef01f6 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-webhook-signature.md @@ -0,0 +1,3 @@ +appwrite projects updateWebhookSignature \ + --projectId \ + --webhookId diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update-webhook.md b/docs/examples/1.7.x/console-cli/examples/projects/update-webhook.md new file mode 100644 index 0000000000..51c536d74c --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update-webhook.md @@ -0,0 +1,10 @@ +appwrite projects updateWebhook \ + --projectId \ + --webhookId \ + --name \ + --events one two three \ + --url '' \ + --security false \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/projects/update.md b/docs/examples/1.7.x/console-cli/examples/projects/update.md new file mode 100644 index 0000000000..d4df289636 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/projects/update.md @@ -0,0 +1,12 @@ +appwrite projects update \ + --projectId \ + --name \ + + + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/proxy/create-a-p-i-rule.md b/docs/examples/1.7.x/console-cli/examples/proxy/create-a-p-i-rule.md new file mode 100644 index 0000000000..5746b94b1e --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/proxy/create-a-p-i-rule.md @@ -0,0 +1,2 @@ +appwrite proxy createAPIRule \ + --domain '' diff --git a/docs/examples/1.7.x/console-cli/examples/proxy/create-function-rule.md b/docs/examples/1.7.x/console-cli/examples/proxy/create-function-rule.md new file mode 100644 index 0000000000..380650c208 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/proxy/create-function-rule.md @@ -0,0 +1,4 @@ +appwrite proxy createFunctionRule \ + --domain '' \ + --functionId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/proxy/create-redirect-rule.md b/docs/examples/1.7.x/console-cli/examples/proxy/create-redirect-rule.md new file mode 100644 index 0000000000..f975ce686e --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/proxy/create-redirect-rule.md @@ -0,0 +1,4 @@ +appwrite proxy createRedirectRule \ + --domain '' \ + --url https://example.com \ + --statusCode 301 diff --git a/docs/examples/1.7.x/console-cli/examples/proxy/create-site-rule.md b/docs/examples/1.7.x/console-cli/examples/proxy/create-site-rule.md new file mode 100644 index 0000000000..eb41bd7158 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/proxy/create-site-rule.md @@ -0,0 +1,4 @@ +appwrite proxy createSiteRule \ + --domain '' \ + --siteId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/proxy/delete-rule.md b/docs/examples/1.7.x/console-cli/examples/proxy/delete-rule.md new file mode 100644 index 0000000000..b11b6ca23e --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/proxy/delete-rule.md @@ -0,0 +1,2 @@ +appwrite proxy deleteRule \ + --ruleId diff --git a/docs/examples/1.7.x/console-cli/examples/proxy/get-rule.md b/docs/examples/1.7.x/console-cli/examples/proxy/get-rule.md new file mode 100644 index 0000000000..85d11a50b1 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/proxy/get-rule.md @@ -0,0 +1,2 @@ +appwrite proxy getRule \ + --ruleId diff --git a/docs/examples/1.7.x/console-cli/examples/proxy/list-rules.md b/docs/examples/1.7.x/console-cli/examples/proxy/list-rules.md new file mode 100644 index 0000000000..bc654bac5c --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/proxy/list-rules.md @@ -0,0 +1,3 @@ +appwrite proxy listRules \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/proxy/update-rule-verification.md b/docs/examples/1.7.x/console-cli/examples/proxy/update-rule-verification.md new file mode 100644 index 0000000000..8200d15702 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/proxy/update-rule-verification.md @@ -0,0 +1,2 @@ +appwrite proxy updateRuleVerification \ + --ruleId diff --git a/docs/examples/1.7.x/console-cli/examples/sites/create-deployment.md b/docs/examples/1.7.x/console-cli/examples/sites/create-deployment.md new file mode 100644 index 0000000000..a83d7f3cfe --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/create-deployment.md @@ -0,0 +1,7 @@ +appwrite sites createDeployment \ + --siteId \ + --code 'path/to/file.png' \ + --activate false \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/sites/create-duplicate-deployment.md b/docs/examples/1.7.x/console-cli/examples/sites/create-duplicate-deployment.md new file mode 100644 index 0000000000..bab63ca8a3 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/create-duplicate-deployment.md @@ -0,0 +1,3 @@ +appwrite sites createDuplicateDeployment \ + --siteId \ + --deploymentId diff --git a/docs/examples/1.7.x/console-cli/examples/sites/create-template-deployment.md b/docs/examples/1.7.x/console-cli/examples/sites/create-template-deployment.md new file mode 100644 index 0000000000..2aaaf445db --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/create-template-deployment.md @@ -0,0 +1,7 @@ +appwrite sites createTemplateDeployment \ + --siteId \ + --repository \ + --owner \ + --rootDirectory \ + --version \ + diff --git a/docs/examples/1.7.x/console-cli/examples/sites/create-variable.md b/docs/examples/1.7.x/console-cli/examples/sites/create-variable.md new file mode 100644 index 0000000000..b640321317 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/create-variable.md @@ -0,0 +1,5 @@ +appwrite sites createVariable \ + --siteId \ + --key \ + --value \ + diff --git a/docs/examples/1.7.x/console-cli/examples/sites/create-vcs-deployment.md b/docs/examples/1.7.x/console-cli/examples/sites/create-vcs-deployment.md new file mode 100644 index 0000000000..85c96f93ec --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/create-vcs-deployment.md @@ -0,0 +1,5 @@ +appwrite sites createVcsDeployment \ + --siteId \ + --type branch \ + --reference \ + diff --git a/docs/examples/1.7.x/console-cli/examples/sites/create.md b/docs/examples/1.7.x/console-cli/examples/sites/create.md new file mode 100644 index 0000000000..bd7e86e70f --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/create.md @@ -0,0 +1,19 @@ +appwrite sites create \ + --siteId \ + --name \ + --framework analog \ + --buildRuntime node-14.5 \ + + + + + + + + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/sites/delete-deployment.md b/docs/examples/1.7.x/console-cli/examples/sites/delete-deployment.md new file mode 100644 index 0000000000..c1cbf49637 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/delete-deployment.md @@ -0,0 +1,3 @@ +appwrite sites deleteDeployment \ + --siteId \ + --deploymentId diff --git a/docs/examples/1.7.x/console-cli/examples/sites/delete-log.md b/docs/examples/1.7.x/console-cli/examples/sites/delete-log.md new file mode 100644 index 0000000000..6769be255c --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/delete-log.md @@ -0,0 +1,3 @@ +appwrite sites deleteLog \ + --siteId \ + --logId diff --git a/docs/examples/1.7.x/console-cli/examples/sites/delete-variable.md b/docs/examples/1.7.x/console-cli/examples/sites/delete-variable.md new file mode 100644 index 0000000000..60d9ecf4eb --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/delete-variable.md @@ -0,0 +1,3 @@ +appwrite sites deleteVariable \ + --siteId \ + --variableId diff --git a/docs/examples/1.7.x/console-cli/examples/sites/delete.md b/docs/examples/1.7.x/console-cli/examples/sites/delete.md new file mode 100644 index 0000000000..9071454850 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/delete.md @@ -0,0 +1,2 @@ +appwrite sites delete \ + --siteId diff --git a/docs/examples/1.7.x/console-cli/examples/sites/get-deployment-download.md b/docs/examples/1.7.x/console-cli/examples/sites/get-deployment-download.md new file mode 100644 index 0000000000..1fae298796 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/get-deployment-download.md @@ -0,0 +1,4 @@ +appwrite sites getDeploymentDownload \ + --siteId \ + --deploymentId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/sites/get-deployment.md b/docs/examples/1.7.x/console-cli/examples/sites/get-deployment.md new file mode 100644 index 0000000000..93680ff70d --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/get-deployment.md @@ -0,0 +1,3 @@ +appwrite sites getDeployment \ + --siteId \ + --deploymentId diff --git a/docs/examples/1.7.x/console-cli/examples/sites/get-log.md b/docs/examples/1.7.x/console-cli/examples/sites/get-log.md new file mode 100644 index 0000000000..7867aba05e --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/get-log.md @@ -0,0 +1,3 @@ +appwrite sites getLog \ + --siteId \ + --logId diff --git a/docs/examples/1.7.x/console-cli/examples/sites/get-template.md b/docs/examples/1.7.x/console-cli/examples/sites/get-template.md new file mode 100644 index 0000000000..e04dd2e120 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/get-template.md @@ -0,0 +1,2 @@ +appwrite sites getTemplate \ + --templateId diff --git a/docs/examples/1.7.x/console-cli/examples/sites/get-usage.md b/docs/examples/1.7.x/console-cli/examples/sites/get-usage.md new file mode 100644 index 0000000000..6de7d6bde8 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/get-usage.md @@ -0,0 +1,3 @@ +appwrite sites getUsage \ + --siteId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/sites/get-variable.md b/docs/examples/1.7.x/console-cli/examples/sites/get-variable.md new file mode 100644 index 0000000000..b60b577c38 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/get-variable.md @@ -0,0 +1,3 @@ +appwrite sites getVariable \ + --siteId \ + --variableId diff --git a/docs/examples/1.7.x/console-cli/examples/sites/get.md b/docs/examples/1.7.x/console-cli/examples/sites/get.md new file mode 100644 index 0000000000..7922efa5f0 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/get.md @@ -0,0 +1,2 @@ +appwrite sites get \ + --siteId diff --git a/docs/examples/1.7.x/console-cli/examples/sites/list-deployments.md b/docs/examples/1.7.x/console-cli/examples/sites/list-deployments.md new file mode 100644 index 0000000000..5ab2cdc104 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/list-deployments.md @@ -0,0 +1,4 @@ +appwrite sites listDeployments \ + --siteId \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/sites/list-frameworks.md b/docs/examples/1.7.x/console-cli/examples/sites/list-frameworks.md new file mode 100644 index 0000000000..1d9b6b4b87 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/list-frameworks.md @@ -0,0 +1 @@ +appwrite sites listFrameworks diff --git a/docs/examples/1.7.x/console-cli/examples/sites/list-logs.md b/docs/examples/1.7.x/console-cli/examples/sites/list-logs.md new file mode 100644 index 0000000000..f13864fe6b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/list-logs.md @@ -0,0 +1,3 @@ +appwrite sites listLogs \ + --siteId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/sites/list-specifications.md b/docs/examples/1.7.x/console-cli/examples/sites/list-specifications.md new file mode 100644 index 0000000000..dc1a16c9dc --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/list-specifications.md @@ -0,0 +1 @@ +appwrite sites listSpecifications diff --git a/docs/examples/1.7.x/console-cli/examples/sites/list-templates.md b/docs/examples/1.7.x/console-cli/examples/sites/list-templates.md new file mode 100644 index 0000000000..9d93913d94 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/list-templates.md @@ -0,0 +1,5 @@ +appwrite sites listTemplates \ + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/sites/list-usage.md b/docs/examples/1.7.x/console-cli/examples/sites/list-usage.md new file mode 100644 index 0000000000..a6f43f61e7 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/list-usage.md @@ -0,0 +1,2 @@ +appwrite sites listUsage \ + diff --git a/docs/examples/1.7.x/console-cli/examples/sites/list-variables.md b/docs/examples/1.7.x/console-cli/examples/sites/list-variables.md new file mode 100644 index 0000000000..13a258b054 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/list-variables.md @@ -0,0 +1,2 @@ +appwrite sites listVariables \ + --siteId diff --git a/docs/examples/1.7.x/console-cli/examples/sites/list.md b/docs/examples/1.7.x/console-cli/examples/sites/list.md new file mode 100644 index 0000000000..0cad70e894 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/list.md @@ -0,0 +1,3 @@ +appwrite sites list \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/sites/update-deployment-status.md b/docs/examples/1.7.x/console-cli/examples/sites/update-deployment-status.md new file mode 100644 index 0000000000..7923b384f6 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/update-deployment-status.md @@ -0,0 +1,3 @@ +appwrite sites updateDeploymentStatus \ + --siteId \ + --deploymentId diff --git a/docs/examples/1.7.x/console-cli/examples/sites/update-site-deployment.md b/docs/examples/1.7.x/console-cli/examples/sites/update-site-deployment.md new file mode 100644 index 0000000000..de877d8ae7 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/update-site-deployment.md @@ -0,0 +1,3 @@ +appwrite sites updateSiteDeployment \ + --siteId \ + --deploymentId diff --git a/docs/examples/1.7.x/console-cli/examples/sites/update-variable.md b/docs/examples/1.7.x/console-cli/examples/sites/update-variable.md new file mode 100644 index 0000000000..e968771056 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/update-variable.md @@ -0,0 +1,6 @@ +appwrite sites updateVariable \ + --siteId \ + --variableId \ + --key \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/sites/update.md b/docs/examples/1.7.x/console-cli/examples/sites/update.md new file mode 100644 index 0000000000..192ee26e3e --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/sites/update.md @@ -0,0 +1,19 @@ +appwrite sites update \ + --siteId \ + --name \ + --framework analog \ + + + + + + + + + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/storage/create-bucket.md b/docs/examples/1.7.x/console-cli/examples/storage/create-bucket.md new file mode 100644 index 0000000000..878c10d253 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/storage/create-bucket.md @@ -0,0 +1,11 @@ +appwrite storage createBucket \ + --bucketId \ + --name \ + + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/storage/create-file.md b/docs/examples/1.7.x/console-cli/examples/storage/create-file.md new file mode 100644 index 0000000000..67bd4da2c0 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/storage/create-file.md @@ -0,0 +1,5 @@ +appwrite storage createFile \ + --bucketId \ + --fileId \ + --file 'path/to/file.png' \ + diff --git a/docs/examples/1.7.x/console-cli/examples/storage/delete-bucket.md b/docs/examples/1.7.x/console-cli/examples/storage/delete-bucket.md new file mode 100644 index 0000000000..e51797e12c --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/storage/delete-bucket.md @@ -0,0 +1,2 @@ +appwrite storage deleteBucket \ + --bucketId diff --git a/docs/examples/1.7.x/console-cli/examples/storage/delete-file.md b/docs/examples/1.7.x/console-cli/examples/storage/delete-file.md new file mode 100644 index 0000000000..79c03e8288 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/storage/delete-file.md @@ -0,0 +1,3 @@ +appwrite storage deleteFile \ + --bucketId \ + --fileId diff --git a/docs/examples/1.7.x/console-cli/examples/storage/get-bucket-usage.md b/docs/examples/1.7.x/console-cli/examples/storage/get-bucket-usage.md new file mode 100644 index 0000000000..df3659c60a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/storage/get-bucket-usage.md @@ -0,0 +1,3 @@ +appwrite storage getBucketUsage \ + --bucketId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/storage/get-bucket.md b/docs/examples/1.7.x/console-cli/examples/storage/get-bucket.md new file mode 100644 index 0000000000..cf8725b35d --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/storage/get-bucket.md @@ -0,0 +1,2 @@ +appwrite storage getBucket \ + --bucketId diff --git a/docs/examples/1.7.x/console-cli/examples/storage/get-file-download.md b/docs/examples/1.7.x/console-cli/examples/storage/get-file-download.md new file mode 100644 index 0000000000..79f3368d87 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/storage/get-file-download.md @@ -0,0 +1,4 @@ +appwrite storage getFileDownload \ + --bucketId \ + --fileId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/storage/get-file-preview.md b/docs/examples/1.7.x/console-cli/examples/storage/get-file-preview.md new file mode 100644 index 0000000000..de437af65b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/storage/get-file-preview.md @@ -0,0 +1,15 @@ +appwrite storage getFilePreview \ + --bucketId \ + --fileId \ + + + + + + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/storage/get-file-view.md b/docs/examples/1.7.x/console-cli/examples/storage/get-file-view.md new file mode 100644 index 0000000000..689cf1233b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/storage/get-file-view.md @@ -0,0 +1,4 @@ +appwrite storage getFileView \ + --bucketId \ + --fileId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/storage/get-file.md b/docs/examples/1.7.x/console-cli/examples/storage/get-file.md new file mode 100644 index 0000000000..641c20d2b0 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/storage/get-file.md @@ -0,0 +1,3 @@ +appwrite storage getFile \ + --bucketId \ + --fileId diff --git a/docs/examples/1.7.x/console-cli/examples/storage/get-usage.md b/docs/examples/1.7.x/console-cli/examples/storage/get-usage.md new file mode 100644 index 0000000000..29466e02f0 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/storage/get-usage.md @@ -0,0 +1,2 @@ +appwrite storage getUsage \ + diff --git a/docs/examples/1.7.x/console-cli/examples/storage/list-buckets.md b/docs/examples/1.7.x/console-cli/examples/storage/list-buckets.md new file mode 100644 index 0000000000..a5cad1988f --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/storage/list-buckets.md @@ -0,0 +1,3 @@ +appwrite storage listBuckets \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/storage/list-files.md b/docs/examples/1.7.x/console-cli/examples/storage/list-files.md new file mode 100644 index 0000000000..0e1c2f09c0 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/storage/list-files.md @@ -0,0 +1,4 @@ +appwrite storage listFiles \ + --bucketId \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/storage/update-bucket.md b/docs/examples/1.7.x/console-cli/examples/storage/update-bucket.md new file mode 100644 index 0000000000..b006a7bf74 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/storage/update-bucket.md @@ -0,0 +1,11 @@ +appwrite storage updateBucket \ + --bucketId \ + --name \ + + + + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/storage/update-file.md b/docs/examples/1.7.x/console-cli/examples/storage/update-file.md new file mode 100644 index 0000000000..593ea658a0 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/storage/update-file.md @@ -0,0 +1,5 @@ +appwrite storage updateFile \ + --bucketId \ + --fileId \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/teams/create-membership.md b/docs/examples/1.7.x/console-cli/examples/teams/create-membership.md new file mode 100644 index 0000000000..0d0fc8df09 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/teams/create-membership.md @@ -0,0 +1,8 @@ +appwrite teams createMembership \ + --teamId \ + --roles one two three \ + + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/teams/create.md b/docs/examples/1.7.x/console-cli/examples/teams/create.md new file mode 100644 index 0000000000..e0f9a126f2 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/teams/create.md @@ -0,0 +1,4 @@ +appwrite teams create \ + --teamId \ + --name \ + diff --git a/docs/examples/1.7.x/console-cli/examples/teams/delete-membership.md b/docs/examples/1.7.x/console-cli/examples/teams/delete-membership.md new file mode 100644 index 0000000000..58d0adbac7 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/teams/delete-membership.md @@ -0,0 +1,3 @@ +appwrite teams deleteMembership \ + --teamId \ + --membershipId diff --git a/docs/examples/1.7.x/console-cli/examples/teams/delete.md b/docs/examples/1.7.x/console-cli/examples/teams/delete.md new file mode 100644 index 0000000000..5b018158cd --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/teams/delete.md @@ -0,0 +1,2 @@ +appwrite teams delete \ + --teamId diff --git a/docs/examples/1.7.x/console-cli/examples/teams/get-membership.md b/docs/examples/1.7.x/console-cli/examples/teams/get-membership.md new file mode 100644 index 0000000000..5e6af4c1a1 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/teams/get-membership.md @@ -0,0 +1,3 @@ +appwrite teams getMembership \ + --teamId \ + --membershipId diff --git a/docs/examples/1.7.x/console-cli/examples/teams/get-prefs.md b/docs/examples/1.7.x/console-cli/examples/teams/get-prefs.md new file mode 100644 index 0000000000..2ab1f1dc01 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/teams/get-prefs.md @@ -0,0 +1,2 @@ +appwrite teams getPrefs \ + --teamId diff --git a/docs/examples/1.7.x/console-cli/examples/teams/get.md b/docs/examples/1.7.x/console-cli/examples/teams/get.md new file mode 100644 index 0000000000..c8e75b7543 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/teams/get.md @@ -0,0 +1,2 @@ +appwrite teams get \ + --teamId diff --git a/docs/examples/1.7.x/console-cli/examples/teams/list-logs.md b/docs/examples/1.7.x/console-cli/examples/teams/list-logs.md new file mode 100644 index 0000000000..66149350d8 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/teams/list-logs.md @@ -0,0 +1,3 @@ +appwrite teams listLogs \ + --teamId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/teams/list-memberships.md b/docs/examples/1.7.x/console-cli/examples/teams/list-memberships.md new file mode 100644 index 0000000000..050ea961d2 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/teams/list-memberships.md @@ -0,0 +1,4 @@ +appwrite teams listMemberships \ + --teamId \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/teams/list.md b/docs/examples/1.7.x/console-cli/examples/teams/list.md new file mode 100644 index 0000000000..dfffc4d4dd --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/teams/list.md @@ -0,0 +1,3 @@ +appwrite teams list \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/teams/update-membership-status.md b/docs/examples/1.7.x/console-cli/examples/teams/update-membership-status.md new file mode 100644 index 0000000000..aa4acf9457 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/teams/update-membership-status.md @@ -0,0 +1,5 @@ +appwrite teams updateMembershipStatus \ + --teamId \ + --membershipId \ + --userId \ + --secret diff --git a/docs/examples/1.7.x/console-cli/examples/teams/update-membership.md b/docs/examples/1.7.x/console-cli/examples/teams/update-membership.md new file mode 100644 index 0000000000..6cfda92920 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/teams/update-membership.md @@ -0,0 +1,4 @@ +appwrite teams updateMembership \ + --teamId \ + --membershipId \ + --roles one two three diff --git a/docs/examples/1.7.x/console-cli/examples/teams/update-name.md b/docs/examples/1.7.x/console-cli/examples/teams/update-name.md new file mode 100644 index 0000000000..8c73e00d7b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/teams/update-name.md @@ -0,0 +1,3 @@ +appwrite teams updateName \ + --teamId \ + --name diff --git a/docs/examples/1.7.x/console-cli/examples/teams/update-prefs.md b/docs/examples/1.7.x/console-cli/examples/teams/update-prefs.md new file mode 100644 index 0000000000..b6fc5a8f6e --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/teams/update-prefs.md @@ -0,0 +1,3 @@ +appwrite teams updatePrefs \ + --teamId \ + --prefs '{ "key": "value" }' diff --git a/docs/examples/1.7.x/console-cli/examples/tokens/create-file-token.md b/docs/examples/1.7.x/console-cli/examples/tokens/create-file-token.md new file mode 100644 index 0000000000..8de8d7ac6c --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/tokens/create-file-token.md @@ -0,0 +1,4 @@ +appwrite tokens createFileToken \ + --bucketId \ + --fileId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/tokens/delete.md b/docs/examples/1.7.x/console-cli/examples/tokens/delete.md new file mode 100644 index 0000000000..c25ea4a4b4 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/tokens/delete.md @@ -0,0 +1,2 @@ +appwrite tokens delete \ + --tokenId diff --git a/docs/examples/1.7.x/console-cli/examples/tokens/get.md b/docs/examples/1.7.x/console-cli/examples/tokens/get.md new file mode 100644 index 0000000000..2c48280b0d --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/tokens/get.md @@ -0,0 +1,2 @@ +appwrite tokens get \ + --tokenId diff --git a/docs/examples/1.7.x/console-cli/examples/tokens/list.md b/docs/examples/1.7.x/console-cli/examples/tokens/list.md new file mode 100644 index 0000000000..a808e545ca --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/tokens/list.md @@ -0,0 +1,4 @@ +appwrite tokens list \ + --bucketId \ + --fileId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/tokens/update.md b/docs/examples/1.7.x/console-cli/examples/tokens/update.md new file mode 100644 index 0000000000..73f21609b6 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/tokens/update.md @@ -0,0 +1,3 @@ +appwrite tokens update \ + --tokenId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/users/create-argon2user.md b/docs/examples/1.7.x/console-cli/examples/users/create-argon2user.md new file mode 100644 index 0000000000..b0c7494e20 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/create-argon2user.md @@ -0,0 +1,5 @@ +appwrite users createArgon2User \ + --userId \ + --email email@example.com \ + --password password \ + diff --git a/docs/examples/1.7.x/console-cli/examples/users/create-bcrypt-user.md b/docs/examples/1.7.x/console-cli/examples/users/create-bcrypt-user.md new file mode 100644 index 0000000000..b5686721b5 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/create-bcrypt-user.md @@ -0,0 +1,5 @@ +appwrite users createBcryptUser \ + --userId \ + --email email@example.com \ + --password password \ + diff --git a/docs/examples/1.7.x/console-cli/examples/users/create-j-w-t.md b/docs/examples/1.7.x/console-cli/examples/users/create-j-w-t.md new file mode 100644 index 0000000000..220086bb1a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/create-j-w-t.md @@ -0,0 +1,4 @@ +appwrite users createJWT \ + --userId \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/users/create-m-d5user.md b/docs/examples/1.7.x/console-cli/examples/users/create-m-d5user.md new file mode 100644 index 0000000000..ba37a78be2 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/create-m-d5user.md @@ -0,0 +1,5 @@ +appwrite users createMD5User \ + --userId \ + --email email@example.com \ + --password password \ + diff --git a/docs/examples/1.7.x/console-cli/examples/users/create-mfa-recovery-codes.md b/docs/examples/1.7.x/console-cli/examples/users/create-mfa-recovery-codes.md new file mode 100644 index 0000000000..4dbd98ff8a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/create-mfa-recovery-codes.md @@ -0,0 +1,2 @@ +appwrite users createMfaRecoveryCodes \ + --userId diff --git a/docs/examples/1.7.x/console-cli/examples/users/create-p-h-pass-user.md b/docs/examples/1.7.x/console-cli/examples/users/create-p-h-pass-user.md new file mode 100644 index 0000000000..9dc378dc99 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/create-p-h-pass-user.md @@ -0,0 +1,5 @@ +appwrite users createPHPassUser \ + --userId \ + --email email@example.com \ + --password password \ + diff --git a/docs/examples/1.7.x/console-cli/examples/users/create-s-h-a-user.md b/docs/examples/1.7.x/console-cli/examples/users/create-s-h-a-user.md new file mode 100644 index 0000000000..57483625e9 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/create-s-h-a-user.md @@ -0,0 +1,6 @@ +appwrite users createSHAUser \ + --userId \ + --email email@example.com \ + --password password \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/users/create-scrypt-modified-user.md b/docs/examples/1.7.x/console-cli/examples/users/create-scrypt-modified-user.md new file mode 100644 index 0000000000..25fc60b6e1 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/create-scrypt-modified-user.md @@ -0,0 +1,8 @@ +appwrite users createScryptModifiedUser \ + --userId \ + --email email@example.com \ + --password password \ + --passwordSalt \ + --passwordSaltSeparator \ + --passwordSignerKey \ + diff --git a/docs/examples/1.7.x/console-cli/examples/users/create-scrypt-user.md b/docs/examples/1.7.x/console-cli/examples/users/create-scrypt-user.md new file mode 100644 index 0000000000..3fc56b1ee3 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/create-scrypt-user.md @@ -0,0 +1,10 @@ +appwrite users createScryptUser \ + --userId \ + --email email@example.com \ + --password password \ + --passwordSalt \ + --passwordCpu null \ + --passwordMemory null \ + --passwordParallel null \ + --passwordLength null \ + diff --git a/docs/examples/1.7.x/console-cli/examples/users/create-session.md b/docs/examples/1.7.x/console-cli/examples/users/create-session.md new file mode 100644 index 0000000000..c8938fa706 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/create-session.md @@ -0,0 +1,2 @@ +appwrite users createSession \ + --userId diff --git a/docs/examples/1.7.x/console-cli/examples/users/create-target.md b/docs/examples/1.7.x/console-cli/examples/users/create-target.md new file mode 100644 index 0000000000..8d9306b00e --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/create-target.md @@ -0,0 +1,7 @@ +appwrite users createTarget \ + --userId \ + --targetId \ + --providerType email \ + --identifier \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/users/create-token.md b/docs/examples/1.7.x/console-cli/examples/users/create-token.md new file mode 100644 index 0000000000..9962e72c73 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/create-token.md @@ -0,0 +1,4 @@ +appwrite users createToken \ + --userId \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/users/create.md b/docs/examples/1.7.x/console-cli/examples/users/create.md new file mode 100644 index 0000000000..e828f56ecb --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/create.md @@ -0,0 +1,6 @@ +appwrite users create \ + --userId \ + + + + diff --git a/docs/examples/1.7.x/console-cli/examples/users/delete-identity.md b/docs/examples/1.7.x/console-cli/examples/users/delete-identity.md new file mode 100644 index 0000000000..f3d2d6d980 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/delete-identity.md @@ -0,0 +1,2 @@ +appwrite users deleteIdentity \ + --identityId diff --git a/docs/examples/1.7.x/console-cli/examples/users/delete-mfa-authenticator.md b/docs/examples/1.7.x/console-cli/examples/users/delete-mfa-authenticator.md new file mode 100644 index 0000000000..edc67d0b9a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/delete-mfa-authenticator.md @@ -0,0 +1,3 @@ +appwrite users deleteMfaAuthenticator \ + --userId \ + --type totp diff --git a/docs/examples/1.7.x/console-cli/examples/users/delete-session.md b/docs/examples/1.7.x/console-cli/examples/users/delete-session.md new file mode 100644 index 0000000000..9f1fbdbfb3 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/delete-session.md @@ -0,0 +1,3 @@ +appwrite users deleteSession \ + --userId \ + --sessionId diff --git a/docs/examples/1.7.x/console-cli/examples/users/delete-sessions.md b/docs/examples/1.7.x/console-cli/examples/users/delete-sessions.md new file mode 100644 index 0000000000..4c683d270a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/delete-sessions.md @@ -0,0 +1,2 @@ +appwrite users deleteSessions \ + --userId diff --git a/docs/examples/1.7.x/console-cli/examples/users/delete-target.md b/docs/examples/1.7.x/console-cli/examples/users/delete-target.md new file mode 100644 index 0000000000..e9780911fd --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/delete-target.md @@ -0,0 +1,3 @@ +appwrite users deleteTarget \ + --userId \ + --targetId diff --git a/docs/examples/1.7.x/console-cli/examples/users/delete.md b/docs/examples/1.7.x/console-cli/examples/users/delete.md new file mode 100644 index 0000000000..293a5b040d --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/delete.md @@ -0,0 +1,2 @@ +appwrite users delete \ + --userId diff --git a/docs/examples/1.7.x/console-cli/examples/users/get-mfa-recovery-codes.md b/docs/examples/1.7.x/console-cli/examples/users/get-mfa-recovery-codes.md new file mode 100644 index 0000000000..cefcce607a --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/get-mfa-recovery-codes.md @@ -0,0 +1,2 @@ +appwrite users getMfaRecoveryCodes \ + --userId diff --git a/docs/examples/1.7.x/console-cli/examples/users/get-prefs.md b/docs/examples/1.7.x/console-cli/examples/users/get-prefs.md new file mode 100644 index 0000000000..324aa4f508 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/get-prefs.md @@ -0,0 +1,2 @@ +appwrite users getPrefs \ + --userId diff --git a/docs/examples/1.7.x/console-cli/examples/users/get-target.md b/docs/examples/1.7.x/console-cli/examples/users/get-target.md new file mode 100644 index 0000000000..b80dbd9728 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/get-target.md @@ -0,0 +1,3 @@ +appwrite users getTarget \ + --userId \ + --targetId diff --git a/docs/examples/1.7.x/console-cli/examples/users/get-usage.md b/docs/examples/1.7.x/console-cli/examples/users/get-usage.md new file mode 100644 index 0000000000..ad7895d3aa --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/get-usage.md @@ -0,0 +1,2 @@ +appwrite users getUsage \ + diff --git a/docs/examples/1.7.x/console-cli/examples/users/get.md b/docs/examples/1.7.x/console-cli/examples/users/get.md new file mode 100644 index 0000000000..47002c5063 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/get.md @@ -0,0 +1,2 @@ +appwrite users get \ + --userId diff --git a/docs/examples/1.7.x/console-cli/examples/users/list-identities.md b/docs/examples/1.7.x/console-cli/examples/users/list-identities.md new file mode 100644 index 0000000000..c6cd6d5e28 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/list-identities.md @@ -0,0 +1,3 @@ +appwrite users listIdentities \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/users/list-logs.md b/docs/examples/1.7.x/console-cli/examples/users/list-logs.md new file mode 100644 index 0000000000..0b0bc1f50f --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/list-logs.md @@ -0,0 +1,3 @@ +appwrite users listLogs \ + --userId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/users/list-memberships.md b/docs/examples/1.7.x/console-cli/examples/users/list-memberships.md new file mode 100644 index 0000000000..119f446ec9 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/list-memberships.md @@ -0,0 +1,4 @@ +appwrite users listMemberships \ + --userId \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/users/list-mfa-factors.md b/docs/examples/1.7.x/console-cli/examples/users/list-mfa-factors.md new file mode 100644 index 0000000000..e5d111b8ee --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/list-mfa-factors.md @@ -0,0 +1,2 @@ +appwrite users listMfaFactors \ + --userId diff --git a/docs/examples/1.7.x/console-cli/examples/users/list-sessions.md b/docs/examples/1.7.x/console-cli/examples/users/list-sessions.md new file mode 100644 index 0000000000..cb85d15ff6 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/list-sessions.md @@ -0,0 +1,2 @@ +appwrite users listSessions \ + --userId diff --git a/docs/examples/1.7.x/console-cli/examples/users/list-targets.md b/docs/examples/1.7.x/console-cli/examples/users/list-targets.md new file mode 100644 index 0000000000..9b5614bd32 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/list-targets.md @@ -0,0 +1,3 @@ +appwrite users listTargets \ + --userId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/users/list.md b/docs/examples/1.7.x/console-cli/examples/users/list.md new file mode 100644 index 0000000000..e5fdb9e5c5 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/list.md @@ -0,0 +1,3 @@ +appwrite users list \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/users/update-email-verification.md b/docs/examples/1.7.x/console-cli/examples/users/update-email-verification.md new file mode 100644 index 0000000000..990436f38b --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/update-email-verification.md @@ -0,0 +1,3 @@ +appwrite users updateEmailVerification \ + --userId \ + --emailVerification false diff --git a/docs/examples/1.7.x/console-cli/examples/users/update-email.md b/docs/examples/1.7.x/console-cli/examples/users/update-email.md new file mode 100644 index 0000000000..cce20e9ebf --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/update-email.md @@ -0,0 +1,3 @@ +appwrite users updateEmail \ + --userId \ + --email email@example.com diff --git a/docs/examples/1.7.x/console-cli/examples/users/update-labels.md b/docs/examples/1.7.x/console-cli/examples/users/update-labels.md new file mode 100644 index 0000000000..ca60c59683 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/update-labels.md @@ -0,0 +1,3 @@ +appwrite users updateLabels \ + --userId \ + --labels one two three diff --git a/docs/examples/1.7.x/console-cli/examples/users/update-mfa-recovery-codes.md b/docs/examples/1.7.x/console-cli/examples/users/update-mfa-recovery-codes.md new file mode 100644 index 0000000000..63fb7f25eb --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/update-mfa-recovery-codes.md @@ -0,0 +1,2 @@ +appwrite users updateMfaRecoveryCodes \ + --userId diff --git a/docs/examples/1.7.x/console-cli/examples/users/update-mfa.md b/docs/examples/1.7.x/console-cli/examples/users/update-mfa.md new file mode 100644 index 0000000000..3ccdbd8fdf --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/update-mfa.md @@ -0,0 +1,3 @@ +appwrite users updateMfa \ + --userId \ + --mfa false diff --git a/docs/examples/1.7.x/console-cli/examples/users/update-name.md b/docs/examples/1.7.x/console-cli/examples/users/update-name.md new file mode 100644 index 0000000000..9bf20eb117 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/update-name.md @@ -0,0 +1,3 @@ +appwrite users updateName \ + --userId \ + --name diff --git a/docs/examples/1.7.x/console-cli/examples/users/update-password.md b/docs/examples/1.7.x/console-cli/examples/users/update-password.md new file mode 100644 index 0000000000..c05197b3c2 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/update-password.md @@ -0,0 +1,3 @@ +appwrite users updatePassword \ + --userId \ + --password '' diff --git a/docs/examples/1.7.x/console-cli/examples/users/update-phone-verification.md b/docs/examples/1.7.x/console-cli/examples/users/update-phone-verification.md new file mode 100644 index 0000000000..b88a282d48 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/update-phone-verification.md @@ -0,0 +1,3 @@ +appwrite users updatePhoneVerification \ + --userId \ + --phoneVerification false diff --git a/docs/examples/1.7.x/console-cli/examples/users/update-phone.md b/docs/examples/1.7.x/console-cli/examples/users/update-phone.md new file mode 100644 index 0000000000..118c8e3557 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/update-phone.md @@ -0,0 +1,3 @@ +appwrite users updatePhone \ + --userId \ + --number +12065550100 diff --git a/docs/examples/1.7.x/console-cli/examples/users/update-prefs.md b/docs/examples/1.7.x/console-cli/examples/users/update-prefs.md new file mode 100644 index 0000000000..f3fa995e4d --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/update-prefs.md @@ -0,0 +1,3 @@ +appwrite users updatePrefs \ + --userId \ + --prefs '{ "key": "value" }' diff --git a/docs/examples/1.7.x/console-cli/examples/users/update-status.md b/docs/examples/1.7.x/console-cli/examples/users/update-status.md new file mode 100644 index 0000000000..b587b70e9e --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/update-status.md @@ -0,0 +1,3 @@ +appwrite users updateStatus \ + --userId \ + --status false diff --git a/docs/examples/1.7.x/console-cli/examples/users/update-target.md b/docs/examples/1.7.x/console-cli/examples/users/update-target.md new file mode 100644 index 0000000000..d6541a0600 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/users/update-target.md @@ -0,0 +1,6 @@ +appwrite users updateTarget \ + --userId \ + --targetId \ + + + diff --git a/docs/examples/1.7.x/console-cli/examples/vcs/create-repository-detection.md b/docs/examples/1.7.x/console-cli/examples/vcs/create-repository-detection.md new file mode 100644 index 0000000000..d12a093d2d --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/vcs/create-repository-detection.md @@ -0,0 +1,5 @@ +appwrite vcs createRepositoryDetection \ + --installationId \ + --providerRepositoryId \ + --type runtime \ + diff --git a/docs/examples/1.7.x/console-cli/examples/vcs/create-repository.md b/docs/examples/1.7.x/console-cli/examples/vcs/create-repository.md new file mode 100644 index 0000000000..a4934d5ef5 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/vcs/create-repository.md @@ -0,0 +1,4 @@ +appwrite vcs createRepository \ + --installationId \ + --name \ + --private false diff --git a/docs/examples/1.7.x/console-cli/examples/vcs/delete-installation.md b/docs/examples/1.7.x/console-cli/examples/vcs/delete-installation.md new file mode 100644 index 0000000000..f7d3a92001 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/vcs/delete-installation.md @@ -0,0 +1,2 @@ +appwrite vcs deleteInstallation \ + --installationId diff --git a/docs/examples/1.7.x/console-cli/examples/vcs/get-installation.md b/docs/examples/1.7.x/console-cli/examples/vcs/get-installation.md new file mode 100644 index 0000000000..df51853ea4 --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/vcs/get-installation.md @@ -0,0 +1,2 @@ +appwrite vcs getInstallation \ + --installationId diff --git a/docs/examples/1.7.x/console-cli/examples/vcs/get-repository-contents.md b/docs/examples/1.7.x/console-cli/examples/vcs/get-repository-contents.md new file mode 100644 index 0000000000..7d378d7efa --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/vcs/get-repository-contents.md @@ -0,0 +1,4 @@ +appwrite vcs getRepositoryContents \ + --installationId \ + --providerRepositoryId \ + diff --git a/docs/examples/1.7.x/console-cli/examples/vcs/get-repository.md b/docs/examples/1.7.x/console-cli/examples/vcs/get-repository.md new file mode 100644 index 0000000000..9f88e18eef --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/vcs/get-repository.md @@ -0,0 +1,3 @@ +appwrite vcs getRepository \ + --installationId \ + --providerRepositoryId diff --git a/docs/examples/1.7.x/console-cli/examples/vcs/list-installations.md b/docs/examples/1.7.x/console-cli/examples/vcs/list-installations.md new file mode 100644 index 0000000000..a0af28dfbb --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/vcs/list-installations.md @@ -0,0 +1,3 @@ +appwrite vcs listInstallations \ + + diff --git a/docs/examples/1.7.x/console-cli/examples/vcs/list-repositories.md b/docs/examples/1.7.x/console-cli/examples/vcs/list-repositories.md new file mode 100644 index 0000000000..15c3a643bb --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/vcs/list-repositories.md @@ -0,0 +1,4 @@ +appwrite vcs listRepositories \ + --installationId \ + --type runtime \ + diff --git a/docs/examples/1.7.x/console-cli/examples/vcs/list-repository-branches.md b/docs/examples/1.7.x/console-cli/examples/vcs/list-repository-branches.md new file mode 100644 index 0000000000..ea2fbd29fb --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/vcs/list-repository-branches.md @@ -0,0 +1,3 @@ +appwrite vcs listRepositoryBranches \ + --installationId \ + --providerRepositoryId diff --git a/docs/examples/1.7.x/console-cli/examples/vcs/update-external-deployments.md b/docs/examples/1.7.x/console-cli/examples/vcs/update-external-deployments.md new file mode 100644 index 0000000000..417b59431d --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/vcs/update-external-deployments.md @@ -0,0 +1,4 @@ +appwrite vcs updateExternalDeployments \ + --installationId \ + --repositoryId \ + --providerPullRequestId diff --git a/docs/examples/1.7.x/console-web/examples/account/create-anonymous-session.md b/docs/examples/1.7.x/console-web/examples/account/create-anonymous-session.md new file mode 100644 index 0000000000..113f882e80 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/create-anonymous-session.md @@ -0,0 +1,11 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.createAnonymousSession(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/create-email-password-session.md b/docs/examples/1.7.x/console-web/examples/account/create-email-password-session.md new file mode 100644 index 0000000000..36a503164b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/create-email-password-session.md @@ -0,0 +1,14 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.createEmailPasswordSession( + 'email@example.com', // email + 'password' // password +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/create-email-token.md b/docs/examples/1.7.x/console-web/examples/account/create-email-token.md new file mode 100644 index 0000000000..9517000af3 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/create-email-token.md @@ -0,0 +1,15 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.createEmailToken( + '', // userId + 'email@example.com', // email + false // phrase (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/create-j-w-t.md b/docs/examples/1.7.x/console-web/examples/account/create-j-w-t.md new file mode 100644 index 0000000000..9fc0e6da5e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/create-j-w-t.md @@ -0,0 +1,11 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.createJWT(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/create-magic-u-r-l-token.md b/docs/examples/1.7.x/console-web/examples/account/create-magic-u-r-l-token.md new file mode 100644 index 0000000000..6b1891855e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/create-magic-u-r-l-token.md @@ -0,0 +1,16 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.createMagicURLToken( + '', // userId + 'email@example.com', // email + 'https://example.com', // url (optional) + false // phrase (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/create-mfa-authenticator.md b/docs/examples/1.7.x/console-web/examples/account/create-mfa-authenticator.md new file mode 100644 index 0000000000..923eb1ee3c --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/create-mfa-authenticator.md @@ -0,0 +1,13 @@ +import { Client, Account, AuthenticatorType } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.createMfaAuthenticator( + AuthenticatorType.Totp // type +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/create-mfa-challenge.md b/docs/examples/1.7.x/console-web/examples/account/create-mfa-challenge.md new file mode 100644 index 0000000000..fd6af6ec19 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/create-mfa-challenge.md @@ -0,0 +1,13 @@ +import { Client, Account, AuthenticationFactor } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.createMfaChallenge( + AuthenticationFactor.Email // factor +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/create-mfa-recovery-codes.md b/docs/examples/1.7.x/console-web/examples/account/create-mfa-recovery-codes.md new file mode 100644 index 0000000000..d7c122b79c --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/create-mfa-recovery-codes.md @@ -0,0 +1,11 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.createMfaRecoveryCodes(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/create-o-auth2session.md b/docs/examples/1.7.x/console-web/examples/account/create-o-auth2session.md new file mode 100644 index 0000000000..a11bd9880b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/create-o-auth2session.md @@ -0,0 +1,15 @@ +import { Client, Account, OAuthProvider } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +account.createOAuth2Session( + OAuthProvider.Amazon, // provider + 'https://example.com', // success (optional) + 'https://example.com', // failure (optional) + [] // scopes (optional) +); + diff --git a/docs/examples/1.7.x/console-web/examples/account/create-o-auth2token.md b/docs/examples/1.7.x/console-web/examples/account/create-o-auth2token.md new file mode 100644 index 0000000000..9eb7cfab67 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/create-o-auth2token.md @@ -0,0 +1,15 @@ +import { Client, Account, OAuthProvider } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +account.createOAuth2Token( + OAuthProvider.Amazon, // provider + 'https://example.com', // success (optional) + 'https://example.com', // failure (optional) + [] // scopes (optional) +); + diff --git a/docs/examples/1.7.x/console-web/examples/account/create-phone-token.md b/docs/examples/1.7.x/console-web/examples/account/create-phone-token.md new file mode 100644 index 0000000000..25216ca73c --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/create-phone-token.md @@ -0,0 +1,14 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.createPhoneToken( + '', // userId + '+12065550100' // phone +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/create-phone-verification.md b/docs/examples/1.7.x/console-web/examples/account/create-phone-verification.md new file mode 100644 index 0000000000..03185e3e91 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/create-phone-verification.md @@ -0,0 +1,11 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.createPhoneVerification(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/create-push-target.md b/docs/examples/1.7.x/console-web/examples/account/create-push-target.md new file mode 100644 index 0000000000..ee35566f8a --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/create-push-target.md @@ -0,0 +1,15 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.createPushTarget( + '', // targetId + '', // identifier + '' // providerId (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/create-recovery.md b/docs/examples/1.7.x/console-web/examples/account/create-recovery.md new file mode 100644 index 0000000000..c2bb4422fa --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/create-recovery.md @@ -0,0 +1,14 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.createRecovery( + 'email@example.com', // email + 'https://example.com' // url +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/create-session.md b/docs/examples/1.7.x/console-web/examples/account/create-session.md new file mode 100644 index 0000000000..1c8d8a4480 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/create-session.md @@ -0,0 +1,14 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.createSession( + '', // userId + '' // secret +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/create-verification.md b/docs/examples/1.7.x/console-web/examples/account/create-verification.md new file mode 100644 index 0000000000..f6eacdce1f --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/create-verification.md @@ -0,0 +1,13 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.createVerification( + 'https://example.com' // url +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/create.md b/docs/examples/1.7.x/console-web/examples/account/create.md new file mode 100644 index 0000000000..d220aed8d0 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/create.md @@ -0,0 +1,16 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.create( + '', // userId + 'email@example.com', // email + '', // password + '' // name (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/delete-identity.md b/docs/examples/1.7.x/console-web/examples/account/delete-identity.md new file mode 100644 index 0000000000..6808b32a1d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/delete-identity.md @@ -0,0 +1,13 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.deleteIdentity( + '' // identityId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/delete-mfa-authenticator.md b/docs/examples/1.7.x/console-web/examples/account/delete-mfa-authenticator.md new file mode 100644 index 0000000000..54610a810c --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/delete-mfa-authenticator.md @@ -0,0 +1,13 @@ +import { Client, Account, AuthenticatorType } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.deleteMfaAuthenticator( + AuthenticatorType.Totp // type +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/delete-push-target.md b/docs/examples/1.7.x/console-web/examples/account/delete-push-target.md new file mode 100644 index 0000000000..f530b64dad --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/delete-push-target.md @@ -0,0 +1,13 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.deletePushTarget( + '' // targetId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/delete-session.md b/docs/examples/1.7.x/console-web/examples/account/delete-session.md new file mode 100644 index 0000000000..4eba0515e4 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/delete-session.md @@ -0,0 +1,13 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.deleteSession( + '' // sessionId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/delete-sessions.md b/docs/examples/1.7.x/console-web/examples/account/delete-sessions.md new file mode 100644 index 0000000000..b9904d612f --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/delete-sessions.md @@ -0,0 +1,11 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.deleteSessions(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/delete.md b/docs/examples/1.7.x/console-web/examples/account/delete.md new file mode 100644 index 0000000000..2fc730f9f0 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/delete.md @@ -0,0 +1,11 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.delete(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/get-mfa-recovery-codes.md b/docs/examples/1.7.x/console-web/examples/account/get-mfa-recovery-codes.md new file mode 100644 index 0000000000..bee039c48d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/get-mfa-recovery-codes.md @@ -0,0 +1,11 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.getMfaRecoveryCodes(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/get-prefs.md b/docs/examples/1.7.x/console-web/examples/account/get-prefs.md new file mode 100644 index 0000000000..3a013e6615 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/get-prefs.md @@ -0,0 +1,11 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.getPrefs(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/get-session.md b/docs/examples/1.7.x/console-web/examples/account/get-session.md new file mode 100644 index 0000000000..d5da237783 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/get-session.md @@ -0,0 +1,13 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.getSession( + '' // sessionId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/get.md b/docs/examples/1.7.x/console-web/examples/account/get.md new file mode 100644 index 0000000000..35661e483b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/get.md @@ -0,0 +1,11 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.get(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/list-identities.md b/docs/examples/1.7.x/console-web/examples/account/list-identities.md new file mode 100644 index 0000000000..675e902c9f --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/list-identities.md @@ -0,0 +1,13 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.listIdentities( + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/list-logs.md b/docs/examples/1.7.x/console-web/examples/account/list-logs.md new file mode 100644 index 0000000000..72a0ee12dd --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/list-logs.md @@ -0,0 +1,13 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.listLogs( + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/list-mfa-factors.md b/docs/examples/1.7.x/console-web/examples/account/list-mfa-factors.md new file mode 100644 index 0000000000..7cbc52ec71 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/list-mfa-factors.md @@ -0,0 +1,11 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.listMfaFactors(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/list-sessions.md b/docs/examples/1.7.x/console-web/examples/account/list-sessions.md new file mode 100644 index 0000000000..6a24e372c5 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/list-sessions.md @@ -0,0 +1,11 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.listSessions(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/update-email.md b/docs/examples/1.7.x/console-web/examples/account/update-email.md new file mode 100644 index 0000000000..df1c7f480a --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/update-email.md @@ -0,0 +1,14 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updateEmail( + 'email@example.com', // email + 'password' // password +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/update-m-f-a.md b/docs/examples/1.7.x/console-web/examples/account/update-m-f-a.md new file mode 100644 index 0000000000..b813b60bb4 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/update-m-f-a.md @@ -0,0 +1,13 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updateMFA( + false // mfa +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/update-magic-u-r-l-session.md b/docs/examples/1.7.x/console-web/examples/account/update-magic-u-r-l-session.md new file mode 100644 index 0000000000..e0ecd66740 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/update-magic-u-r-l-session.md @@ -0,0 +1,14 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updateMagicURLSession( + '', // userId + '' // secret +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/update-mfa-authenticator.md b/docs/examples/1.7.x/console-web/examples/account/update-mfa-authenticator.md new file mode 100644 index 0000000000..b960675914 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/update-mfa-authenticator.md @@ -0,0 +1,14 @@ +import { Client, Account, AuthenticatorType } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updateMfaAuthenticator( + AuthenticatorType.Totp, // type + '' // otp +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/update-mfa-challenge.md b/docs/examples/1.7.x/console-web/examples/account/update-mfa-challenge.md new file mode 100644 index 0000000000..5314959f25 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/update-mfa-challenge.md @@ -0,0 +1,14 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updateMfaChallenge( + '', // challengeId + '' // otp +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/update-mfa-recovery-codes.md b/docs/examples/1.7.x/console-web/examples/account/update-mfa-recovery-codes.md new file mode 100644 index 0000000000..654d9fb0fa --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/update-mfa-recovery-codes.md @@ -0,0 +1,11 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updateMfaRecoveryCodes(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/update-name.md b/docs/examples/1.7.x/console-web/examples/account/update-name.md new file mode 100644 index 0000000000..cd36ece113 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/update-name.md @@ -0,0 +1,13 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updateName( + '' // name +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/update-password.md b/docs/examples/1.7.x/console-web/examples/account/update-password.md new file mode 100644 index 0000000000..863c5f28b3 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/update-password.md @@ -0,0 +1,14 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updatePassword( + '', // password + 'password' // oldPassword (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/update-phone-session.md b/docs/examples/1.7.x/console-web/examples/account/update-phone-session.md new file mode 100644 index 0000000000..d23c10bbda --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/update-phone-session.md @@ -0,0 +1,14 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updatePhoneSession( + '', // userId + '' // secret +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/update-phone-verification.md b/docs/examples/1.7.x/console-web/examples/account/update-phone-verification.md new file mode 100644 index 0000000000..1a05386a9d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/update-phone-verification.md @@ -0,0 +1,14 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updatePhoneVerification( + '', // userId + '' // secret +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/update-phone.md b/docs/examples/1.7.x/console-web/examples/account/update-phone.md new file mode 100644 index 0000000000..380279d057 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/update-phone.md @@ -0,0 +1,14 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updatePhone( + '+12065550100', // phone + 'password' // password +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/update-prefs.md b/docs/examples/1.7.x/console-web/examples/account/update-prefs.md new file mode 100644 index 0000000000..13d857468d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/update-prefs.md @@ -0,0 +1,13 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updatePrefs( + {} // prefs +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/update-push-target.md b/docs/examples/1.7.x/console-web/examples/account/update-push-target.md new file mode 100644 index 0000000000..566d754db7 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/update-push-target.md @@ -0,0 +1,14 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updatePushTarget( + '', // targetId + '' // identifier +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/update-recovery.md b/docs/examples/1.7.x/console-web/examples/account/update-recovery.md new file mode 100644 index 0000000000..53d75f95d2 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/update-recovery.md @@ -0,0 +1,15 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updateRecovery( + '', // userId + '', // secret + '' // password +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/update-session.md b/docs/examples/1.7.x/console-web/examples/account/update-session.md new file mode 100644 index 0000000000..207fc026d8 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/update-session.md @@ -0,0 +1,13 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updateSession( + '' // sessionId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/update-status.md b/docs/examples/1.7.x/console-web/examples/account/update-status.md new file mode 100644 index 0000000000..c1377dc4a6 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/update-status.md @@ -0,0 +1,11 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updateStatus(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/account/update-verification.md b/docs/examples/1.7.x/console-web/examples/account/update-verification.md new file mode 100644 index 0000000000..4861ca2b81 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/account/update-verification.md @@ -0,0 +1,14 @@ +import { Client, Account } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const account = new Account(client); + +const result = await account.updateVerification( + '', // userId + '' // secret +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/assistant/chat.md b/docs/examples/1.7.x/console-web/examples/assistant/chat.md new file mode 100644 index 0000000000..98032043a5 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/assistant/chat.md @@ -0,0 +1,13 @@ +import { Client, Assistant } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const assistant = new Assistant(client); + +const result = await assistant.chat( + '' // prompt +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/avatars/get-browser.md b/docs/examples/1.7.x/console-web/examples/avatars/get-browser.md new file mode 100644 index 0000000000..65e7c826ff --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/avatars/get-browser.md @@ -0,0 +1,16 @@ +import { Client, Avatars, Browser } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const avatars = new Avatars(client); + +const result = avatars.getBrowser( + Browser.AvantBrowser, // code + 0, // width (optional) + 0, // height (optional) + -1 // quality (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/avatars/get-credit-card.md b/docs/examples/1.7.x/console-web/examples/avatars/get-credit-card.md new file mode 100644 index 0000000000..bda5407b27 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/avatars/get-credit-card.md @@ -0,0 +1,16 @@ +import { Client, Avatars, CreditCard } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const avatars = new Avatars(client); + +const result = avatars.getCreditCard( + CreditCard.AmericanExpress, // code + 0, // width (optional) + 0, // height (optional) + -1 // quality (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/avatars/get-favicon.md b/docs/examples/1.7.x/console-web/examples/avatars/get-favicon.md new file mode 100644 index 0000000000..b23e99a551 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/avatars/get-favicon.md @@ -0,0 +1,13 @@ +import { Client, Avatars } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const avatars = new Avatars(client); + +const result = avatars.getFavicon( + 'https://example.com' // url +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/avatars/get-flag.md b/docs/examples/1.7.x/console-web/examples/avatars/get-flag.md new file mode 100644 index 0000000000..f6c0814abd --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/avatars/get-flag.md @@ -0,0 +1,16 @@ +import { Client, Avatars, Flag } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const avatars = new Avatars(client); + +const result = avatars.getFlag( + Flag.Afghanistan, // code + 0, // width (optional) + 0, // height (optional) + -1 // quality (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/avatars/get-image.md b/docs/examples/1.7.x/console-web/examples/avatars/get-image.md new file mode 100644 index 0000000000..209e1ea836 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/avatars/get-image.md @@ -0,0 +1,15 @@ +import { Client, Avatars } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const avatars = new Avatars(client); + +const result = avatars.getImage( + 'https://example.com', // url + 0, // width (optional) + 0 // height (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/avatars/get-initials.md b/docs/examples/1.7.x/console-web/examples/avatars/get-initials.md new file mode 100644 index 0000000000..6ec70b2143 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/avatars/get-initials.md @@ -0,0 +1,16 @@ +import { Client, Avatars } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const avatars = new Avatars(client); + +const result = avatars.getInitials( + '', // name (optional) + 0, // width (optional) + 0, // height (optional) + '' // background (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/avatars/get-q-r.md b/docs/examples/1.7.x/console-web/examples/avatars/get-q-r.md new file mode 100644 index 0000000000..a255cdc531 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/avatars/get-q-r.md @@ -0,0 +1,16 @@ +import { Client, Avatars } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const avatars = new Avatars(client); + +const result = avatars.getQR( + '', // text + 1, // size (optional) + 0, // margin (optional) + false // download (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/console/get-resource.md b/docs/examples/1.7.x/console-web/examples/console/get-resource.md new file mode 100644 index 0000000000..94a4707081 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/console/get-resource.md @@ -0,0 +1,14 @@ +import { Client, Console, ConsoleResourceType } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const console = new Console(client); + +const result = await console.getResource( + '', // value + ConsoleResourceType.Rules // type +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/console/variables.md b/docs/examples/1.7.x/console-web/examples/console/variables.md new file mode 100644 index 0000000000..1dce6c0260 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/console/variables.md @@ -0,0 +1,11 @@ +import { Client, Console } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const console = new Console(client); + +const result = await console.variables(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/create-boolean-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/create-boolean-attribute.md new file mode 100644 index 0000000000..5b161c6f51 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/create-boolean-attribute.md @@ -0,0 +1,18 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.createBooleanAttribute( + '', // databaseId + '', // collectionId + '', // key + false, // required + false, // default (optional) + false // array (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/create-collection.md b/docs/examples/1.7.x/console-web/examples/databases/create-collection.md new file mode 100644 index 0000000000..cd28cf8616 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/create-collection.md @@ -0,0 +1,18 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.createCollection( + '', // databaseId + '', // collectionId + '', // name + ["read("any")"], // permissions (optional) + false, // documentSecurity (optional) + false // enabled (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/create-datetime-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/create-datetime-attribute.md new file mode 100644 index 0000000000..c431105bdf --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/create-datetime-attribute.md @@ -0,0 +1,18 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.createDatetimeAttribute( + '', // databaseId + '', // collectionId + '', // key + false, // required + '', // default (optional) + false // array (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/create-document.md b/docs/examples/1.7.x/console-web/examples/databases/create-document.md new file mode 100644 index 0000000000..4524017dd5 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/create-document.md @@ -0,0 +1,19 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setSession('') // + .setKey('') // Your secret API key + .setJWT(''); // Your secret JSON Web Token + +const databases = new Databases(client); + +const result = await databases.createDocument( + '', // databaseId + '', // collectionId + '', // documentId + {}, // data + ["read("any")"] // permissions (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/create-documents.md b/docs/examples/1.7.x/console-web/examples/databases/create-documents.md new file mode 100644 index 0000000000..9651a99775 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/create-documents.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setKey(''); // Your secret API key + +const databases = new Databases(client); + +const result = await databases.createDocuments( + '', // databaseId + '', // collectionId + [] // documents +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/create-email-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/create-email-attribute.md new file mode 100644 index 0000000000..f11c1a9649 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/create-email-attribute.md @@ -0,0 +1,18 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.createEmailAttribute( + '', // databaseId + '', // collectionId + '', // key + false, // required + 'email@example.com', // default (optional) + false // array (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/create-enum-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/create-enum-attribute.md new file mode 100644 index 0000000000..d180b1b9f2 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/create-enum-attribute.md @@ -0,0 +1,19 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.createEnumAttribute( + '', // databaseId + '', // collectionId + '', // key + [], // elements + false, // required + '', // default (optional) + false // array (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/create-float-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/create-float-attribute.md new file mode 100644 index 0000000000..036d3fc201 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/create-float-attribute.md @@ -0,0 +1,20 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.createFloatAttribute( + '', // databaseId + '', // collectionId + '', // key + false, // required + null, // min (optional) + null, // max (optional) + null, // default (optional) + false // array (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/create-index.md b/docs/examples/1.7.x/console-web/examples/databases/create-index.md new file mode 100644 index 0000000000..6a35f55349 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/create-index.md @@ -0,0 +1,19 @@ +import { Client, Databases, IndexType } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.createIndex( + '', // databaseId + '', // collectionId + '', // key + IndexType.Key, // type + [], // attributes + [], // orders (optional) + [] // lengths (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/create-integer-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/create-integer-attribute.md new file mode 100644 index 0000000000..25f474d0aa --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/create-integer-attribute.md @@ -0,0 +1,20 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.createIntegerAttribute( + '', // databaseId + '', // collectionId + '', // key + false, // required + null, // min (optional) + null, // max (optional) + null, // default (optional) + false // array (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/create-ip-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/create-ip-attribute.md new file mode 100644 index 0000000000..e8abc80f91 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/create-ip-attribute.md @@ -0,0 +1,18 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.createIpAttribute( + '', // databaseId + '', // collectionId + '', // key + false, // required + '', // default (optional) + false // array (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/create-relationship-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/create-relationship-attribute.md new file mode 100644 index 0000000000..358a2df5fc --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/create-relationship-attribute.md @@ -0,0 +1,20 @@ +import { Client, Databases, RelationshipType, RelationMutate } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.createRelationshipAttribute( + '', // databaseId + '', // collectionId + '', // relatedCollectionId + RelationshipType.OneToOne, // type + false, // twoWay (optional) + '', // key (optional) + '', // twoWayKey (optional) + RelationMutate.Cascade // onDelete (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/create-string-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/create-string-attribute.md new file mode 100644 index 0000000000..ba94b0348b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/create-string-attribute.md @@ -0,0 +1,20 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.createStringAttribute( + '', // databaseId + '', // collectionId + '', // key + 1, // size + false, // required + '', // default (optional) + false, // array (optional) + false // encrypt (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/create-url-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/create-url-attribute.md new file mode 100644 index 0000000000..da80e392d3 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/create-url-attribute.md @@ -0,0 +1,18 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.createUrlAttribute( + '', // databaseId + '', // collectionId + '', // key + false, // required + 'https://example.com', // default (optional) + false // array (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/create.md b/docs/examples/1.7.x/console-web/examples/databases/create.md new file mode 100644 index 0000000000..6d709ddd56 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/create.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.create( + '', // databaseId + '', // name + false // enabled (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/delete-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/delete-attribute.md new file mode 100644 index 0000000000..df12b0d2f0 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/delete-attribute.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.deleteAttribute( + '', // databaseId + '', // collectionId + '' // key +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/delete-collection.md b/docs/examples/1.7.x/console-web/examples/databases/delete-collection.md new file mode 100644 index 0000000000..f490ae1096 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/delete-collection.md @@ -0,0 +1,14 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.deleteCollection( + '', // databaseId + '' // collectionId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/delete-document.md b/docs/examples/1.7.x/console-web/examples/databases/delete-document.md new file mode 100644 index 0000000000..a56a4f23c5 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/delete-document.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.deleteDocument( + '', // databaseId + '', // collectionId + '' // documentId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/delete-documents.md b/docs/examples/1.7.x/console-web/examples/databases/delete-documents.md new file mode 100644 index 0000000000..ec520c6cf9 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/delete-documents.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.deleteDocuments( + '', // databaseId + '', // collectionId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/delete-index.md b/docs/examples/1.7.x/console-web/examples/databases/delete-index.md new file mode 100644 index 0000000000..cdd96a31f0 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/delete-index.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.deleteIndex( + '', // databaseId + '', // collectionId + '' // key +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/delete.md b/docs/examples/1.7.x/console-web/examples/databases/delete.md new file mode 100644 index 0000000000..3bd69657f9 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/delete.md @@ -0,0 +1,13 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.delete( + '' // databaseId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/get-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/get-attribute.md new file mode 100644 index 0000000000..9dac2ad133 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/get-attribute.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.getAttribute( + '', // databaseId + '', // collectionId + '' // key +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/get-collection-usage.md b/docs/examples/1.7.x/console-web/examples/databases/get-collection-usage.md new file mode 100644 index 0000000000..a2f736377a --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/get-collection-usage.md @@ -0,0 +1,15 @@ +import { Client, Databases, DatabaseUsageRange } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.getCollectionUsage( + '', // databaseId + '', // collectionId + DatabaseUsageRange.TwentyFourHours // range (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/get-collection.md b/docs/examples/1.7.x/console-web/examples/databases/get-collection.md new file mode 100644 index 0000000000..56d29f05cb --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/get-collection.md @@ -0,0 +1,14 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.getCollection( + '', // databaseId + '' // collectionId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/get-database-usage.md b/docs/examples/1.7.x/console-web/examples/databases/get-database-usage.md new file mode 100644 index 0000000000..13038ab755 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/get-database-usage.md @@ -0,0 +1,14 @@ +import { Client, Databases, DatabaseUsageRange } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.getDatabaseUsage( + '', // databaseId + DatabaseUsageRange.TwentyFourHours // range (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/get-document.md b/docs/examples/1.7.x/console-web/examples/databases/get-document.md new file mode 100644 index 0000000000..0e90cf785e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/get-document.md @@ -0,0 +1,16 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.getDocument( + '', // databaseId + '', // collectionId + '', // documentId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/get-index.md b/docs/examples/1.7.x/console-web/examples/databases/get-index.md new file mode 100644 index 0000000000..4c8c3794af --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/get-index.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.getIndex( + '', // databaseId + '', // collectionId + '' // key +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/get-usage.md b/docs/examples/1.7.x/console-web/examples/databases/get-usage.md new file mode 100644 index 0000000000..a0dd3ce983 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/get-usage.md @@ -0,0 +1,13 @@ +import { Client, Databases, DatabaseUsageRange } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.getUsage( + DatabaseUsageRange.TwentyFourHours // range (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/get.md b/docs/examples/1.7.x/console-web/examples/databases/get.md new file mode 100644 index 0000000000..5c72c5639c --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/get.md @@ -0,0 +1,13 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.get( + '' // databaseId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/list-attributes.md b/docs/examples/1.7.x/console-web/examples/databases/list-attributes.md new file mode 100644 index 0000000000..0c2cd4092c --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/list-attributes.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.listAttributes( + '', // databaseId + '', // collectionId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/list-collection-logs.md b/docs/examples/1.7.x/console-web/examples/databases/list-collection-logs.md new file mode 100644 index 0000000000..b2ef92d677 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/list-collection-logs.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.listCollectionLogs( + '', // databaseId + '', // collectionId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/list-collections.md b/docs/examples/1.7.x/console-web/examples/databases/list-collections.md new file mode 100644 index 0000000000..f9a0511e3e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/list-collections.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.listCollections( + '', // databaseId + [], // queries (optional) + '' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/list-document-logs.md b/docs/examples/1.7.x/console-web/examples/databases/list-document-logs.md new file mode 100644 index 0000000000..ddb789b3f0 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/list-document-logs.md @@ -0,0 +1,16 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.listDocumentLogs( + '', // databaseId + '', // collectionId + '', // documentId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/list-documents.md b/docs/examples/1.7.x/console-web/examples/databases/list-documents.md new file mode 100644 index 0000000000..3a77c05faa --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/list-documents.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.listDocuments( + '', // databaseId + '', // collectionId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/list-indexes.md b/docs/examples/1.7.x/console-web/examples/databases/list-indexes.md new file mode 100644 index 0000000000..fbbef1a9d8 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/list-indexes.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.listIndexes( + '', // databaseId + '', // collectionId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/list-logs.md b/docs/examples/1.7.x/console-web/examples/databases/list-logs.md new file mode 100644 index 0000000000..12ccccf87e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/list-logs.md @@ -0,0 +1,14 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.listLogs( + '', // databaseId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/list.md b/docs/examples/1.7.x/console-web/examples/databases/list.md new file mode 100644 index 0000000000..58ec7209a3 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/list.md @@ -0,0 +1,14 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.list( + [], // queries (optional) + '' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/update-boolean-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/update-boolean-attribute.md new file mode 100644 index 0000000000..95207fd2ab --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/update-boolean-attribute.md @@ -0,0 +1,18 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.updateBooleanAttribute( + '', // databaseId + '', // collectionId + '', // key + false, // required + false, // default + '' // newKey (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/update-collection.md b/docs/examples/1.7.x/console-web/examples/databases/update-collection.md new file mode 100644 index 0000000000..ced992baf4 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/update-collection.md @@ -0,0 +1,18 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.updateCollection( + '', // databaseId + '', // collectionId + '', // name + ["read("any")"], // permissions (optional) + false, // documentSecurity (optional) + false // enabled (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/update-datetime-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/update-datetime-attribute.md new file mode 100644 index 0000000000..7c413ee532 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/update-datetime-attribute.md @@ -0,0 +1,18 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.updateDatetimeAttribute( + '', // databaseId + '', // collectionId + '', // key + false, // required + '', // default + '' // newKey (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/update-document.md b/docs/examples/1.7.x/console-web/examples/databases/update-document.md new file mode 100644 index 0000000000..85898ea2a7 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/update-document.md @@ -0,0 +1,17 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.updateDocument( + '', // databaseId + '', // collectionId + '', // documentId + {}, // data (optional) + ["read("any")"] // permissions (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/update-documents.md b/docs/examples/1.7.x/console-web/examples/databases/update-documents.md new file mode 100644 index 0000000000..67be1e405c --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/update-documents.md @@ -0,0 +1,16 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.updateDocuments( + '', // databaseId + '', // collectionId + {}, // data (optional) + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/update-email-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/update-email-attribute.md new file mode 100644 index 0000000000..e54dba99bd --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/update-email-attribute.md @@ -0,0 +1,18 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.updateEmailAttribute( + '', // databaseId + '', // collectionId + '', // key + false, // required + 'email@example.com', // default + '' // newKey (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/update-enum-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/update-enum-attribute.md new file mode 100644 index 0000000000..aa5330af04 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/update-enum-attribute.md @@ -0,0 +1,19 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.updateEnumAttribute( + '', // databaseId + '', // collectionId + '', // key + [], // elements + false, // required + '', // default + '' // newKey (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/update-float-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/update-float-attribute.md new file mode 100644 index 0000000000..344ddb8815 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/update-float-attribute.md @@ -0,0 +1,20 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.updateFloatAttribute( + '', // databaseId + '', // collectionId + '', // key + false, // required + null, // default + null, // min (optional) + null, // max (optional) + '' // newKey (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/update-integer-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/update-integer-attribute.md new file mode 100644 index 0000000000..72565bd5f4 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/update-integer-attribute.md @@ -0,0 +1,20 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.updateIntegerAttribute( + '', // databaseId + '', // collectionId + '', // key + false, // required + null, // default + null, // min (optional) + null, // max (optional) + '' // newKey (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/update-ip-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/update-ip-attribute.md new file mode 100644 index 0000000000..ff6dded552 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/update-ip-attribute.md @@ -0,0 +1,18 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.updateIpAttribute( + '', // databaseId + '', // collectionId + '', // key + false, // required + '', // default + '' // newKey (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/update-relationship-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/update-relationship-attribute.md new file mode 100644 index 0000000000..acce3fd741 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/update-relationship-attribute.md @@ -0,0 +1,17 @@ +import { Client, Databases, RelationMutate } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.updateRelationshipAttribute( + '', // databaseId + '', // collectionId + '', // key + RelationMutate.Cascade, // onDelete (optional) + '' // newKey (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/update-string-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/update-string-attribute.md new file mode 100644 index 0000000000..05601bd4a2 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/update-string-attribute.md @@ -0,0 +1,19 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.updateStringAttribute( + '', // databaseId + '', // collectionId + '', // key + false, // required + '', // default + 1, // size (optional) + '' // newKey (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/update-url-attribute.md b/docs/examples/1.7.x/console-web/examples/databases/update-url-attribute.md new file mode 100644 index 0000000000..78b4d92a28 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/update-url-attribute.md @@ -0,0 +1,18 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.updateUrlAttribute( + '', // databaseId + '', // collectionId + '', // key + false, // required + 'https://example.com', // default + '' // newKey (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/update.md b/docs/examples/1.7.x/console-web/examples/databases/update.md new file mode 100644 index 0000000000..a29475b816 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/update.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.update( + '', // databaseId + '', // name + false // enabled (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/databases/upsert-documents.md b/docs/examples/1.7.x/console-web/examples/databases/upsert-documents.md new file mode 100644 index 0000000000..c58bd1e99c --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/databases/upsert-documents.md @@ -0,0 +1,15 @@ +import { Client, Databases } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const databases = new Databases(client); + +const result = await databases.upsertDocuments( + '', // databaseId + '', // collectionId + [] // documents (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/create-deployment.md b/docs/examples/1.7.x/console-web/examples/functions/create-deployment.md new file mode 100644 index 0000000000..62309d5e98 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/create-deployment.md @@ -0,0 +1,17 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.createDeployment( + '', // functionId + document.getElementById('uploader').files[0], // code + false, // activate + '', // entrypoint (optional) + '' // commands (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/create-duplicate-deployment.md b/docs/examples/1.7.x/console-web/examples/functions/create-duplicate-deployment.md new file mode 100644 index 0000000000..1b48c27a6f --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/create-duplicate-deployment.md @@ -0,0 +1,15 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.createDuplicateDeployment( + '', // functionId + '', // deploymentId + '' // buildId (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/create-execution.md b/docs/examples/1.7.x/console-web/examples/functions/create-execution.md new file mode 100644 index 0000000000..813e1fd0a7 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/create-execution.md @@ -0,0 +1,19 @@ +import { Client, Functions, ExecutionMethod } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.createExecution( + '', // functionId + '', // body (optional) + false, // async (optional) + '', // path (optional) + ExecutionMethod.GET, // method (optional) + {}, // headers (optional) + '' // scheduledAt (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/create-template-deployment.md b/docs/examples/1.7.x/console-web/examples/functions/create-template-deployment.md new file mode 100644 index 0000000000..98bf957eb1 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/create-template-deployment.md @@ -0,0 +1,18 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.createTemplateDeployment( + '', // functionId + '', // repository + '', // owner + '', // rootDirectory + '', // version + false // activate (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/create-variable.md b/docs/examples/1.7.x/console-web/examples/functions/create-variable.md new file mode 100644 index 0000000000..0b562cb93d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/create-variable.md @@ -0,0 +1,16 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.createVariable( + '', // functionId + '', // key + '', // value + false // secret (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/create-vcs-deployment.md b/docs/examples/1.7.x/console-web/examples/functions/create-vcs-deployment.md new file mode 100644 index 0000000000..6a12653de4 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/create-vcs-deployment.md @@ -0,0 +1,16 @@ +import { Client, Functions, VCSDeploymentType } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.createVcsDeployment( + '', // functionId + VCSDeploymentType.Branch, // type + '', // reference + false // activate (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/create.md b/docs/examples/1.7.x/console-web/examples/functions/create.md new file mode 100644 index 0000000000..1d9915f978 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/create.md @@ -0,0 +1,30 @@ +import { Client, Functions, } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.create( + '', // functionId + '', // name + .Node145, // runtime + ["any"], // execute (optional) + [], // events (optional) + '', // schedule (optional) + 1, // timeout (optional) + false, // enabled (optional) + false, // logging (optional) + '', // entrypoint (optional) + '', // commands (optional) + [], // scopes (optional) + '', // installationId (optional) + '', // providerRepositoryId (optional) + '', // providerBranch (optional) + false, // providerSilentMode (optional) + '', // providerRootDirectory (optional) + '' // specification (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/delete-deployment.md b/docs/examples/1.7.x/console-web/examples/functions/delete-deployment.md new file mode 100644 index 0000000000..1bc26feab0 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/delete-deployment.md @@ -0,0 +1,14 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.deleteDeployment( + '', // functionId + '' // deploymentId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/delete-execution.md b/docs/examples/1.7.x/console-web/examples/functions/delete-execution.md new file mode 100644 index 0000000000..0816434637 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/delete-execution.md @@ -0,0 +1,14 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.deleteExecution( + '', // functionId + '' // executionId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/delete-variable.md b/docs/examples/1.7.x/console-web/examples/functions/delete-variable.md new file mode 100644 index 0000000000..878d15d235 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/delete-variable.md @@ -0,0 +1,14 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.deleteVariable( + '', // functionId + '' // variableId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/delete.md b/docs/examples/1.7.x/console-web/examples/functions/delete.md new file mode 100644 index 0000000000..86d616d267 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/delete.md @@ -0,0 +1,13 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.delete( + '' // functionId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/get-deployment-download.md b/docs/examples/1.7.x/console-web/examples/functions/get-deployment-download.md new file mode 100644 index 0000000000..1ad8fd30cd --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/get-deployment-download.md @@ -0,0 +1,15 @@ +import { Client, Functions, DeploymentDownloadType } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = functions.getDeploymentDownload( + '', // functionId + '', // deploymentId + DeploymentDownloadType.Source // type (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/get-deployment.md b/docs/examples/1.7.x/console-web/examples/functions/get-deployment.md new file mode 100644 index 0000000000..75cb11f741 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/get-deployment.md @@ -0,0 +1,14 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.getDeployment( + '', // functionId + '' // deploymentId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/get-execution.md b/docs/examples/1.7.x/console-web/examples/functions/get-execution.md new file mode 100644 index 0000000000..58ab917bbd --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/get-execution.md @@ -0,0 +1,14 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.getExecution( + '', // functionId + '' // executionId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/get-template.md b/docs/examples/1.7.x/console-web/examples/functions/get-template.md new file mode 100644 index 0000000000..13c95210ab --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/get-template.md @@ -0,0 +1,13 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.getTemplate( + '' // templateId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/get-usage.md b/docs/examples/1.7.x/console-web/examples/functions/get-usage.md new file mode 100644 index 0000000000..bc010c3bd9 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/get-usage.md @@ -0,0 +1,14 @@ +import { Client, Functions, FunctionUsageRange } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.getUsage( + '', // functionId + FunctionUsageRange.TwentyFourHours // range (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/get-variable.md b/docs/examples/1.7.x/console-web/examples/functions/get-variable.md new file mode 100644 index 0000000000..d80b2bccbf --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/get-variable.md @@ -0,0 +1,14 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.getVariable( + '', // functionId + '' // variableId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/get.md b/docs/examples/1.7.x/console-web/examples/functions/get.md new file mode 100644 index 0000000000..9b852849eb --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/get.md @@ -0,0 +1,13 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.get( + '' // functionId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/list-deployments.md b/docs/examples/1.7.x/console-web/examples/functions/list-deployments.md new file mode 100644 index 0000000000..b9f2ec0eaf --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/list-deployments.md @@ -0,0 +1,15 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.listDeployments( + '', // functionId + [], // queries (optional) + '' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/list-executions.md b/docs/examples/1.7.x/console-web/examples/functions/list-executions.md new file mode 100644 index 0000000000..7d8a6c7a98 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/list-executions.md @@ -0,0 +1,14 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.listExecutions( + '', // functionId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/list-runtimes.md b/docs/examples/1.7.x/console-web/examples/functions/list-runtimes.md new file mode 100644 index 0000000000..cdd1e08cad --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/list-runtimes.md @@ -0,0 +1,11 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.listRuntimes(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/list-specifications.md b/docs/examples/1.7.x/console-web/examples/functions/list-specifications.md new file mode 100644 index 0000000000..fe671c54bb --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/list-specifications.md @@ -0,0 +1,11 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.listSpecifications(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/list-templates.md b/docs/examples/1.7.x/console-web/examples/functions/list-templates.md new file mode 100644 index 0000000000..ab7f84b34d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/list-templates.md @@ -0,0 +1,16 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.listTemplates( + [], // runtimes (optional) + [], // useCases (optional) + 1, // limit (optional) + 0 // offset (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/list-usage.md b/docs/examples/1.7.x/console-web/examples/functions/list-usage.md new file mode 100644 index 0000000000..14a880692b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/list-usage.md @@ -0,0 +1,13 @@ +import { Client, Functions, FunctionUsageRange } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.listUsage( + FunctionUsageRange.TwentyFourHours // range (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/list-variables.md b/docs/examples/1.7.x/console-web/examples/functions/list-variables.md new file mode 100644 index 0000000000..5651dbd1c5 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/list-variables.md @@ -0,0 +1,13 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.listVariables( + '' // functionId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/list.md b/docs/examples/1.7.x/console-web/examples/functions/list.md new file mode 100644 index 0000000000..462214449d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/list.md @@ -0,0 +1,14 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.list( + [], // queries (optional) + '' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/update-deployment-status.md b/docs/examples/1.7.x/console-web/examples/functions/update-deployment-status.md new file mode 100644 index 0000000000..ba4f37fabf --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/update-deployment-status.md @@ -0,0 +1,14 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.updateDeploymentStatus( + '', // functionId + '' // deploymentId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/update-function-deployment.md b/docs/examples/1.7.x/console-web/examples/functions/update-function-deployment.md new file mode 100644 index 0000000000..2d714fb43c --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/update-function-deployment.md @@ -0,0 +1,14 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.updateFunctionDeployment( + '', // functionId + '' // deploymentId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/update-variable.md b/docs/examples/1.7.x/console-web/examples/functions/update-variable.md new file mode 100644 index 0000000000..a6be7c0dd2 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/update-variable.md @@ -0,0 +1,17 @@ +import { Client, Functions } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.updateVariable( + '', // functionId + '', // variableId + '', // key + '', // value (optional) + false // secret (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/functions/update.md b/docs/examples/1.7.x/console-web/examples/functions/update.md new file mode 100644 index 0000000000..66d3cd8e8f --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/functions/update.md @@ -0,0 +1,30 @@ +import { Client, Functions, } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const functions = new Functions(client); + +const result = await functions.update( + '', // functionId + '', // name + .Node145, // runtime (optional) + ["any"], // execute (optional) + [], // events (optional) + '', // schedule (optional) + 1, // timeout (optional) + false, // enabled (optional) + false, // logging (optional) + '', // entrypoint (optional) + '', // commands (optional) + [], // scopes (optional) + '', // installationId (optional) + '', // providerRepositoryId (optional) + '', // providerBranch (optional) + false, // providerSilentMode (optional) + '', // providerRootDirectory (optional) + '' // specification (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/graphql/mutation.md b/docs/examples/1.7.x/console-web/examples/graphql/mutation.md new file mode 100644 index 0000000000..5360139b07 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/graphql/mutation.md @@ -0,0 +1,13 @@ +import { Client, Graphql } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const graphql = new Graphql(client); + +const result = await graphql.mutation( + {} // query +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/graphql/query.md b/docs/examples/1.7.x/console-web/examples/graphql/query.md new file mode 100644 index 0000000000..15434872ab --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/graphql/query.md @@ -0,0 +1,13 @@ +import { Client, Graphql } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const graphql = new Graphql(client); + +const result = await graphql.query( + {} // query +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-antivirus.md b/docs/examples/1.7.x/console-web/examples/health/get-antivirus.md new file mode 100644 index 0000000000..30e142a63d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-antivirus.md @@ -0,0 +1,11 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getAntivirus(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-cache.md b/docs/examples/1.7.x/console-web/examples/health/get-cache.md new file mode 100644 index 0000000000..1c0bb182e2 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-cache.md @@ -0,0 +1,11 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getCache(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-certificate.md b/docs/examples/1.7.x/console-web/examples/health/get-certificate.md new file mode 100644 index 0000000000..288c0f8732 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-certificate.md @@ -0,0 +1,13 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getCertificate( + '' // domain (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-d-b.md b/docs/examples/1.7.x/console-web/examples/health/get-d-b.md new file mode 100644 index 0000000000..855e73466c --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-d-b.md @@ -0,0 +1,11 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getDB(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-failed-jobs.md b/docs/examples/1.7.x/console-web/examples/health/get-failed-jobs.md new file mode 100644 index 0000000000..d96a5545aa --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-failed-jobs.md @@ -0,0 +1,14 @@ +import { Client, Health, } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getFailedJobs( + .V1Database, // name + null // threshold (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-pub-sub.md b/docs/examples/1.7.x/console-web/examples/health/get-pub-sub.md new file mode 100644 index 0000000000..0ccce8e4d8 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-pub-sub.md @@ -0,0 +1,11 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getPubSub(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-queue-builds.md b/docs/examples/1.7.x/console-web/examples/health/get-queue-builds.md new file mode 100644 index 0000000000..dfbbfd91a6 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-queue-builds.md @@ -0,0 +1,13 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getQueueBuilds( + null // threshold (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-queue-certificates.md b/docs/examples/1.7.x/console-web/examples/health/get-queue-certificates.md new file mode 100644 index 0000000000..b0397f4422 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-queue-certificates.md @@ -0,0 +1,13 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getQueueCertificates( + null // threshold (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-queue-databases.md b/docs/examples/1.7.x/console-web/examples/health/get-queue-databases.md new file mode 100644 index 0000000000..1b958a9c75 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-queue-databases.md @@ -0,0 +1,14 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getQueueDatabases( + '', // name (optional) + null // threshold (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-queue-deletes.md b/docs/examples/1.7.x/console-web/examples/health/get-queue-deletes.md new file mode 100644 index 0000000000..3f34bc2228 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-queue-deletes.md @@ -0,0 +1,13 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getQueueDeletes( + null // threshold (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-queue-functions.md b/docs/examples/1.7.x/console-web/examples/health/get-queue-functions.md new file mode 100644 index 0000000000..2ea3701462 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-queue-functions.md @@ -0,0 +1,13 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getQueueFunctions( + null // threshold (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-queue-logs.md b/docs/examples/1.7.x/console-web/examples/health/get-queue-logs.md new file mode 100644 index 0000000000..73bd18589a --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-queue-logs.md @@ -0,0 +1,13 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getQueueLogs( + null // threshold (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-queue-mails.md b/docs/examples/1.7.x/console-web/examples/health/get-queue-mails.md new file mode 100644 index 0000000000..a6d86c04c7 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-queue-mails.md @@ -0,0 +1,13 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getQueueMails( + null // threshold (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-queue-messaging.md b/docs/examples/1.7.x/console-web/examples/health/get-queue-messaging.md new file mode 100644 index 0000000000..d25979713d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-queue-messaging.md @@ -0,0 +1,13 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getQueueMessaging( + null // threshold (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-queue-migrations.md b/docs/examples/1.7.x/console-web/examples/health/get-queue-migrations.md new file mode 100644 index 0000000000..3619c56028 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-queue-migrations.md @@ -0,0 +1,13 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getQueueMigrations( + null // threshold (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-queue-stats-resources.md b/docs/examples/1.7.x/console-web/examples/health/get-queue-stats-resources.md new file mode 100644 index 0000000000..cf1c3ee5df --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-queue-stats-resources.md @@ -0,0 +1,13 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getQueueStatsResources( + null // threshold (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-queue-usage.md b/docs/examples/1.7.x/console-web/examples/health/get-queue-usage.md new file mode 100644 index 0000000000..f79fd3b5ad --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-queue-usage.md @@ -0,0 +1,13 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getQueueUsage( + null // threshold (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-queue-webhooks.md b/docs/examples/1.7.x/console-web/examples/health/get-queue-webhooks.md new file mode 100644 index 0000000000..72bcc44c9a --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-queue-webhooks.md @@ -0,0 +1,13 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getQueueWebhooks( + null // threshold (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-storage-local.md b/docs/examples/1.7.x/console-web/examples/health/get-storage-local.md new file mode 100644 index 0000000000..e6bdf62c50 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-storage-local.md @@ -0,0 +1,11 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getStorageLocal(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-storage.md b/docs/examples/1.7.x/console-web/examples/health/get-storage.md new file mode 100644 index 0000000000..1d8941490e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-storage.md @@ -0,0 +1,11 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getStorage(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get-time.md b/docs/examples/1.7.x/console-web/examples/health/get-time.md new file mode 100644 index 0000000000..826eaf5a8c --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get-time.md @@ -0,0 +1,11 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.getTime(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/health/get.md b/docs/examples/1.7.x/console-web/examples/health/get.md new file mode 100644 index 0000000000..b510d8a891 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/health/get.md @@ -0,0 +1,11 @@ +import { Client, Health } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const health = new Health(client); + +const result = await health.get(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/locale/get.md b/docs/examples/1.7.x/console-web/examples/locale/get.md new file mode 100644 index 0000000000..4b0331787e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/locale/get.md @@ -0,0 +1,11 @@ +import { Client, Locale } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const locale = new Locale(client); + +const result = await locale.get(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/locale/list-codes.md b/docs/examples/1.7.x/console-web/examples/locale/list-codes.md new file mode 100644 index 0000000000..d20399af4a --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/locale/list-codes.md @@ -0,0 +1,11 @@ +import { Client, Locale } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const locale = new Locale(client); + +const result = await locale.listCodes(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/locale/list-continents.md b/docs/examples/1.7.x/console-web/examples/locale/list-continents.md new file mode 100644 index 0000000000..d769e88f1c --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/locale/list-continents.md @@ -0,0 +1,11 @@ +import { Client, Locale } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const locale = new Locale(client); + +const result = await locale.listContinents(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/locale/list-countries-e-u.md b/docs/examples/1.7.x/console-web/examples/locale/list-countries-e-u.md new file mode 100644 index 0000000000..ce8746421b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/locale/list-countries-e-u.md @@ -0,0 +1,11 @@ +import { Client, Locale } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const locale = new Locale(client); + +const result = await locale.listCountriesEU(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/locale/list-countries-phones.md b/docs/examples/1.7.x/console-web/examples/locale/list-countries-phones.md new file mode 100644 index 0000000000..457867707c --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/locale/list-countries-phones.md @@ -0,0 +1,11 @@ +import { Client, Locale } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const locale = new Locale(client); + +const result = await locale.listCountriesPhones(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/locale/list-countries.md b/docs/examples/1.7.x/console-web/examples/locale/list-countries.md new file mode 100644 index 0000000000..298e25ee81 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/locale/list-countries.md @@ -0,0 +1,11 @@ +import { Client, Locale } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const locale = new Locale(client); + +const result = await locale.listCountries(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/locale/list-currencies.md b/docs/examples/1.7.x/console-web/examples/locale/list-currencies.md new file mode 100644 index 0000000000..05ff041cbb --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/locale/list-currencies.md @@ -0,0 +1,11 @@ +import { Client, Locale } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const locale = new Locale(client); + +const result = await locale.listCurrencies(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/locale/list-languages.md b/docs/examples/1.7.x/console-web/examples/locale/list-languages.md new file mode 100644 index 0000000000..1a2db31b55 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/locale/list-languages.md @@ -0,0 +1,11 @@ +import { Client, Locale } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const locale = new Locale(client); + +const result = await locale.listLanguages(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/create-apns-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/create-apns-provider.md new file mode 100644 index 0000000000..9b238afc9e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/create-apns-provider.md @@ -0,0 +1,20 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.createApnsProvider( + '', // providerId + '', // name + '', // authKey (optional) + '', // authKeyId (optional) + '', // teamId (optional) + '', // bundleId (optional) + false, // sandbox (optional) + false // enabled (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/create-email.md b/docs/examples/1.7.x/console-web/examples/messaging/create-email.md new file mode 100644 index 0000000000..108517c89d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/create-email.md @@ -0,0 +1,24 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.createEmail( + '', // messageId + '', // subject + '', // content + [], // topics (optional) + [], // users (optional) + [], // targets (optional) + [], // cc (optional) + [], // bcc (optional) + [], // attachments (optional) + false, // draft (optional) + false, // html (optional) + '' // scheduledAt (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/create-fcm-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/create-fcm-provider.md new file mode 100644 index 0000000000..9d67e89fd6 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/create-fcm-provider.md @@ -0,0 +1,16 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.createFcmProvider( + '', // providerId + '', // name + {}, // serviceAccountJSON (optional) + false // enabled (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/create-mailgun-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/create-mailgun-provider.md new file mode 100644 index 0000000000..dc165af859 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/create-mailgun-provider.md @@ -0,0 +1,22 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.createMailgunProvider( + '', // providerId + '', // name + '', // apiKey (optional) + '', // domain (optional) + false, // isEuRegion (optional) + '', // fromName (optional) + 'email@example.com', // fromEmail (optional) + '', // replyToName (optional) + 'email@example.com', // replyToEmail (optional) + false // enabled (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/create-msg91provider.md b/docs/examples/1.7.x/console-web/examples/messaging/create-msg91provider.md new file mode 100644 index 0000000000..cab468a089 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/create-msg91provider.md @@ -0,0 +1,18 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.createMsg91Provider( + '', // providerId + '', // name + '', // templateId (optional) + '', // senderId (optional) + '', // authKey (optional) + false // enabled (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/create-push.md b/docs/examples/1.7.x/console-web/examples/messaging/create-push.md new file mode 100644 index 0000000000..79c3a20e83 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/create-push.md @@ -0,0 +1,31 @@ +import { Client, Messaging, MessagePriority } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://.cloud.appwrite.io/v1') // Your API Endpoint + .setProject(''); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.createPush( + '', // messageId + '', // title (optional) + '<BODY>', // body (optional) + [], // topics (optional) + [], // users (optional) + [], // targets (optional) + {}, // data (optional) + '<ACTION>', // action (optional) + '[ID1:ID2]', // image (optional) + '<ICON>', // icon (optional) + '<SOUND>', // sound (optional) + '<COLOR>', // color (optional) + '<TAG>', // tag (optional) + null, // badge (optional) + false, // draft (optional) + '', // scheduledAt (optional) + false, // contentAvailable (optional) + false, // critical (optional) + MessagePriority.Normal // priority (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/create-sendgrid-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/create-sendgrid-provider.md new file mode 100644 index 0000000000..b93c84b258 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/create-sendgrid-provider.md @@ -0,0 +1,20 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.createSendgridProvider( + '<PROVIDER_ID>', // providerId + '<NAME>', // name + '<API_KEY>', // apiKey (optional) + '<FROM_NAME>', // fromName (optional) + 'email@example.com', // fromEmail (optional) + '<REPLY_TO_NAME>', // replyToName (optional) + 'email@example.com', // replyToEmail (optional) + false // enabled (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/create-sms.md b/docs/examples/1.7.x/console-web/examples/messaging/create-sms.md new file mode 100644 index 0000000000..7146ee4ac9 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/create-sms.md @@ -0,0 +1,19 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.createSms( + '<MESSAGE_ID>', // messageId + '<CONTENT>', // content + [], // topics (optional) + [], // users (optional) + [], // targets (optional) + false, // draft (optional) + '' // scheduledAt (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/create-smtp-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/create-smtp-provider.md new file mode 100644 index 0000000000..b4bcf14d0b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/create-smtp-provider.md @@ -0,0 +1,26 @@ +import { Client, Messaging, SmtpEncryption } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.createSmtpProvider( + '<PROVIDER_ID>', // providerId + '<NAME>', // name + '<HOST>', // host + 1, // port (optional) + '<USERNAME>', // username (optional) + '<PASSWORD>', // password (optional) + SmtpEncryption.None, // encryption (optional) + false, // autoTLS (optional) + '<MAILER>', // mailer (optional) + '<FROM_NAME>', // fromName (optional) + 'email@example.com', // fromEmail (optional) + '<REPLY_TO_NAME>', // replyToName (optional) + 'email@example.com', // replyToEmail (optional) + false // enabled (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/create-subscriber.md b/docs/examples/1.7.x/console-web/examples/messaging/create-subscriber.md new file mode 100644 index 0000000000..b1f7239413 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/create-subscriber.md @@ -0,0 +1,15 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.createSubscriber( + '<TOPIC_ID>', // topicId + '<SUBSCRIBER_ID>', // subscriberId + '<TARGET_ID>' // targetId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/create-telesign-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/create-telesign-provider.md new file mode 100644 index 0000000000..355bc22f85 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/create-telesign-provider.md @@ -0,0 +1,18 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.createTelesignProvider( + '<PROVIDER_ID>', // providerId + '<NAME>', // name + '+12065550100', // from (optional) + '<CUSTOMER_ID>', // customerId (optional) + '<API_KEY>', // apiKey (optional) + false // enabled (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/create-textmagic-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/create-textmagic-provider.md new file mode 100644 index 0000000000..d79cffc316 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/create-textmagic-provider.md @@ -0,0 +1,18 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.createTextmagicProvider( + '<PROVIDER_ID>', // providerId + '<NAME>', // name + '+12065550100', // from (optional) + '<USERNAME>', // username (optional) + '<API_KEY>', // apiKey (optional) + false // enabled (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/create-topic.md b/docs/examples/1.7.x/console-web/examples/messaging/create-topic.md new file mode 100644 index 0000000000..274714a63b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/create-topic.md @@ -0,0 +1,15 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.createTopic( + '<TOPIC_ID>', // topicId + '<NAME>', // name + ["any"] // subscribe (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/create-twilio-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/create-twilio-provider.md new file mode 100644 index 0000000000..9b8f440743 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/create-twilio-provider.md @@ -0,0 +1,18 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.createTwilioProvider( + '<PROVIDER_ID>', // providerId + '<NAME>', // name + '+12065550100', // from (optional) + '<ACCOUNT_SID>', // accountSid (optional) + '<AUTH_TOKEN>', // authToken (optional) + false // enabled (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/create-vonage-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/create-vonage-provider.md new file mode 100644 index 0000000000..6e115e8eb9 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/create-vonage-provider.md @@ -0,0 +1,18 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.createVonageProvider( + '<PROVIDER_ID>', // providerId + '<NAME>', // name + '+12065550100', // from (optional) + '<API_KEY>', // apiKey (optional) + '<API_SECRET>', // apiSecret (optional) + false // enabled (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/delete-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/delete-provider.md new file mode 100644 index 0000000000..f71eb65f29 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/delete-provider.md @@ -0,0 +1,13 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.deleteProvider( + '<PROVIDER_ID>' // providerId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/delete-subscriber.md b/docs/examples/1.7.x/console-web/examples/messaging/delete-subscriber.md new file mode 100644 index 0000000000..ace9670211 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/delete-subscriber.md @@ -0,0 +1,14 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.deleteSubscriber( + '<TOPIC_ID>', // topicId + '<SUBSCRIBER_ID>' // subscriberId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/delete-topic.md b/docs/examples/1.7.x/console-web/examples/messaging/delete-topic.md new file mode 100644 index 0000000000..8f8e5460d3 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/delete-topic.md @@ -0,0 +1,13 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.deleteTopic( + '<TOPIC_ID>' // topicId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/delete.md b/docs/examples/1.7.x/console-web/examples/messaging/delete.md new file mode 100644 index 0000000000..17324cca7e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/delete.md @@ -0,0 +1,13 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.delete( + '<MESSAGE_ID>' // messageId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/get-message.md b/docs/examples/1.7.x/console-web/examples/messaging/get-message.md new file mode 100644 index 0000000000..3282adbe57 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/get-message.md @@ -0,0 +1,13 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.getMessage( + '<MESSAGE_ID>' // messageId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/get-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/get-provider.md new file mode 100644 index 0000000000..97ac5fd127 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/get-provider.md @@ -0,0 +1,13 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.getProvider( + '<PROVIDER_ID>' // providerId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/get-subscriber.md b/docs/examples/1.7.x/console-web/examples/messaging/get-subscriber.md new file mode 100644 index 0000000000..b718558d71 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/get-subscriber.md @@ -0,0 +1,14 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.getSubscriber( + '<TOPIC_ID>', // topicId + '<SUBSCRIBER_ID>' // subscriberId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/get-topic.md b/docs/examples/1.7.x/console-web/examples/messaging/get-topic.md new file mode 100644 index 0000000000..802ec1fba4 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/get-topic.md @@ -0,0 +1,13 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.getTopic( + '<TOPIC_ID>' // topicId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/list-message-logs.md b/docs/examples/1.7.x/console-web/examples/messaging/list-message-logs.md new file mode 100644 index 0000000000..8679b267ce --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/list-message-logs.md @@ -0,0 +1,14 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.listMessageLogs( + '<MESSAGE_ID>', // messageId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/list-messages.md b/docs/examples/1.7.x/console-web/examples/messaging/list-messages.md new file mode 100644 index 0000000000..a537844f81 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/list-messages.md @@ -0,0 +1,14 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.listMessages( + [], // queries (optional) + '<SEARCH>' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/list-provider-logs.md b/docs/examples/1.7.x/console-web/examples/messaging/list-provider-logs.md new file mode 100644 index 0000000000..2e4acb38cf --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/list-provider-logs.md @@ -0,0 +1,14 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.listProviderLogs( + '<PROVIDER_ID>', // providerId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/list-providers.md b/docs/examples/1.7.x/console-web/examples/messaging/list-providers.md new file mode 100644 index 0000000000..5c91f01bbc --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/list-providers.md @@ -0,0 +1,14 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.listProviders( + [], // queries (optional) + '<SEARCH>' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/list-subscriber-logs.md b/docs/examples/1.7.x/console-web/examples/messaging/list-subscriber-logs.md new file mode 100644 index 0000000000..f722c9a9ed --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/list-subscriber-logs.md @@ -0,0 +1,14 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.listSubscriberLogs( + '<SUBSCRIBER_ID>', // subscriberId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/list-subscribers.md b/docs/examples/1.7.x/console-web/examples/messaging/list-subscribers.md new file mode 100644 index 0000000000..f120e9d96d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/list-subscribers.md @@ -0,0 +1,15 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.listSubscribers( + '<TOPIC_ID>', // topicId + [], // queries (optional) + '<SEARCH>' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/list-targets.md b/docs/examples/1.7.x/console-web/examples/messaging/list-targets.md new file mode 100644 index 0000000000..89baf87cb0 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/list-targets.md @@ -0,0 +1,14 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.listTargets( + '<MESSAGE_ID>', // messageId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/list-topic-logs.md b/docs/examples/1.7.x/console-web/examples/messaging/list-topic-logs.md new file mode 100644 index 0000000000..bc23a09a91 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/list-topic-logs.md @@ -0,0 +1,14 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.listTopicLogs( + '<TOPIC_ID>', // topicId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/list-topics.md b/docs/examples/1.7.x/console-web/examples/messaging/list-topics.md new file mode 100644 index 0000000000..d23cca3171 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/list-topics.md @@ -0,0 +1,14 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.listTopics( + [], // queries (optional) + '<SEARCH>' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/update-apns-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/update-apns-provider.md new file mode 100644 index 0000000000..bc69c3ad1e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/update-apns-provider.md @@ -0,0 +1,20 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.updateApnsProvider( + '<PROVIDER_ID>', // providerId + '<NAME>', // name (optional) + false, // enabled (optional) + '<AUTH_KEY>', // authKey (optional) + '<AUTH_KEY_ID>', // authKeyId (optional) + '<TEAM_ID>', // teamId (optional) + '<BUNDLE_ID>', // bundleId (optional) + false // sandbox (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/update-email.md b/docs/examples/1.7.x/console-web/examples/messaging/update-email.md new file mode 100644 index 0000000000..ba9bc7eb48 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/update-email.md @@ -0,0 +1,24 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.updateEmail( + '<MESSAGE_ID>', // messageId + [], // topics (optional) + [], // users (optional) + [], // targets (optional) + '<SUBJECT>', // subject (optional) + '<CONTENT>', // content (optional) + false, // draft (optional) + false, // html (optional) + [], // cc (optional) + [], // bcc (optional) + '', // scheduledAt (optional) + [] // attachments (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/update-fcm-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/update-fcm-provider.md new file mode 100644 index 0000000000..d2e7382561 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/update-fcm-provider.md @@ -0,0 +1,16 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.updateFcmProvider( + '<PROVIDER_ID>', // providerId + '<NAME>', // name (optional) + false, // enabled (optional) + {} // serviceAccountJSON (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/update-mailgun-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/update-mailgun-provider.md new file mode 100644 index 0000000000..cc48ac52f3 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/update-mailgun-provider.md @@ -0,0 +1,22 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.updateMailgunProvider( + '<PROVIDER_ID>', // providerId + '<NAME>', // name (optional) + '<API_KEY>', // apiKey (optional) + '<DOMAIN>', // domain (optional) + false, // isEuRegion (optional) + false, // enabled (optional) + '<FROM_NAME>', // fromName (optional) + 'email@example.com', // fromEmail (optional) + '<REPLY_TO_NAME>', // replyToName (optional) + '<REPLY_TO_EMAIL>' // replyToEmail (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/update-msg91provider.md b/docs/examples/1.7.x/console-web/examples/messaging/update-msg91provider.md new file mode 100644 index 0000000000..c2a6faec24 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/update-msg91provider.md @@ -0,0 +1,18 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.updateMsg91Provider( + '<PROVIDER_ID>', // providerId + '<NAME>', // name (optional) + false, // enabled (optional) + '<TEMPLATE_ID>', // templateId (optional) + '<SENDER_ID>', // senderId (optional) + '<AUTH_KEY>' // authKey (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/update-push.md b/docs/examples/1.7.x/console-web/examples/messaging/update-push.md new file mode 100644 index 0000000000..e479dcc425 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/update-push.md @@ -0,0 +1,31 @@ +import { Client, Messaging, MessagePriority } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.updatePush( + '<MESSAGE_ID>', // messageId + [], // topics (optional) + [], // users (optional) + [], // targets (optional) + '<TITLE>', // title (optional) + '<BODY>', // body (optional) + {}, // data (optional) + '<ACTION>', // action (optional) + '[ID1:ID2]', // image (optional) + '<ICON>', // icon (optional) + '<SOUND>', // sound (optional) + '<COLOR>', // color (optional) + '<TAG>', // tag (optional) + null, // badge (optional) + false, // draft (optional) + '', // scheduledAt (optional) + false, // contentAvailable (optional) + false, // critical (optional) + MessagePriority.Normal // priority (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/update-sendgrid-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/update-sendgrid-provider.md new file mode 100644 index 0000000000..efe8263718 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/update-sendgrid-provider.md @@ -0,0 +1,20 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.updateSendgridProvider( + '<PROVIDER_ID>', // providerId + '<NAME>', // name (optional) + false, // enabled (optional) + '<API_KEY>', // apiKey (optional) + '<FROM_NAME>', // fromName (optional) + 'email@example.com', // fromEmail (optional) + '<REPLY_TO_NAME>', // replyToName (optional) + '<REPLY_TO_EMAIL>' // replyToEmail (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/update-sms.md b/docs/examples/1.7.x/console-web/examples/messaging/update-sms.md new file mode 100644 index 0000000000..2c535a014e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/update-sms.md @@ -0,0 +1,19 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.updateSms( + '<MESSAGE_ID>', // messageId + [], // topics (optional) + [], // users (optional) + [], // targets (optional) + '<CONTENT>', // content (optional) + false, // draft (optional) + '' // scheduledAt (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/update-smtp-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/update-smtp-provider.md new file mode 100644 index 0000000000..0274337a7b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/update-smtp-provider.md @@ -0,0 +1,26 @@ +import { Client, Messaging, SmtpEncryption } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.updateSmtpProvider( + '<PROVIDER_ID>', // providerId + '<NAME>', // name (optional) + '<HOST>', // host (optional) + 1, // port (optional) + '<USERNAME>', // username (optional) + '<PASSWORD>', // password (optional) + SmtpEncryption.None, // encryption (optional) + false, // autoTLS (optional) + '<MAILER>', // mailer (optional) + '<FROM_NAME>', // fromName (optional) + 'email@example.com', // fromEmail (optional) + '<REPLY_TO_NAME>', // replyToName (optional) + '<REPLY_TO_EMAIL>', // replyToEmail (optional) + false // enabled (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/update-telesign-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/update-telesign-provider.md new file mode 100644 index 0000000000..5d8bc1602d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/update-telesign-provider.md @@ -0,0 +1,18 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.updateTelesignProvider( + '<PROVIDER_ID>', // providerId + '<NAME>', // name (optional) + false, // enabled (optional) + '<CUSTOMER_ID>', // customerId (optional) + '<API_KEY>', // apiKey (optional) + '<FROM>' // from (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/update-textmagic-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/update-textmagic-provider.md new file mode 100644 index 0000000000..564ad4fc69 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/update-textmagic-provider.md @@ -0,0 +1,18 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.updateTextmagicProvider( + '<PROVIDER_ID>', // providerId + '<NAME>', // name (optional) + false, // enabled (optional) + '<USERNAME>', // username (optional) + '<API_KEY>', // apiKey (optional) + '<FROM>' // from (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/update-topic.md b/docs/examples/1.7.x/console-web/examples/messaging/update-topic.md new file mode 100644 index 0000000000..e0edbae714 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/update-topic.md @@ -0,0 +1,15 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.updateTopic( + '<TOPIC_ID>', // topicId + '<NAME>', // name (optional) + ["any"] // subscribe (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/update-twilio-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/update-twilio-provider.md new file mode 100644 index 0000000000..544a52e4fd --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/update-twilio-provider.md @@ -0,0 +1,18 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.updateTwilioProvider( + '<PROVIDER_ID>', // providerId + '<NAME>', // name (optional) + false, // enabled (optional) + '<ACCOUNT_SID>', // accountSid (optional) + '<AUTH_TOKEN>', // authToken (optional) + '<FROM>' // from (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/messaging/update-vonage-provider.md b/docs/examples/1.7.x/console-web/examples/messaging/update-vonage-provider.md new file mode 100644 index 0000000000..e831c03184 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/messaging/update-vonage-provider.md @@ -0,0 +1,18 @@ +import { Client, Messaging } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const messaging = new Messaging(client); + +const result = await messaging.updateVonageProvider( + '<PROVIDER_ID>', // providerId + '<NAME>', // name (optional) + false, // enabled (optional) + '<API_KEY>', // apiKey (optional) + '<API_SECRET>', // apiSecret (optional) + '<FROM>' // from (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/migrations/create-appwrite-migration.md b/docs/examples/1.7.x/console-web/examples/migrations/create-appwrite-migration.md new file mode 100644 index 0000000000..db9a4cd0e0 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/migrations/create-appwrite-migration.md @@ -0,0 +1,16 @@ +import { Client, Migrations } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const migrations = new Migrations(client); + +const result = await migrations.createAppwriteMigration( + [], // resources + 'https://example.com', // endpoint + '<PROJECT_ID>', // projectId + '<API_KEY>' // apiKey +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/migrations/create-csv-migration.md b/docs/examples/1.7.x/console-web/examples/migrations/create-csv-migration.md new file mode 100644 index 0000000000..544f6c8ef6 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/migrations/create-csv-migration.md @@ -0,0 +1,15 @@ +import { Client, Migrations } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const migrations = new Migrations(client); + +const result = await migrations.createCsvMigration( + '<BUCKET_ID>', // bucketId + '<FILE_ID>', // fileId + '[ID1:ID2]' // resourceId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/migrations/create-firebase-migration.md b/docs/examples/1.7.x/console-web/examples/migrations/create-firebase-migration.md new file mode 100644 index 0000000000..20ce3a8b3c --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/migrations/create-firebase-migration.md @@ -0,0 +1,14 @@ +import { Client, Migrations } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const migrations = new Migrations(client); + +const result = await migrations.createFirebaseMigration( + [], // resources + '<SERVICE_ACCOUNT>' // serviceAccount +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/migrations/create-n-host-migration.md b/docs/examples/1.7.x/console-web/examples/migrations/create-n-host-migration.md new file mode 100644 index 0000000000..23b22ff371 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/migrations/create-n-host-migration.md @@ -0,0 +1,20 @@ +import { Client, Migrations } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const migrations = new Migrations(client); + +const result = await migrations.createNHostMigration( + [], // resources + '<SUBDOMAIN>', // subdomain + '<REGION>', // region + '<ADMIN_SECRET>', // adminSecret + '<DATABASE>', // database + '<USERNAME>', // username + '<PASSWORD>', // password + null // port (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/migrations/create-supabase-migration.md b/docs/examples/1.7.x/console-web/examples/migrations/create-supabase-migration.md new file mode 100644 index 0000000000..18c326ca7e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/migrations/create-supabase-migration.md @@ -0,0 +1,19 @@ +import { Client, Migrations } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const migrations = new Migrations(client); + +const result = await migrations.createSupabaseMigration( + [], // resources + 'https://example.com', // endpoint + '<API_KEY>', // apiKey + '<DATABASE_HOST>', // databaseHost + '<USERNAME>', // username + '<PASSWORD>', // password + null // port (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/migrations/delete.md b/docs/examples/1.7.x/console-web/examples/migrations/delete.md new file mode 100644 index 0000000000..bb013ddf27 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/migrations/delete.md @@ -0,0 +1,13 @@ +import { Client, Migrations } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const migrations = new Migrations(client); + +const result = await migrations.delete( + '<MIGRATION_ID>' // migrationId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/migrations/get-appwrite-report.md b/docs/examples/1.7.x/console-web/examples/migrations/get-appwrite-report.md new file mode 100644 index 0000000000..a70b6a45fb --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/migrations/get-appwrite-report.md @@ -0,0 +1,16 @@ +import { Client, Migrations } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const migrations = new Migrations(client); + +const result = await migrations.getAppwriteReport( + [], // resources + 'https://example.com', // endpoint + '<PROJECT_ID>', // projectID + '<KEY>' // key +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/migrations/get-firebase-report.md b/docs/examples/1.7.x/console-web/examples/migrations/get-firebase-report.md new file mode 100644 index 0000000000..bf1c85eeb6 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/migrations/get-firebase-report.md @@ -0,0 +1,14 @@ +import { Client, Migrations } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const migrations = new Migrations(client); + +const result = await migrations.getFirebaseReport( + [], // resources + '<SERVICE_ACCOUNT>' // serviceAccount +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/migrations/get-n-host-report.md b/docs/examples/1.7.x/console-web/examples/migrations/get-n-host-report.md new file mode 100644 index 0000000000..a983088f0d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/migrations/get-n-host-report.md @@ -0,0 +1,20 @@ +import { Client, Migrations } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const migrations = new Migrations(client); + +const result = await migrations.getNHostReport( + [], // resources + '<SUBDOMAIN>', // subdomain + '<REGION>', // region + '<ADMIN_SECRET>', // adminSecret + '<DATABASE>', // database + '<USERNAME>', // username + '<PASSWORD>', // password + null // port (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/migrations/get-supabase-report.md b/docs/examples/1.7.x/console-web/examples/migrations/get-supabase-report.md new file mode 100644 index 0000000000..d6ea7a9712 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/migrations/get-supabase-report.md @@ -0,0 +1,19 @@ +import { Client, Migrations } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const migrations = new Migrations(client); + +const result = await migrations.getSupabaseReport( + [], // resources + 'https://example.com', // endpoint + '<API_KEY>', // apiKey + '<DATABASE_HOST>', // databaseHost + '<USERNAME>', // username + '<PASSWORD>', // password + null // port (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/migrations/get.md b/docs/examples/1.7.x/console-web/examples/migrations/get.md new file mode 100644 index 0000000000..e2c67eb884 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/migrations/get.md @@ -0,0 +1,13 @@ +import { Client, Migrations } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const migrations = new Migrations(client); + +const result = await migrations.get( + '<MIGRATION_ID>' // migrationId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/migrations/list.md b/docs/examples/1.7.x/console-web/examples/migrations/list.md new file mode 100644 index 0000000000..a978e1843e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/migrations/list.md @@ -0,0 +1,14 @@ +import { Client, Migrations } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const migrations = new Migrations(client); + +const result = await migrations.list( + [], // queries (optional) + '<SEARCH>' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/migrations/retry.md b/docs/examples/1.7.x/console-web/examples/migrations/retry.md new file mode 100644 index 0000000000..f489168d7e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/migrations/retry.md @@ -0,0 +1,13 @@ +import { Client, Migrations } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const migrations = new Migrations(client); + +const result = await migrations.retry( + '<MIGRATION_ID>' // migrationId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/project/create-variable.md b/docs/examples/1.7.x/console-web/examples/project/create-variable.md new file mode 100644 index 0000000000..aa7361ffc2 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/project/create-variable.md @@ -0,0 +1,15 @@ +import { Client, Project } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const project = new Project(client); + +const result = await project.createVariable( + '<KEY>', // key + '<VALUE>', // value + false // secret (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/project/delete-variable.md b/docs/examples/1.7.x/console-web/examples/project/delete-variable.md new file mode 100644 index 0000000000..224691691d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/project/delete-variable.md @@ -0,0 +1,13 @@ +import { Client, Project } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const project = new Project(client); + +const result = await project.deleteVariable( + '<VARIABLE_ID>' // variableId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/project/get-usage.md b/docs/examples/1.7.x/console-web/examples/project/get-usage.md new file mode 100644 index 0000000000..300311dd8f --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/project/get-usage.md @@ -0,0 +1,15 @@ +import { Client, Project, ProjectUsageRange } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const project = new Project(client); + +const result = await project.getUsage( + '', // startDate + '', // endDate + ProjectUsageRange.OneHour // period (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/project/get-variable.md b/docs/examples/1.7.x/console-web/examples/project/get-variable.md new file mode 100644 index 0000000000..bc30baa325 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/project/get-variable.md @@ -0,0 +1,13 @@ +import { Client, Project } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const project = new Project(client); + +const result = await project.getVariable( + '<VARIABLE_ID>' // variableId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/project/list-variables.md b/docs/examples/1.7.x/console-web/examples/project/list-variables.md new file mode 100644 index 0000000000..9c17f8514e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/project/list-variables.md @@ -0,0 +1,11 @@ +import { Client, Project } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const project = new Project(client); + +const result = await project.listVariables(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/project/update-variable.md b/docs/examples/1.7.x/console-web/examples/project/update-variable.md new file mode 100644 index 0000000000..9dcd62a7c2 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/project/update-variable.md @@ -0,0 +1,16 @@ +import { Client, Project } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const project = new Project(client); + +const result = await project.updateVariable( + '<VARIABLE_ID>', // variableId + '<KEY>', // key + '<VALUE>', // value (optional) + false // secret (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/create-dev-key.md b/docs/examples/1.7.x/console-web/examples/projects/create-dev-key.md new file mode 100644 index 0000000000..28f89aea49 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/create-dev-key.md @@ -0,0 +1,15 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.createDevKey( + '<PROJECT_ID>', // projectId + '<NAME>', // name + '' // expire +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/create-j-w-t.md b/docs/examples/1.7.x/console-web/examples/projects/create-j-w-t.md new file mode 100644 index 0000000000..7175e266ae --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/create-j-w-t.md @@ -0,0 +1,15 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.createJWT( + '<PROJECT_ID>', // projectId + [], // scopes + 0 // duration (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/create-key.md b/docs/examples/1.7.x/console-web/examples/projects/create-key.md new file mode 100644 index 0000000000..25bcc125ed --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/create-key.md @@ -0,0 +1,16 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.createKey( + '<PROJECT_ID>', // projectId + '<NAME>', // name + [], // scopes + '' // expire (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/create-platform.md b/docs/examples/1.7.x/console-web/examples/projects/create-platform.md new file mode 100644 index 0000000000..7e23dd6f9e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/create-platform.md @@ -0,0 +1,18 @@ +import { Client, Projects, PlatformType } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.createPlatform( + '<PROJECT_ID>', // projectId + PlatformType.Web, // type + '<NAME>', // name + '<KEY>', // key (optional) + '<STORE>', // store (optional) + '' // hostname (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/create-smtp-test.md b/docs/examples/1.7.x/console-web/examples/projects/create-smtp-test.md new file mode 100644 index 0000000000..ab0e184432 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/create-smtp-test.md @@ -0,0 +1,22 @@ +import { Client, Projects, SMTPSecure } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.createSmtpTest( + '<PROJECT_ID>', // projectId + [], // emails + '<SENDER_NAME>', // senderName + 'email@example.com', // senderEmail + '', // host + 'email@example.com', // replyTo (optional) + null, // port (optional) + '<USERNAME>', // username (optional) + '<PASSWORD>', // password (optional) + SMTPSecure.Tls // secure (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/create-webhook.md b/docs/examples/1.7.x/console-web/examples/projects/create-webhook.md new file mode 100644 index 0000000000..62fdac56cd --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/create-webhook.md @@ -0,0 +1,20 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.createWebhook( + '<PROJECT_ID>', // projectId + '<NAME>', // name + [], // events + '', // url + false, // security + false, // enabled (optional) + '<HTTP_USER>', // httpUser (optional) + '<HTTP_PASS>' // httpPass (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/create.md b/docs/examples/1.7.x/console-web/examples/projects/create.md new file mode 100644 index 0000000000..58efd0b75f --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/create.md @@ -0,0 +1,25 @@ +import { Client, Projects, } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.create( + '', // projectId + '<NAME>', // name + '<TEAM_ID>', // teamId + .Default, // region (optional) + '<DESCRIPTION>', // description (optional) + '<LOGO>', // logo (optional) + 'https://example.com', // url (optional) + '<LEGAL_NAME>', // legalName (optional) + '<LEGAL_COUNTRY>', // legalCountry (optional) + '<LEGAL_STATE>', // legalState (optional) + '<LEGAL_CITY>', // legalCity (optional) + '<LEGAL_ADDRESS>', // legalAddress (optional) + '<LEGAL_TAX_ID>' // legalTaxId (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/delete-dev-key.md b/docs/examples/1.7.x/console-web/examples/projects/delete-dev-key.md new file mode 100644 index 0000000000..fc2ca4f1a7 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/delete-dev-key.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.deleteDevKey( + '<PROJECT_ID>', // projectId + '<KEY_ID>' // keyId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/delete-email-template.md b/docs/examples/1.7.x/console-web/examples/projects/delete-email-template.md new file mode 100644 index 0000000000..10e3d302ae --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/delete-email-template.md @@ -0,0 +1,15 @@ +import { Client, Projects, EmailTemplateType, EmailTemplateLocale } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.deleteEmailTemplate( + '<PROJECT_ID>', // projectId + EmailTemplateType.Verification, // type + EmailTemplateLocale.Af // locale +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/delete-key.md b/docs/examples/1.7.x/console-web/examples/projects/delete-key.md new file mode 100644 index 0000000000..7ea7dc6fdc --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/delete-key.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.deleteKey( + '<PROJECT_ID>', // projectId + '<KEY_ID>' // keyId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/delete-platform.md b/docs/examples/1.7.x/console-web/examples/projects/delete-platform.md new file mode 100644 index 0000000000..5c71747a64 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/delete-platform.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.deletePlatform( + '<PROJECT_ID>', // projectId + '<PLATFORM_ID>' // platformId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/delete-sms-template.md b/docs/examples/1.7.x/console-web/examples/projects/delete-sms-template.md new file mode 100644 index 0000000000..eef3cccae9 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/delete-sms-template.md @@ -0,0 +1,15 @@ +import { Client, Projects, SmsTemplateType, SmsTemplateLocale } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.deleteSmsTemplate( + '<PROJECT_ID>', // projectId + SmsTemplateType.Verification, // type + SmsTemplateLocale.Af // locale +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/delete-webhook.md b/docs/examples/1.7.x/console-web/examples/projects/delete-webhook.md new file mode 100644 index 0000000000..24abaafc66 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/delete-webhook.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.deleteWebhook( + '<PROJECT_ID>', // projectId + '<WEBHOOK_ID>' // webhookId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/delete.md b/docs/examples/1.7.x/console-web/examples/projects/delete.md new file mode 100644 index 0000000000..d868616db2 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/delete.md @@ -0,0 +1,13 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.delete( + '<PROJECT_ID>' // projectId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/get-dev-key.md b/docs/examples/1.7.x/console-web/examples/projects/get-dev-key.md new file mode 100644 index 0000000000..a9c38df45a --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/get-dev-key.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.getDevKey( + '<PROJECT_ID>', // projectId + '<KEY_ID>' // keyId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/get-email-template.md b/docs/examples/1.7.x/console-web/examples/projects/get-email-template.md new file mode 100644 index 0000000000..1d27c8c682 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/get-email-template.md @@ -0,0 +1,15 @@ +import { Client, Projects, EmailTemplateType, EmailTemplateLocale } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.getEmailTemplate( + '<PROJECT_ID>', // projectId + EmailTemplateType.Verification, // type + EmailTemplateLocale.Af // locale +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/get-key.md b/docs/examples/1.7.x/console-web/examples/projects/get-key.md new file mode 100644 index 0000000000..79359e298b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/get-key.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.getKey( + '<PROJECT_ID>', // projectId + '<KEY_ID>' // keyId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/get-platform.md b/docs/examples/1.7.x/console-web/examples/projects/get-platform.md new file mode 100644 index 0000000000..a17bcb122d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/get-platform.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.getPlatform( + '<PROJECT_ID>', // projectId + '<PLATFORM_ID>' // platformId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/get-sms-template.md b/docs/examples/1.7.x/console-web/examples/projects/get-sms-template.md new file mode 100644 index 0000000000..0badf1cca4 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/get-sms-template.md @@ -0,0 +1,15 @@ +import { Client, Projects, SmsTemplateType, SmsTemplateLocale } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.getSmsTemplate( + '<PROJECT_ID>', // projectId + SmsTemplateType.Verification, // type + SmsTemplateLocale.Af // locale +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/get-webhook.md b/docs/examples/1.7.x/console-web/examples/projects/get-webhook.md new file mode 100644 index 0000000000..6b6530a04e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/get-webhook.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.getWebhook( + '<PROJECT_ID>', // projectId + '<WEBHOOK_ID>' // webhookId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/get.md b/docs/examples/1.7.x/console-web/examples/projects/get.md new file mode 100644 index 0000000000..dbec5dd543 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/get.md @@ -0,0 +1,13 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.get( + '<PROJECT_ID>' // projectId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/list-dev-keys.md b/docs/examples/1.7.x/console-web/examples/projects/list-dev-keys.md new file mode 100644 index 0000000000..d3b17706cd --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/list-dev-keys.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.listDevKeys( + '<PROJECT_ID>', // projectId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/list-keys.md b/docs/examples/1.7.x/console-web/examples/projects/list-keys.md new file mode 100644 index 0000000000..5701133ba4 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/list-keys.md @@ -0,0 +1,13 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.listKeys( + '<PROJECT_ID>' // projectId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/list-platforms.md b/docs/examples/1.7.x/console-web/examples/projects/list-platforms.md new file mode 100644 index 0000000000..214092b6b3 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/list-platforms.md @@ -0,0 +1,13 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.listPlatforms( + '<PROJECT_ID>' // projectId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/list-webhooks.md b/docs/examples/1.7.x/console-web/examples/projects/list-webhooks.md new file mode 100644 index 0000000000..11639bfccf --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/list-webhooks.md @@ -0,0 +1,13 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.listWebhooks( + '<PROJECT_ID>' // projectId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/list.md b/docs/examples/1.7.x/console-web/examples/projects/list.md new file mode 100644 index 0000000000..0ade65189a --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/list.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.list( + [], // queries (optional) + '<SEARCH>' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-api-status-all.md b/docs/examples/1.7.x/console-web/examples/projects/update-api-status-all.md new file mode 100644 index 0000000000..a51ed2df2b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-api-status-all.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateApiStatusAll( + '<PROJECT_ID>', // projectId + false // status +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-api-status.md b/docs/examples/1.7.x/console-web/examples/projects/update-api-status.md new file mode 100644 index 0000000000..9cc7dfe8ab --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-api-status.md @@ -0,0 +1,15 @@ +import { Client, Projects, } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateApiStatus( + '<PROJECT_ID>', // projectId + .Rest, // api + false // status +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-auth-duration.md b/docs/examples/1.7.x/console-web/examples/projects/update-auth-duration.md new file mode 100644 index 0000000000..d0d8c67b28 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-auth-duration.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateAuthDuration( + '<PROJECT_ID>', // projectId + 0 // duration +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-auth-limit.md b/docs/examples/1.7.x/console-web/examples/projects/update-auth-limit.md new file mode 100644 index 0000000000..80f73f871f --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-auth-limit.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateAuthLimit( + '<PROJECT_ID>', // projectId + 0 // limit +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-auth-password-dictionary.md b/docs/examples/1.7.x/console-web/examples/projects/update-auth-password-dictionary.md new file mode 100644 index 0000000000..1e878c2246 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-auth-password-dictionary.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateAuthPasswordDictionary( + '<PROJECT_ID>', // projectId + false // enabled +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-auth-password-history.md b/docs/examples/1.7.x/console-web/examples/projects/update-auth-password-history.md new file mode 100644 index 0000000000..26a3adcfde --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-auth-password-history.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateAuthPasswordHistory( + '<PROJECT_ID>', // projectId + 0 // limit +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-auth-sessions-limit.md b/docs/examples/1.7.x/console-web/examples/projects/update-auth-sessions-limit.md new file mode 100644 index 0000000000..c1b0e14e91 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-auth-sessions-limit.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateAuthSessionsLimit( + '<PROJECT_ID>', // projectId + 1 // limit +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-auth-status.md b/docs/examples/1.7.x/console-web/examples/projects/update-auth-status.md new file mode 100644 index 0000000000..d4862282a6 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-auth-status.md @@ -0,0 +1,15 @@ +import { Client, Projects, AuthMethod } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateAuthStatus( + '<PROJECT_ID>', // projectId + AuthMethod.EmailPassword, // method + false // status +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-dev-key.md b/docs/examples/1.7.x/console-web/examples/projects/update-dev-key.md new file mode 100644 index 0000000000..9c00474262 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-dev-key.md @@ -0,0 +1,16 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateDevKey( + '<PROJECT_ID>', // projectId + '<KEY_ID>', // keyId + '<NAME>', // name + '' // expire +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-email-template.md b/docs/examples/1.7.x/console-web/examples/projects/update-email-template.md new file mode 100644 index 0000000000..44467c4f8a --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-email-template.md @@ -0,0 +1,20 @@ +import { Client, Projects, EmailTemplateType, EmailTemplateLocale } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateEmailTemplate( + '<PROJECT_ID>', // projectId + EmailTemplateType.Verification, // type + EmailTemplateLocale.Af, // locale + '<SUBJECT>', // subject + '<MESSAGE>', // message + '<SENDER_NAME>', // senderName (optional) + 'email@example.com', // senderEmail (optional) + 'email@example.com' // replyTo (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-key.md b/docs/examples/1.7.x/console-web/examples/projects/update-key.md new file mode 100644 index 0000000000..492a0ac23d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-key.md @@ -0,0 +1,17 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateKey( + '<PROJECT_ID>', // projectId + '<KEY_ID>', // keyId + '<NAME>', // name + [], // scopes + '' // expire (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-memberships-privacy.md b/docs/examples/1.7.x/console-web/examples/projects/update-memberships-privacy.md new file mode 100644 index 0000000000..31adcd3855 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-memberships-privacy.md @@ -0,0 +1,16 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateMembershipsPrivacy( + '<PROJECT_ID>', // projectId + false, // userName + false, // userEmail + false // mfa +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-mock-numbers.md b/docs/examples/1.7.x/console-web/examples/projects/update-mock-numbers.md new file mode 100644 index 0000000000..245a20c19b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-mock-numbers.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateMockNumbers( + '<PROJECT_ID>', // projectId + [] // numbers +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-o-auth2.md b/docs/examples/1.7.x/console-web/examples/projects/update-o-auth2.md new file mode 100644 index 0000000000..0671ee38bd --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-o-auth2.md @@ -0,0 +1,17 @@ +import { Client, Projects, OAuthProvider } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateOAuth2( + '<PROJECT_ID>', // projectId + OAuthProvider.Amazon, // provider + '<APP_ID>', // appId (optional) + '<SECRET>', // secret (optional) + false // enabled (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-personal-data-check.md b/docs/examples/1.7.x/console-web/examples/projects/update-personal-data-check.md new file mode 100644 index 0000000000..fb0fcffc16 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-personal-data-check.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updatePersonalDataCheck( + '<PROJECT_ID>', // projectId + false // enabled +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-platform.md b/docs/examples/1.7.x/console-web/examples/projects/update-platform.md new file mode 100644 index 0000000000..2f9cc0a4fd --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-platform.md @@ -0,0 +1,18 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updatePlatform( + '<PROJECT_ID>', // projectId + '<PLATFORM_ID>', // platformId + '<NAME>', // name + '<KEY>', // key (optional) + '<STORE>', // store (optional) + '' // hostname (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-service-status-all.md b/docs/examples/1.7.x/console-web/examples/projects/update-service-status-all.md new file mode 100644 index 0000000000..672a1491bc --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-service-status-all.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateServiceStatusAll( + '<PROJECT_ID>', // projectId + false // status +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-service-status.md b/docs/examples/1.7.x/console-web/examples/projects/update-service-status.md new file mode 100644 index 0000000000..5d2189e339 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-service-status.md @@ -0,0 +1,15 @@ +import { Client, Projects, ApiService } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateServiceStatus( + '<PROJECT_ID>', // projectId + ApiService.Account, // service + false // status +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-session-alerts.md b/docs/examples/1.7.x/console-web/examples/projects/update-session-alerts.md new file mode 100644 index 0000000000..65aa353b2b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-session-alerts.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateSessionAlerts( + '<PROJECT_ID>', // projectId + false // alerts +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-sms-template.md b/docs/examples/1.7.x/console-web/examples/projects/update-sms-template.md new file mode 100644 index 0000000000..cc801a67c5 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-sms-template.md @@ -0,0 +1,16 @@ +import { Client, Projects, SmsTemplateType, SmsTemplateLocale } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateSmsTemplate( + '<PROJECT_ID>', // projectId + SmsTemplateType.Verification, // type + SmsTemplateLocale.Af, // locale + '<MESSAGE>' // message +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-smtp.md b/docs/examples/1.7.x/console-web/examples/projects/update-smtp.md new file mode 100644 index 0000000000..605ba0f5e3 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-smtp.md @@ -0,0 +1,22 @@ +import { Client, Projects, SMTPSecure } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateSmtp( + '<PROJECT_ID>', // projectId + false, // enabled + '<SENDER_NAME>', // senderName (optional) + 'email@example.com', // senderEmail (optional) + 'email@example.com', // replyTo (optional) + '', // host (optional) + null, // port (optional) + '<USERNAME>', // username (optional) + '<PASSWORD>', // password (optional) + SMTPSecure.Tls // secure (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-team.md b/docs/examples/1.7.x/console-web/examples/projects/update-team.md new file mode 100644 index 0000000000..b7c5d934e2 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-team.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateTeam( + '<PROJECT_ID>', // projectId + '<TEAM_ID>' // teamId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-webhook-signature.md b/docs/examples/1.7.x/console-web/examples/projects/update-webhook-signature.md new file mode 100644 index 0000000000..593c6c0fce --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-webhook-signature.md @@ -0,0 +1,14 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateWebhookSignature( + '<PROJECT_ID>', // projectId + '<WEBHOOK_ID>' // webhookId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update-webhook.md b/docs/examples/1.7.x/console-web/examples/projects/update-webhook.md new file mode 100644 index 0000000000..18d10051e9 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update-webhook.md @@ -0,0 +1,21 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.updateWebhook( + '<PROJECT_ID>', // projectId + '<WEBHOOK_ID>', // webhookId + '<NAME>', // name + [], // events + '', // url + false, // security + false, // enabled (optional) + '<HTTP_USER>', // httpUser (optional) + '<HTTP_PASS>' // httpPass (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/projects/update.md b/docs/examples/1.7.x/console-web/examples/projects/update.md new file mode 100644 index 0000000000..8b2d2823ca --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/projects/update.md @@ -0,0 +1,23 @@ +import { Client, Projects } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const projects = new Projects(client); + +const result = await projects.update( + '<PROJECT_ID>', // projectId + '<NAME>', // name + '<DESCRIPTION>', // description (optional) + '<LOGO>', // logo (optional) + 'https://example.com', // url (optional) + '<LEGAL_NAME>', // legalName (optional) + '<LEGAL_COUNTRY>', // legalCountry (optional) + '<LEGAL_STATE>', // legalState (optional) + '<LEGAL_CITY>', // legalCity (optional) + '<LEGAL_ADDRESS>', // legalAddress (optional) + '<LEGAL_TAX_ID>' // legalTaxId (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/proxy/create-a-p-i-rule.md b/docs/examples/1.7.x/console-web/examples/proxy/create-a-p-i-rule.md new file mode 100644 index 0000000000..e248ebea3d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/proxy/create-a-p-i-rule.md @@ -0,0 +1,13 @@ +import { Client, Proxy } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const proxy = new Proxy(client); + +const result = await proxy.createAPIRule( + '' // domain +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/proxy/create-function-rule.md b/docs/examples/1.7.x/console-web/examples/proxy/create-function-rule.md new file mode 100644 index 0000000000..2bb0b83f08 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/proxy/create-function-rule.md @@ -0,0 +1,15 @@ +import { Client, Proxy } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const proxy = new Proxy(client); + +const result = await proxy.createFunctionRule( + '', // domain + '<FUNCTION_ID>', // functionId + '<BRANCH>' // branch (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/proxy/create-redirect-rule.md b/docs/examples/1.7.x/console-web/examples/proxy/create-redirect-rule.md new file mode 100644 index 0000000000..43b3f79d8a --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/proxy/create-redirect-rule.md @@ -0,0 +1,15 @@ +import { Client, Proxy, } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const proxy = new Proxy(client); + +const result = await proxy.createRedirectRule( + '', // domain + 'https://example.com', // url + .MovedPermanently301 // statusCode +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/proxy/create-site-rule.md b/docs/examples/1.7.x/console-web/examples/proxy/create-site-rule.md new file mode 100644 index 0000000000..4ea806eceb --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/proxy/create-site-rule.md @@ -0,0 +1,15 @@ +import { Client, Proxy } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const proxy = new Proxy(client); + +const result = await proxy.createSiteRule( + '', // domain + '<SITE_ID>', // siteId + '<BRANCH>' // branch (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/proxy/delete-rule.md b/docs/examples/1.7.x/console-web/examples/proxy/delete-rule.md new file mode 100644 index 0000000000..783f06d95c --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/proxy/delete-rule.md @@ -0,0 +1,13 @@ +import { Client, Proxy } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const proxy = new Proxy(client); + +const result = await proxy.deleteRule( + '<RULE_ID>' // ruleId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/proxy/get-rule.md b/docs/examples/1.7.x/console-web/examples/proxy/get-rule.md new file mode 100644 index 0000000000..e69c8210ce --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/proxy/get-rule.md @@ -0,0 +1,13 @@ +import { Client, Proxy } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const proxy = new Proxy(client); + +const result = await proxy.getRule( + '<RULE_ID>' // ruleId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/proxy/list-rules.md b/docs/examples/1.7.x/console-web/examples/proxy/list-rules.md new file mode 100644 index 0000000000..8c07168292 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/proxy/list-rules.md @@ -0,0 +1,14 @@ +import { Client, Proxy } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const proxy = new Proxy(client); + +const result = await proxy.listRules( + [], // queries (optional) + '<SEARCH>' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/proxy/update-rule-verification.md b/docs/examples/1.7.x/console-web/examples/proxy/update-rule-verification.md new file mode 100644 index 0000000000..349535cec8 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/proxy/update-rule-verification.md @@ -0,0 +1,13 @@ +import { Client, Proxy } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const proxy = new Proxy(client); + +const result = await proxy.updateRuleVerification( + '<RULE_ID>' // ruleId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/create-deployment.md b/docs/examples/1.7.x/console-web/examples/sites/create-deployment.md new file mode 100644 index 0000000000..5bc597c20e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/create-deployment.md @@ -0,0 +1,18 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.createDeployment( + '<SITE_ID>', // siteId + document.getElementById('uploader').files[0], // code + false, // activate + '<INSTALL_COMMAND>', // installCommand (optional) + '<BUILD_COMMAND>', // buildCommand (optional) + '<OUTPUT_DIRECTORY>' // outputDirectory (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/create-duplicate-deployment.md b/docs/examples/1.7.x/console-web/examples/sites/create-duplicate-deployment.md new file mode 100644 index 0000000000..3b8347fbf6 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/create-duplicate-deployment.md @@ -0,0 +1,14 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.createDuplicateDeployment( + '<SITE_ID>', // siteId + '<DEPLOYMENT_ID>' // deploymentId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/create-template-deployment.md b/docs/examples/1.7.x/console-web/examples/sites/create-template-deployment.md new file mode 100644 index 0000000000..990d7cf98b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/create-template-deployment.md @@ -0,0 +1,18 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.createTemplateDeployment( + '<SITE_ID>', // siteId + '<REPOSITORY>', // repository + '<OWNER>', // owner + '<ROOT_DIRECTORY>', // rootDirectory + '<VERSION>', // version + false // activate (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/create-variable.md b/docs/examples/1.7.x/console-web/examples/sites/create-variable.md new file mode 100644 index 0000000000..d605f2e4aa --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/create-variable.md @@ -0,0 +1,16 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.createVariable( + '<SITE_ID>', // siteId + '<KEY>', // key + '<VALUE>', // value + false // secret (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/create-vcs-deployment.md b/docs/examples/1.7.x/console-web/examples/sites/create-vcs-deployment.md new file mode 100644 index 0000000000..dd595db14d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/create-vcs-deployment.md @@ -0,0 +1,16 @@ +import { Client, Sites, VCSDeploymentType } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.createVcsDeployment( + '<SITE_ID>', // siteId + VCSDeploymentType.Branch, // type + '<REFERENCE>', // reference + false // activate (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/create.md b/docs/examples/1.7.x/console-web/examples/sites/create.md new file mode 100644 index 0000000000..7880ba361b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/create.md @@ -0,0 +1,30 @@ +import { Client, Sites, , , } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.create( + '<SITE_ID>', // siteId + '<NAME>', // name + .Analog, // framework + .Node145, // buildRuntime + false, // enabled (optional) + false, // logging (optional) + 1, // timeout (optional) + '<INSTALL_COMMAND>', // installCommand (optional) + '<BUILD_COMMAND>', // buildCommand (optional) + '<OUTPUT_DIRECTORY>', // outputDirectory (optional) + .Static, // adapter (optional) + '<INSTALLATION_ID>', // installationId (optional) + '<FALLBACK_FILE>', // fallbackFile (optional) + '<PROVIDER_REPOSITORY_ID>', // providerRepositoryId (optional) + '<PROVIDER_BRANCH>', // providerBranch (optional) + false, // providerSilentMode (optional) + '<PROVIDER_ROOT_DIRECTORY>', // providerRootDirectory (optional) + '' // specification (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/delete-deployment.md b/docs/examples/1.7.x/console-web/examples/sites/delete-deployment.md new file mode 100644 index 0000000000..357b69c04e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/delete-deployment.md @@ -0,0 +1,14 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.deleteDeployment( + '<SITE_ID>', // siteId + '<DEPLOYMENT_ID>' // deploymentId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/delete-log.md b/docs/examples/1.7.x/console-web/examples/sites/delete-log.md new file mode 100644 index 0000000000..25defd1546 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/delete-log.md @@ -0,0 +1,14 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.deleteLog( + '<SITE_ID>', // siteId + '<LOG_ID>' // logId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/delete-variable.md b/docs/examples/1.7.x/console-web/examples/sites/delete-variable.md new file mode 100644 index 0000000000..f6201738d8 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/delete-variable.md @@ -0,0 +1,14 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.deleteVariable( + '<SITE_ID>', // siteId + '<VARIABLE_ID>' // variableId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/delete.md b/docs/examples/1.7.x/console-web/examples/sites/delete.md new file mode 100644 index 0000000000..e3eff9cbb9 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/delete.md @@ -0,0 +1,13 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.delete( + '<SITE_ID>' // siteId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/get-deployment-download.md b/docs/examples/1.7.x/console-web/examples/sites/get-deployment-download.md new file mode 100644 index 0000000000..17707eded0 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/get-deployment-download.md @@ -0,0 +1,15 @@ +import { Client, Sites, DeploymentDownloadType } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = sites.getDeploymentDownload( + '<SITE_ID>', // siteId + '<DEPLOYMENT_ID>', // deploymentId + DeploymentDownloadType.Source // type (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/get-deployment.md b/docs/examples/1.7.x/console-web/examples/sites/get-deployment.md new file mode 100644 index 0000000000..c3453446e8 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/get-deployment.md @@ -0,0 +1,14 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.getDeployment( + '<SITE_ID>', // siteId + '<DEPLOYMENT_ID>' // deploymentId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/get-log.md b/docs/examples/1.7.x/console-web/examples/sites/get-log.md new file mode 100644 index 0000000000..eb1cd654c9 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/get-log.md @@ -0,0 +1,14 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.getLog( + '<SITE_ID>', // siteId + '<LOG_ID>' // logId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/get-template.md b/docs/examples/1.7.x/console-web/examples/sites/get-template.md new file mode 100644 index 0000000000..4220390d95 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/get-template.md @@ -0,0 +1,13 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.getTemplate( + '<TEMPLATE_ID>' // templateId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/get-usage.md b/docs/examples/1.7.x/console-web/examples/sites/get-usage.md new file mode 100644 index 0000000000..582a754e07 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/get-usage.md @@ -0,0 +1,14 @@ +import { Client, Sites, SiteUsageRange } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.getUsage( + '<SITE_ID>', // siteId + SiteUsageRange.TwentyFourHours // range (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/get-variable.md b/docs/examples/1.7.x/console-web/examples/sites/get-variable.md new file mode 100644 index 0000000000..c0d95326cc --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/get-variable.md @@ -0,0 +1,14 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.getVariable( + '<SITE_ID>', // siteId + '<VARIABLE_ID>' // variableId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/get.md b/docs/examples/1.7.x/console-web/examples/sites/get.md new file mode 100644 index 0000000000..102cade4c6 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/get.md @@ -0,0 +1,13 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.get( + '<SITE_ID>' // siteId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/list-deployments.md b/docs/examples/1.7.x/console-web/examples/sites/list-deployments.md new file mode 100644 index 0000000000..8c0bd8ea2d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/list-deployments.md @@ -0,0 +1,15 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.listDeployments( + '<SITE_ID>', // siteId + [], // queries (optional) + '<SEARCH>' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/list-frameworks.md b/docs/examples/1.7.x/console-web/examples/sites/list-frameworks.md new file mode 100644 index 0000000000..aceadcc8c9 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/list-frameworks.md @@ -0,0 +1,11 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.listFrameworks(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/list-logs.md b/docs/examples/1.7.x/console-web/examples/sites/list-logs.md new file mode 100644 index 0000000000..458cc69b2b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/list-logs.md @@ -0,0 +1,14 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.listLogs( + '<SITE_ID>', // siteId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/list-specifications.md b/docs/examples/1.7.x/console-web/examples/sites/list-specifications.md new file mode 100644 index 0000000000..9bbb35d76d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/list-specifications.md @@ -0,0 +1,11 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.listSpecifications(); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/list-templates.md b/docs/examples/1.7.x/console-web/examples/sites/list-templates.md new file mode 100644 index 0000000000..58f46bbb4a --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/list-templates.md @@ -0,0 +1,16 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.listTemplates( + [], // frameworks (optional) + [], // useCases (optional) + 1, // limit (optional) + 0 // offset (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/list-usage.md b/docs/examples/1.7.x/console-web/examples/sites/list-usage.md new file mode 100644 index 0000000000..7182d78880 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/list-usage.md @@ -0,0 +1,13 @@ +import { Client, Sites, SiteUsageRange } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.listUsage( + SiteUsageRange.TwentyFourHours // range (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/list-variables.md b/docs/examples/1.7.x/console-web/examples/sites/list-variables.md new file mode 100644 index 0000000000..de62195aea --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/list-variables.md @@ -0,0 +1,13 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.listVariables( + '<SITE_ID>' // siteId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/list.md b/docs/examples/1.7.x/console-web/examples/sites/list.md new file mode 100644 index 0000000000..fafe3cb229 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/list.md @@ -0,0 +1,14 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.list( + [], // queries (optional) + '<SEARCH>' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/update-deployment-status.md b/docs/examples/1.7.x/console-web/examples/sites/update-deployment-status.md new file mode 100644 index 0000000000..8205c863b0 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/update-deployment-status.md @@ -0,0 +1,14 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.updateDeploymentStatus( + '<SITE_ID>', // siteId + '<DEPLOYMENT_ID>' // deploymentId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/update-site-deployment.md b/docs/examples/1.7.x/console-web/examples/sites/update-site-deployment.md new file mode 100644 index 0000000000..d63541702e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/update-site-deployment.md @@ -0,0 +1,14 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.updateSiteDeployment( + '<SITE_ID>', // siteId + '<DEPLOYMENT_ID>' // deploymentId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/update-variable.md b/docs/examples/1.7.x/console-web/examples/sites/update-variable.md new file mode 100644 index 0000000000..1ea9481737 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/update-variable.md @@ -0,0 +1,17 @@ +import { Client, Sites } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.updateVariable( + '<SITE_ID>', // siteId + '<VARIABLE_ID>', // variableId + '<KEY>', // key + '<VALUE>', // value (optional) + false // secret (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/sites/update.md b/docs/examples/1.7.x/console-web/examples/sites/update.md new file mode 100644 index 0000000000..b20a19526d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/sites/update.md @@ -0,0 +1,30 @@ +import { Client, Sites, , , } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const sites = new Sites(client); + +const result = await sites.update( + '<SITE_ID>', // siteId + '<NAME>', // name + .Analog, // framework + false, // enabled (optional) + false, // logging (optional) + 1, // timeout (optional) + '<INSTALL_COMMAND>', // installCommand (optional) + '<BUILD_COMMAND>', // buildCommand (optional) + '<OUTPUT_DIRECTORY>', // outputDirectory (optional) + .Node145, // buildRuntime (optional) + .Static, // adapter (optional) + '<FALLBACK_FILE>', // fallbackFile (optional) + '<INSTALLATION_ID>', // installationId (optional) + '<PROVIDER_REPOSITORY_ID>', // providerRepositoryId (optional) + '<PROVIDER_BRANCH>', // providerBranch (optional) + false, // providerSilentMode (optional) + '<PROVIDER_ROOT_DIRECTORY>', // providerRootDirectory (optional) + '' // specification (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/storage/create-bucket.md b/docs/examples/1.7.x/console-web/examples/storage/create-bucket.md new file mode 100644 index 0000000000..a01bb0945f --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/storage/create-bucket.md @@ -0,0 +1,22 @@ +import { Client, Storage, } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const storage = new Storage(client); + +const result = await storage.createBucket( + '<BUCKET_ID>', // bucketId + '<NAME>', // name + ["read("any")"], // permissions (optional) + false, // fileSecurity (optional) + false, // enabled (optional) + 1, // maximumFileSize (optional) + [], // allowedFileExtensions (optional) + .None, // compression (optional) + false, // encryption (optional) + false // antivirus (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/storage/create-file.md b/docs/examples/1.7.x/console-web/examples/storage/create-file.md new file mode 100644 index 0000000000..8048772389 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/storage/create-file.md @@ -0,0 +1,16 @@ +import { Client, Storage } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const storage = new Storage(client); + +const result = await storage.createFile( + '<BUCKET_ID>', // bucketId + '<FILE_ID>', // fileId + document.getElementById('uploader').files[0], // file + ["read("any")"] // permissions (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/storage/delete-bucket.md b/docs/examples/1.7.x/console-web/examples/storage/delete-bucket.md new file mode 100644 index 0000000000..20084fd7e3 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/storage/delete-bucket.md @@ -0,0 +1,13 @@ +import { Client, Storage } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const storage = new Storage(client); + +const result = await storage.deleteBucket( + '<BUCKET_ID>' // bucketId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/storage/delete-file.md b/docs/examples/1.7.x/console-web/examples/storage/delete-file.md new file mode 100644 index 0000000000..41afa9e375 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/storage/delete-file.md @@ -0,0 +1,14 @@ +import { Client, Storage } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const storage = new Storage(client); + +const result = await storage.deleteFile( + '<BUCKET_ID>', // bucketId + '<FILE_ID>' // fileId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/storage/get-bucket-usage.md b/docs/examples/1.7.x/console-web/examples/storage/get-bucket-usage.md new file mode 100644 index 0000000000..1007454c2e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/storage/get-bucket-usage.md @@ -0,0 +1,14 @@ +import { Client, Storage, StorageUsageRange } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const storage = new Storage(client); + +const result = await storage.getBucketUsage( + '<BUCKET_ID>', // bucketId + StorageUsageRange.TwentyFourHours // range (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/storage/get-bucket.md b/docs/examples/1.7.x/console-web/examples/storage/get-bucket.md new file mode 100644 index 0000000000..ec77dd2bf5 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/storage/get-bucket.md @@ -0,0 +1,13 @@ +import { Client, Storage } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const storage = new Storage(client); + +const result = await storage.getBucket( + '<BUCKET_ID>' // bucketId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/storage/get-file-download.md b/docs/examples/1.7.x/console-web/examples/storage/get-file-download.md new file mode 100644 index 0000000000..8e98105ef3 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/storage/get-file-download.md @@ -0,0 +1,15 @@ +import { Client, Storage } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const storage = new Storage(client); + +const result = storage.getFileDownload( + '<BUCKET_ID>', // bucketId + '<FILE_ID>', // fileId + '<TOKEN>' // token (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/storage/get-file-preview.md b/docs/examples/1.7.x/console-web/examples/storage/get-file-preview.md new file mode 100644 index 0000000000..b14a02769e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/storage/get-file-preview.md @@ -0,0 +1,26 @@ +import { Client, Storage, ImageGravity, ImageFormat } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const storage = new Storage(client); + +const result = storage.getFilePreview( + '<BUCKET_ID>', // bucketId + '<FILE_ID>', // fileId + 0, // width (optional) + 0, // height (optional) + ImageGravity.Center, // gravity (optional) + -1, // quality (optional) + 0, // borderWidth (optional) + '', // borderColor (optional) + 0, // borderRadius (optional) + 0, // opacity (optional) + -360, // rotation (optional) + '', // background (optional) + ImageFormat.Jpg, // output (optional) + '<TOKEN>' // token (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/storage/get-file-view.md b/docs/examples/1.7.x/console-web/examples/storage/get-file-view.md new file mode 100644 index 0000000000..03db75f044 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/storage/get-file-view.md @@ -0,0 +1,15 @@ +import { Client, Storage } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const storage = new Storage(client); + +const result = storage.getFileView( + '<BUCKET_ID>', // bucketId + '<FILE_ID>', // fileId + '<TOKEN>' // token (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/storage/get-file.md b/docs/examples/1.7.x/console-web/examples/storage/get-file.md new file mode 100644 index 0000000000..76658edb0b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/storage/get-file.md @@ -0,0 +1,14 @@ +import { Client, Storage } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const storage = new Storage(client); + +const result = await storage.getFile( + '<BUCKET_ID>', // bucketId + '<FILE_ID>' // fileId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/storage/get-usage.md b/docs/examples/1.7.x/console-web/examples/storage/get-usage.md new file mode 100644 index 0000000000..b57f8f8b03 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/storage/get-usage.md @@ -0,0 +1,13 @@ +import { Client, Storage, StorageUsageRange } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const storage = new Storage(client); + +const result = await storage.getUsage( + StorageUsageRange.TwentyFourHours // range (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/storage/list-buckets.md b/docs/examples/1.7.x/console-web/examples/storage/list-buckets.md new file mode 100644 index 0000000000..f82c01a879 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/storage/list-buckets.md @@ -0,0 +1,14 @@ +import { Client, Storage } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const storage = new Storage(client); + +const result = await storage.listBuckets( + [], // queries (optional) + '<SEARCH>' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/storage/list-files.md b/docs/examples/1.7.x/console-web/examples/storage/list-files.md new file mode 100644 index 0000000000..9076b8997f --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/storage/list-files.md @@ -0,0 +1,15 @@ +import { Client, Storage } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const storage = new Storage(client); + +const result = await storage.listFiles( + '<BUCKET_ID>', // bucketId + [], // queries (optional) + '<SEARCH>' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/storage/update-bucket.md b/docs/examples/1.7.x/console-web/examples/storage/update-bucket.md new file mode 100644 index 0000000000..d6c125a213 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/storage/update-bucket.md @@ -0,0 +1,22 @@ +import { Client, Storage, } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const storage = new Storage(client); + +const result = await storage.updateBucket( + '<BUCKET_ID>', // bucketId + '<NAME>', // name + ["read("any")"], // permissions (optional) + false, // fileSecurity (optional) + false, // enabled (optional) + 1, // maximumFileSize (optional) + [], // allowedFileExtensions (optional) + .None, // compression (optional) + false, // encryption (optional) + false // antivirus (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/storage/update-file.md b/docs/examples/1.7.x/console-web/examples/storage/update-file.md new file mode 100644 index 0000000000..79830f77d2 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/storage/update-file.md @@ -0,0 +1,16 @@ +import { Client, Storage } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const storage = new Storage(client); + +const result = await storage.updateFile( + '<BUCKET_ID>', // bucketId + '<FILE_ID>', // fileId + '<NAME>', // name (optional) + ["read("any")"] // permissions (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/teams/create-membership.md b/docs/examples/1.7.x/console-web/examples/teams/create-membership.md new file mode 100644 index 0000000000..18f6b0ab4d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/teams/create-membership.md @@ -0,0 +1,19 @@ +import { Client, Teams } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const teams = new Teams(client); + +const result = await teams.createMembership( + '<TEAM_ID>', // teamId + [], // roles + 'email@example.com', // email (optional) + '<USER_ID>', // userId (optional) + '+12065550100', // phone (optional) + 'https://example.com', // url (optional) + '<NAME>' // name (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/teams/create.md b/docs/examples/1.7.x/console-web/examples/teams/create.md new file mode 100644 index 0000000000..a33e71ad5f --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/teams/create.md @@ -0,0 +1,15 @@ +import { Client, Teams } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const teams = new Teams(client); + +const result = await teams.create( + '<TEAM_ID>', // teamId + '<NAME>', // name + [] // roles (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/teams/delete-membership.md b/docs/examples/1.7.x/console-web/examples/teams/delete-membership.md new file mode 100644 index 0000000000..a63ed46749 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/teams/delete-membership.md @@ -0,0 +1,14 @@ +import { Client, Teams } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const teams = new Teams(client); + +const result = await teams.deleteMembership( + '<TEAM_ID>', // teamId + '<MEMBERSHIP_ID>' // membershipId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/teams/delete.md b/docs/examples/1.7.x/console-web/examples/teams/delete.md new file mode 100644 index 0000000000..e97cc05cc7 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/teams/delete.md @@ -0,0 +1,13 @@ +import { Client, Teams } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const teams = new Teams(client); + +const result = await teams.delete( + '<TEAM_ID>' // teamId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/teams/get-membership.md b/docs/examples/1.7.x/console-web/examples/teams/get-membership.md new file mode 100644 index 0000000000..bc31ee1470 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/teams/get-membership.md @@ -0,0 +1,14 @@ +import { Client, Teams } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const teams = new Teams(client); + +const result = await teams.getMembership( + '<TEAM_ID>', // teamId + '<MEMBERSHIP_ID>' // membershipId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/teams/get-prefs.md b/docs/examples/1.7.x/console-web/examples/teams/get-prefs.md new file mode 100644 index 0000000000..394848c5c3 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/teams/get-prefs.md @@ -0,0 +1,13 @@ +import { Client, Teams } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const teams = new Teams(client); + +const result = await teams.getPrefs( + '<TEAM_ID>' // teamId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/teams/get.md b/docs/examples/1.7.x/console-web/examples/teams/get.md new file mode 100644 index 0000000000..8c752a9828 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/teams/get.md @@ -0,0 +1,13 @@ +import { Client, Teams } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const teams = new Teams(client); + +const result = await teams.get( + '<TEAM_ID>' // teamId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/teams/list-logs.md b/docs/examples/1.7.x/console-web/examples/teams/list-logs.md new file mode 100644 index 0000000000..004e627f0d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/teams/list-logs.md @@ -0,0 +1,14 @@ +import { Client, Teams } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const teams = new Teams(client); + +const result = await teams.listLogs( + '<TEAM_ID>', // teamId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/teams/list-memberships.md b/docs/examples/1.7.x/console-web/examples/teams/list-memberships.md new file mode 100644 index 0000000000..22fb731175 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/teams/list-memberships.md @@ -0,0 +1,15 @@ +import { Client, Teams } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const teams = new Teams(client); + +const result = await teams.listMemberships( + '<TEAM_ID>', // teamId + [], // queries (optional) + '<SEARCH>' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/teams/list.md b/docs/examples/1.7.x/console-web/examples/teams/list.md new file mode 100644 index 0000000000..c51dfaf389 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/teams/list.md @@ -0,0 +1,14 @@ +import { Client, Teams } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const teams = new Teams(client); + +const result = await teams.list( + [], // queries (optional) + '<SEARCH>' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/teams/update-membership-status.md b/docs/examples/1.7.x/console-web/examples/teams/update-membership-status.md new file mode 100644 index 0000000000..c8e608278e --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/teams/update-membership-status.md @@ -0,0 +1,16 @@ +import { Client, Teams } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const teams = new Teams(client); + +const result = await teams.updateMembershipStatus( + '<TEAM_ID>', // teamId + '<MEMBERSHIP_ID>', // membershipId + '<USER_ID>', // userId + '<SECRET>' // secret +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/teams/update-membership.md b/docs/examples/1.7.x/console-web/examples/teams/update-membership.md new file mode 100644 index 0000000000..d3e0164a17 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/teams/update-membership.md @@ -0,0 +1,15 @@ +import { Client, Teams } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const teams = new Teams(client); + +const result = await teams.updateMembership( + '<TEAM_ID>', // teamId + '<MEMBERSHIP_ID>', // membershipId + [] // roles +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/teams/update-name.md b/docs/examples/1.7.x/console-web/examples/teams/update-name.md new file mode 100644 index 0000000000..43703d0c98 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/teams/update-name.md @@ -0,0 +1,14 @@ +import { Client, Teams } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const teams = new Teams(client); + +const result = await teams.updateName( + '<TEAM_ID>', // teamId + '<NAME>' // name +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/teams/update-prefs.md b/docs/examples/1.7.x/console-web/examples/teams/update-prefs.md new file mode 100644 index 0000000000..e0acff0a30 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/teams/update-prefs.md @@ -0,0 +1,14 @@ +import { Client, Teams } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const teams = new Teams(client); + +const result = await teams.updatePrefs( + '<TEAM_ID>', // teamId + {} // prefs +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/tokens/create-file-token.md b/docs/examples/1.7.x/console-web/examples/tokens/create-file-token.md new file mode 100644 index 0000000000..bac4863159 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/tokens/create-file-token.md @@ -0,0 +1,15 @@ +import { Client, Tokens } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const tokens = new Tokens(client); + +const result = await tokens.createFileToken( + '<BUCKET_ID>', // bucketId + '<FILE_ID>', // fileId + '' // expire (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/tokens/delete.md b/docs/examples/1.7.x/console-web/examples/tokens/delete.md new file mode 100644 index 0000000000..0a871d0fe4 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/tokens/delete.md @@ -0,0 +1,13 @@ +import { Client, Tokens } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const tokens = new Tokens(client); + +const result = await tokens.delete( + '<TOKEN_ID>' // tokenId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/tokens/get.md b/docs/examples/1.7.x/console-web/examples/tokens/get.md new file mode 100644 index 0000000000..ee83fb83c2 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/tokens/get.md @@ -0,0 +1,13 @@ +import { Client, Tokens } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const tokens = new Tokens(client); + +const result = await tokens.get( + '<TOKEN_ID>' // tokenId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/tokens/list.md b/docs/examples/1.7.x/console-web/examples/tokens/list.md new file mode 100644 index 0000000000..33077e26dd --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/tokens/list.md @@ -0,0 +1,15 @@ +import { Client, Tokens } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const tokens = new Tokens(client); + +const result = await tokens.list( + '<BUCKET_ID>', // bucketId + '<FILE_ID>', // fileId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/tokens/update.md b/docs/examples/1.7.x/console-web/examples/tokens/update.md new file mode 100644 index 0000000000..ce3b80dd22 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/tokens/update.md @@ -0,0 +1,14 @@ +import { Client, Tokens } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const tokens = new Tokens(client); + +const result = await tokens.update( + '<TOKEN_ID>', // tokenId + '' // expire (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/create-argon2user.md b/docs/examples/1.7.x/console-web/examples/users/create-argon2user.md new file mode 100644 index 0000000000..c190225d4b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/create-argon2user.md @@ -0,0 +1,16 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.createArgon2User( + '<USER_ID>', // userId + 'email@example.com', // email + 'password', // password + '<NAME>' // name (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/create-bcrypt-user.md b/docs/examples/1.7.x/console-web/examples/users/create-bcrypt-user.md new file mode 100644 index 0000000000..9c51181890 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/create-bcrypt-user.md @@ -0,0 +1,16 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.createBcryptUser( + '<USER_ID>', // userId + 'email@example.com', // email + 'password', // password + '<NAME>' // name (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/create-j-w-t.md b/docs/examples/1.7.x/console-web/examples/users/create-j-w-t.md new file mode 100644 index 0000000000..7d50fbce03 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/create-j-w-t.md @@ -0,0 +1,15 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.createJWT( + '<USER_ID>', // userId + '<SESSION_ID>', // sessionId (optional) + 0 // duration (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/create-m-d5user.md b/docs/examples/1.7.x/console-web/examples/users/create-m-d5user.md new file mode 100644 index 0000000000..610f795ab0 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/create-m-d5user.md @@ -0,0 +1,16 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.createMD5User( + '<USER_ID>', // userId + 'email@example.com', // email + 'password', // password + '<NAME>' // name (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/create-mfa-recovery-codes.md b/docs/examples/1.7.x/console-web/examples/users/create-mfa-recovery-codes.md new file mode 100644 index 0000000000..ea52af9cf8 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/create-mfa-recovery-codes.md @@ -0,0 +1,13 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.createMfaRecoveryCodes( + '<USER_ID>' // userId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/create-p-h-pass-user.md b/docs/examples/1.7.x/console-web/examples/users/create-p-h-pass-user.md new file mode 100644 index 0000000000..c9437c5c38 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/create-p-h-pass-user.md @@ -0,0 +1,16 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.createPHPassUser( + '<USER_ID>', // userId + 'email@example.com', // email + 'password', // password + '<NAME>' // name (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/create-s-h-a-user.md b/docs/examples/1.7.x/console-web/examples/users/create-s-h-a-user.md new file mode 100644 index 0000000000..b70f09c133 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/create-s-h-a-user.md @@ -0,0 +1,17 @@ +import { Client, Users, PasswordHash } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.createSHAUser( + '<USER_ID>', // userId + 'email@example.com', // email + 'password', // password + PasswordHash.Sha1, // passwordVersion (optional) + '<NAME>' // name (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/create-scrypt-modified-user.md b/docs/examples/1.7.x/console-web/examples/users/create-scrypt-modified-user.md new file mode 100644 index 0000000000..c0a0435b67 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/create-scrypt-modified-user.md @@ -0,0 +1,19 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.createScryptModifiedUser( + '<USER_ID>', // userId + 'email@example.com', // email + 'password', // password + '<PASSWORD_SALT>', // passwordSalt + '<PASSWORD_SALT_SEPARATOR>', // passwordSaltSeparator + '<PASSWORD_SIGNER_KEY>', // passwordSignerKey + '<NAME>' // name (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/create-scrypt-user.md b/docs/examples/1.7.x/console-web/examples/users/create-scrypt-user.md new file mode 100644 index 0000000000..f1cb93637a --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/create-scrypt-user.md @@ -0,0 +1,21 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.createScryptUser( + '<USER_ID>', // userId + 'email@example.com', // email + 'password', // password + '<PASSWORD_SALT>', // passwordSalt + null, // passwordCpu + null, // passwordMemory + null, // passwordParallel + null, // passwordLength + '<NAME>' // name (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/create-session.md b/docs/examples/1.7.x/console-web/examples/users/create-session.md new file mode 100644 index 0000000000..5393c4408d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/create-session.md @@ -0,0 +1,13 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.createSession( + '<USER_ID>' // userId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/create-target.md b/docs/examples/1.7.x/console-web/examples/users/create-target.md new file mode 100644 index 0000000000..4c8eac9c45 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/create-target.md @@ -0,0 +1,18 @@ +import { Client, Users, MessagingProviderType } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.createTarget( + '<USER_ID>', // userId + '<TARGET_ID>', // targetId + MessagingProviderType.Email, // providerType + '<IDENTIFIER>', // identifier + '<PROVIDER_ID>', // providerId (optional) + '<NAME>' // name (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/create-token.md b/docs/examples/1.7.x/console-web/examples/users/create-token.md new file mode 100644 index 0000000000..58e8c9f035 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/create-token.md @@ -0,0 +1,15 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.createToken( + '<USER_ID>', // userId + 4, // length (optional) + 60 // expire (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/create.md b/docs/examples/1.7.x/console-web/examples/users/create.md new file mode 100644 index 0000000000..131ef1290c --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/create.md @@ -0,0 +1,17 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.create( + '<USER_ID>', // userId + 'email@example.com', // email (optional) + '+12065550100', // phone (optional) + '', // password (optional) + '<NAME>' // name (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/delete-identity.md b/docs/examples/1.7.x/console-web/examples/users/delete-identity.md new file mode 100644 index 0000000000..cf7425c843 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/delete-identity.md @@ -0,0 +1,13 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.deleteIdentity( + '<IDENTITY_ID>' // identityId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/delete-mfa-authenticator.md b/docs/examples/1.7.x/console-web/examples/users/delete-mfa-authenticator.md new file mode 100644 index 0000000000..023686ae26 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/delete-mfa-authenticator.md @@ -0,0 +1,14 @@ +import { Client, Users, AuthenticatorType } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.deleteMfaAuthenticator( + '<USER_ID>', // userId + AuthenticatorType.Totp // type +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/delete-session.md b/docs/examples/1.7.x/console-web/examples/users/delete-session.md new file mode 100644 index 0000000000..ca6880431b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/delete-session.md @@ -0,0 +1,14 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.deleteSession( + '<USER_ID>', // userId + '<SESSION_ID>' // sessionId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/delete-sessions.md b/docs/examples/1.7.x/console-web/examples/users/delete-sessions.md new file mode 100644 index 0000000000..1137a8b29b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/delete-sessions.md @@ -0,0 +1,13 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.deleteSessions( + '<USER_ID>' // userId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/delete-target.md b/docs/examples/1.7.x/console-web/examples/users/delete-target.md new file mode 100644 index 0000000000..386d8a90b5 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/delete-target.md @@ -0,0 +1,14 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.deleteTarget( + '<USER_ID>', // userId + '<TARGET_ID>' // targetId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/delete.md b/docs/examples/1.7.x/console-web/examples/users/delete.md new file mode 100644 index 0000000000..1d4b1d0e1c --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/delete.md @@ -0,0 +1,13 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.delete( + '<USER_ID>' // userId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/get-mfa-recovery-codes.md b/docs/examples/1.7.x/console-web/examples/users/get-mfa-recovery-codes.md new file mode 100644 index 0000000000..02d17649c8 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/get-mfa-recovery-codes.md @@ -0,0 +1,13 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.getMfaRecoveryCodes( + '<USER_ID>' // userId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/get-prefs.md b/docs/examples/1.7.x/console-web/examples/users/get-prefs.md new file mode 100644 index 0000000000..b24f2bd3ae --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/get-prefs.md @@ -0,0 +1,13 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.getPrefs( + '<USER_ID>' // userId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/get-target.md b/docs/examples/1.7.x/console-web/examples/users/get-target.md new file mode 100644 index 0000000000..cfa7d3d5cd --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/get-target.md @@ -0,0 +1,14 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.getTarget( + '<USER_ID>', // userId + '<TARGET_ID>' // targetId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/get-usage.md b/docs/examples/1.7.x/console-web/examples/users/get-usage.md new file mode 100644 index 0000000000..bd87faf10f --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/get-usage.md @@ -0,0 +1,13 @@ +import { Client, Users, UserUsageRange } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.getUsage( + UserUsageRange.TwentyFourHours // range (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/get.md b/docs/examples/1.7.x/console-web/examples/users/get.md new file mode 100644 index 0000000000..77f5006890 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/get.md @@ -0,0 +1,13 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.get( + '<USER_ID>' // userId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/list-identities.md b/docs/examples/1.7.x/console-web/examples/users/list-identities.md new file mode 100644 index 0000000000..34b92900a7 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/list-identities.md @@ -0,0 +1,14 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.listIdentities( + [], // queries (optional) + '<SEARCH>' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/list-logs.md b/docs/examples/1.7.x/console-web/examples/users/list-logs.md new file mode 100644 index 0000000000..85e6cf5071 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/list-logs.md @@ -0,0 +1,14 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.listLogs( + '<USER_ID>', // userId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/list-memberships.md b/docs/examples/1.7.x/console-web/examples/users/list-memberships.md new file mode 100644 index 0000000000..01ce244361 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/list-memberships.md @@ -0,0 +1,15 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.listMemberships( + '<USER_ID>', // userId + [], // queries (optional) + '<SEARCH>' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/list-mfa-factors.md b/docs/examples/1.7.x/console-web/examples/users/list-mfa-factors.md new file mode 100644 index 0000000000..fe1dd23594 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/list-mfa-factors.md @@ -0,0 +1,13 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.listMfaFactors( + '<USER_ID>' // userId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/list-sessions.md b/docs/examples/1.7.x/console-web/examples/users/list-sessions.md new file mode 100644 index 0000000000..e3d5d6e51d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/list-sessions.md @@ -0,0 +1,13 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.listSessions( + '<USER_ID>' // userId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/list-targets.md b/docs/examples/1.7.x/console-web/examples/users/list-targets.md new file mode 100644 index 0000000000..58f4079aee --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/list-targets.md @@ -0,0 +1,14 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.listTargets( + '<USER_ID>', // userId + [] // queries (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/list.md b/docs/examples/1.7.x/console-web/examples/users/list.md new file mode 100644 index 0000000000..d2189b9c93 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/list.md @@ -0,0 +1,14 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.list( + [], // queries (optional) + '<SEARCH>' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/update-email-verification.md b/docs/examples/1.7.x/console-web/examples/users/update-email-verification.md new file mode 100644 index 0000000000..3fedd4b86f --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/update-email-verification.md @@ -0,0 +1,14 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.updateEmailVerification( + '<USER_ID>', // userId + false // emailVerification +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/update-email.md b/docs/examples/1.7.x/console-web/examples/users/update-email.md new file mode 100644 index 0000000000..9922376778 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/update-email.md @@ -0,0 +1,14 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.updateEmail( + '<USER_ID>', // userId + 'email@example.com' // email +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/update-labels.md b/docs/examples/1.7.x/console-web/examples/users/update-labels.md new file mode 100644 index 0000000000..4fc268fc3c --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/update-labels.md @@ -0,0 +1,14 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.updateLabels( + '<USER_ID>', // userId + [] // labels +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/update-mfa-recovery-codes.md b/docs/examples/1.7.x/console-web/examples/users/update-mfa-recovery-codes.md new file mode 100644 index 0000000000..041cd9098b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/update-mfa-recovery-codes.md @@ -0,0 +1,13 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.updateMfaRecoveryCodes( + '<USER_ID>' // userId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/update-mfa.md b/docs/examples/1.7.x/console-web/examples/users/update-mfa.md new file mode 100644 index 0000000000..af710ecd48 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/update-mfa.md @@ -0,0 +1,14 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.updateMfa( + '<USER_ID>', // userId + false // mfa +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/update-name.md b/docs/examples/1.7.x/console-web/examples/users/update-name.md new file mode 100644 index 0000000000..b57cb33730 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/update-name.md @@ -0,0 +1,14 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.updateName( + '<USER_ID>', // userId + '<NAME>' // name +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/update-password.md b/docs/examples/1.7.x/console-web/examples/users/update-password.md new file mode 100644 index 0000000000..e9c7f9b51d --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/update-password.md @@ -0,0 +1,14 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.updatePassword( + '<USER_ID>', // userId + '' // password +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/update-phone-verification.md b/docs/examples/1.7.x/console-web/examples/users/update-phone-verification.md new file mode 100644 index 0000000000..a29e38591c --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/update-phone-verification.md @@ -0,0 +1,14 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.updatePhoneVerification( + '<USER_ID>', // userId + false // phoneVerification +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/update-phone.md b/docs/examples/1.7.x/console-web/examples/users/update-phone.md new file mode 100644 index 0000000000..a87780161b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/update-phone.md @@ -0,0 +1,14 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.updatePhone( + '<USER_ID>', // userId + '+12065550100' // number +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/update-prefs.md b/docs/examples/1.7.x/console-web/examples/users/update-prefs.md new file mode 100644 index 0000000000..7d9993bbb1 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/update-prefs.md @@ -0,0 +1,14 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.updatePrefs( + '<USER_ID>', // userId + {} // prefs +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/update-status.md b/docs/examples/1.7.x/console-web/examples/users/update-status.md new file mode 100644 index 0000000000..5e823e7a48 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/update-status.md @@ -0,0 +1,14 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.updateStatus( + '<USER_ID>', // userId + false // status +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/users/update-target.md b/docs/examples/1.7.x/console-web/examples/users/update-target.md new file mode 100644 index 0000000000..ed33fe9bb0 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/users/update-target.md @@ -0,0 +1,17 @@ +import { Client, Users } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const users = new Users(client); + +const result = await users.updateTarget( + '<USER_ID>', // userId + '<TARGET_ID>', // targetId + '<IDENTIFIER>', // identifier (optional) + '<PROVIDER_ID>', // providerId (optional) + '<NAME>' // name (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/vcs/create-repository-detection.md b/docs/examples/1.7.x/console-web/examples/vcs/create-repository-detection.md new file mode 100644 index 0000000000..84de3ffb26 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/vcs/create-repository-detection.md @@ -0,0 +1,16 @@ +import { Client, Vcs, VCSDetectionType } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const vcs = new Vcs(client); + +const result = await vcs.createRepositoryDetection( + '<INSTALLATION_ID>', // installationId + '<PROVIDER_REPOSITORY_ID>', // providerRepositoryId + VCSDetectionType.Runtime, // type + '<PROVIDER_ROOT_DIRECTORY>' // providerRootDirectory (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/vcs/create-repository.md b/docs/examples/1.7.x/console-web/examples/vcs/create-repository.md new file mode 100644 index 0000000000..1d08ac5b09 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/vcs/create-repository.md @@ -0,0 +1,15 @@ +import { Client, Vcs } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const vcs = new Vcs(client); + +const result = await vcs.createRepository( + '<INSTALLATION_ID>', // installationId + '<NAME>', // name + false // private +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/vcs/delete-installation.md b/docs/examples/1.7.x/console-web/examples/vcs/delete-installation.md new file mode 100644 index 0000000000..3f760c09b6 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/vcs/delete-installation.md @@ -0,0 +1,13 @@ +import { Client, Vcs } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const vcs = new Vcs(client); + +const result = await vcs.deleteInstallation( + '<INSTALLATION_ID>' // installationId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/vcs/get-installation.md b/docs/examples/1.7.x/console-web/examples/vcs/get-installation.md new file mode 100644 index 0000000000..4230f2bd9a --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/vcs/get-installation.md @@ -0,0 +1,13 @@ +import { Client, Vcs } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const vcs = new Vcs(client); + +const result = await vcs.getInstallation( + '<INSTALLATION_ID>' // installationId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/vcs/get-repository-contents.md b/docs/examples/1.7.x/console-web/examples/vcs/get-repository-contents.md new file mode 100644 index 0000000000..8a04ba1ae4 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/vcs/get-repository-contents.md @@ -0,0 +1,15 @@ +import { Client, Vcs } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const vcs = new Vcs(client); + +const result = await vcs.getRepositoryContents( + '<INSTALLATION_ID>', // installationId + '<PROVIDER_REPOSITORY_ID>', // providerRepositoryId + '<PROVIDER_ROOT_DIRECTORY>' // providerRootDirectory (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/vcs/get-repository.md b/docs/examples/1.7.x/console-web/examples/vcs/get-repository.md new file mode 100644 index 0000000000..516265a0c8 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/vcs/get-repository.md @@ -0,0 +1,14 @@ +import { Client, Vcs } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const vcs = new Vcs(client); + +const result = await vcs.getRepository( + '<INSTALLATION_ID>', // installationId + '<PROVIDER_REPOSITORY_ID>' // providerRepositoryId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/vcs/list-installations.md b/docs/examples/1.7.x/console-web/examples/vcs/list-installations.md new file mode 100644 index 0000000000..1ba1e64615 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/vcs/list-installations.md @@ -0,0 +1,14 @@ +import { Client, Vcs } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const vcs = new Vcs(client); + +const result = await vcs.listInstallations( + [], // queries (optional) + '<SEARCH>' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/vcs/list-repositories.md b/docs/examples/1.7.x/console-web/examples/vcs/list-repositories.md new file mode 100644 index 0000000000..f414ec316b --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/vcs/list-repositories.md @@ -0,0 +1,15 @@ +import { Client, Vcs, VCSDetectionType } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const vcs = new Vcs(client); + +const result = await vcs.listRepositories( + '<INSTALLATION_ID>', // installationId + VCSDetectionType.Runtime, // type + '<SEARCH>' // search (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/vcs/list-repository-branches.md b/docs/examples/1.7.x/console-web/examples/vcs/list-repository-branches.md new file mode 100644 index 0000000000..ba6b86a053 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/vcs/list-repository-branches.md @@ -0,0 +1,14 @@ +import { Client, Vcs } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const vcs = new Vcs(client); + +const result = await vcs.listRepositoryBranches( + '<INSTALLATION_ID>', // installationId + '<PROVIDER_REPOSITORY_ID>' // providerRepositoryId +); + +console.log(result); diff --git a/docs/examples/1.7.x/console-web/examples/vcs/update-external-deployments.md b/docs/examples/1.7.x/console-web/examples/vcs/update-external-deployments.md new file mode 100644 index 0000000000..31425cb883 --- /dev/null +++ b/docs/examples/1.7.x/console-web/examples/vcs/update-external-deployments.md @@ -0,0 +1,15 @@ +import { Client, Vcs } from "@appwrite.io/console"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const vcs = new Vcs(client); + +const result = await vcs.updateExternalDeployments( + '<INSTALLATION_ID>', // installationId + '<REPOSITORY_ID>', // repositoryId + '<PROVIDER_PULL_REQUEST_ID>' // providerPullRequestId +); + +console.log(result); diff --git a/src/Appwrite/Platform/Tasks/SDKs.php b/src/Appwrite/Platform/Tasks/SDKs.php index cf917ae96b..a0009fd59f 100644 --- a/src/Appwrite/Platform/Tasks/SDKs.php +++ b/src/Appwrite/Platform/Tasks/SDKs.php @@ -312,7 +312,5 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND } } } - - Console::exit(); } } diff --git a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php index 31ed14b198..19742ee3ee 100644 --- a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php @@ -309,7 +309,7 @@ class OpenAPI3 extends Format $bodyRequired = []; foreach ($route->getParams() as $name => $param) { // Set params - if ($param['deprecated']) { + if (($param['deprecated'] ?? false) === true) { continue; } diff --git a/src/Appwrite/SDK/Specification/Format/Swagger2.php b/src/Appwrite/SDK/Specification/Format/Swagger2.php index 86c9420739..bac483ffee 100644 --- a/src/Appwrite/SDK/Specification/Format/Swagger2.php +++ b/src/Appwrite/SDK/Specification/Format/Swagger2.php @@ -314,7 +314,7 @@ class Swagger2 extends Format ); foreach ($parameters as $name => $param) { // Set params - if ($param['deprecated']) { + if (($param['deprecated'] ?? false) === true) { continue; } From 455554a6a2afe4f54ce3d36d542c0da09caf12b5 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Tue, 20 May 2025 11:06:09 +0100 Subject: [PATCH 028/219] fix: download endpoint --- app/controllers/api/storage.php | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 78c4c5fec9..a96b871bf2 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -1225,12 +1225,15 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') if (!empty($source)) { if (!empty($rangeHeader)) { $response->send(substr($source, $start, ($end - $start + 1))); + return; } $response->send($source); + return; } if (!empty($rangeHeader)) { $response->send($deviceForFiles->read($path, $start, ($end - $start + 1))); + return; } if ($size > APP_STORAGE_READ_BUFFER) { @@ -1383,6 +1386,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') if (!empty($source)) { if (!empty($rangeHeader)) { $response->send(substr($source, $start, ($end - $start + 1))); + return; } $response->send($source); return; @@ -1534,6 +1538,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') if (!empty($source)) { if (!empty($rangeHeader)) { $response->send(substr($source, $start, ($end - $start + 1))); + return; } $response->send($source); return; From bc5343b559359b78718cf689cea3b768b660f600 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Tue, 20 May 2025 23:27:31 +1200 Subject: [PATCH 029/219] Apply suggestions from code review --- app/controllers/api/databases.php | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 15eef93160..cd2fef8dca 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4203,7 +4203,6 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum }); App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId') - ->alias('/v1/database/collections/:collectionId/documents/:documentId') ->desc('Upsert document') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].update') @@ -4231,7 +4230,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ->param('databaseId', '', new CustomId(), 'Database ID.') ->param('collectionId', '', new CustomId(), 'Collection ID.') ->param('documentId', '', new CustomId(), 'Document ID.') - ->param('data', [], new JSON(), 'Document data as JSON object. Include only attribute and value pairs to be updated.') + ->param('data', [], new JSON(), 'Document data as JSON object. Include all required attributes of the document to be created or updated.') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) ->inject('requestTimestamp') ->inject('response') From 69adb689f877cafe2c1eb9f4d83aea6d6a9262f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= <matejbaco2000@gmail.com> Date: Tue, 20 May 2025 14:16:04 +0200 Subject: [PATCH 030/219] Upgrade console --- app/views/install/compose.phtml | 2 +- docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index 6f6fac3f77..f53a6f2545 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -177,7 +177,7 @@ $image = $this->getParam('image', ''); appwrite-console: <<: *x-logging container_name: appwrite-console - image: <?php echo $organization; ?>/console:6.0.1 + image: <?php echo $organization; ?>/console:6.0.8 restart: unless-stopped networks: - appwrite diff --git a/docker-compose.yml b/docker-compose.yml index 48a94f6ce1..6c7900ac78 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -213,7 +213,7 @@ services: appwrite-console: <<: *x-logging container_name: appwrite-console - image: appwrite/console:6.0.7 + image: appwrite/console:6.0.8 restart: unless-stopped networks: - appwrite From c5a08b69b0d87e9896a3b29b2eb43893ac2e422d Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k <arnabchatterjee.ac.2@gmail.com> Date: Tue, 20 May 2025 18:14:51 +0530 Subject: [PATCH 031/219] changed custom id to uid --- app/controllers/api/databases.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index cd2fef8dca..03016d8e2e 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4227,8 +4227,8 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen ], contentType: ContentType::JSON )) - ->param('databaseId', '', new CustomId(), 'Database ID.') - ->param('collectionId', '', new CustomId(), 'Collection ID.') + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') ->param('documentId', '', new CustomId(), 'Document ID.') ->param('data', [], new JSON(), 'Document data as JSON object. Include all required attributes of the document to be created or updated.') ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) From fe763093df4d91d21cbc015c237078e26cbf0a0e Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Wed, 21 May 2025 00:58:32 +1200 Subject: [PATCH 032/219] Catch query exception on get document for selects --- app/controllers/api/databases.php | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 675268b894..138428ef75 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -3785,7 +3785,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId, $queries); + try { + $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId, $queries); + } catch (QueryException $e) { + throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); + } + if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); } From 2ad439095851ba939ca3339dca22cc069ab1a907 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= <matejbaco2000@gmail.com> Date: Tue, 20 May 2025 15:03:45 +0200 Subject: [PATCH 033/219] Add lynx gallery --- app/config/templates/site.php | 19 ++++++++++++++++++ .../sites/templates/gallery-for-lynx-dark.png | Bin 0 -> 613188 bytes .../templates/gallery-for-lynx-light.png | Bin 0 -> 613188 bytes 3 files changed, 19 insertions(+) create mode 100644 public/images/sites/templates/gallery-for-lynx-dark.png create mode 100644 public/images/sites/templates/gallery-for-lynx-light.png diff --git a/app/config/templates/site.php b/app/config/templates/site.php index eec129a7bf..27b2cd7c0c 100644 --- a/app/config/templates/site.php +++ b/app/config/templates/site.php @@ -1351,4 +1351,23 @@ return [ 'providerVersion' => '0.3.*', 'variables' => [], ], + [ + 'key' => 'gallery-for-lynx', + 'name' => 'Lynx gallery', + 'tagline' => 'A Lynx website showcasing gallery with smooth animations.', + 'score' => 1, // 0 to 10 based on looks of screenshot (avoid 1,2,3,8,9,10 if possible) + 'useCases' => [UseCases::STARTER], + 'screenshotDark' => $url . '/images/sites/templates/gallery-for-lynx-dark.png', + 'screenshotLight' => $url . '/images/sites/templates/gallery-for-lynx-light.png', + 'frameworks' => [ + getFramework('LYNX', [ + 'providerRootDirectory' => './lynx/gallery', + ]), + ], + 'vcsProvider' => 'github', + 'providerRepositoryId' => 'templates-for-sites', + 'providerOwner' => 'appwrite', + 'providerVersion' => '0.3.*', + 'variables' => [] + ], ]; diff --git a/public/images/sites/templates/gallery-for-lynx-dark.png b/public/images/sites/templates/gallery-for-lynx-dark.png new file mode 100644 index 0000000000000000000000000000000000000000..9dfd278985684287e5ea1651d69930f0540001c3 GIT binary patch literal 613188 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∨^^ZfnTCx2f=Du}VlH5iQU{;;e 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%0Ap60SFp-&<pK_mu9B5GRA1i_Hd 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∋n)B2!*1Hi@qGOLb^UTWeSWF+2jcmx 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­k1hk! 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%0DB5D=j2sTm{7epM)0p~0#dUbri zDFXWz!$@X7ydE9{QN)~;&C}T?DVeAqXuY>>o{-#?PGxzv`W|3Ql&qxqNWw(3G7P-b zhrn^zZeA8H4Tc;MImRFf%`l8)IGFj!gglSPA0A}kARzf<$6n@5-~z&>eYk;&tu^~C zk<yQZ1Hp@qp-MGjfZ<mm42uqQ$-QdPc4sx|)CPO&c^UZv{)Zlv0(HGLZU~>p4D-){ zF;;vLu$_r~8>&Mpb=s!a?L~SzQvh|HV(?t5c$l9I=25gzS^-Ldw{!#q9bL`bINM<+ zc{X46l+o#X_kNWOdFX;x&AY&~DByt@h3f-9BVoE*IHRgNI)ZTOljlC2AQ<Wal#t2I z<gp~lB0suD#^@zcY7MQe9;nSf&yS`V0Z`1dS9QdpLZ!r=F@0-Ruwc@6N<!-DLT3Kq z`%Bi0GQS&OtQM%qK;uGSDi@q`I;>}&C1zjEkvBXSz#|rthMFbKqF=E8Wsu(3>HoYM z`0Dmt^YC95;3V*0f6wdv!;|ZWxFO1r<db259JDfZ3ivo?tNq>T?l2MK?)Q$x_N}4b z`SH3w;E=sK!^^UHq2{=@-Z?*EI8xqhev8L3S^(miPe+Nyb=Ubd#cIr(#?Tvk7C+|c zz6XB`O5L16uh)*VS9Wr@+Z1L!)CVMV%0AqOV$*cx4-GBR?{ea~uxx0jhe@l&pb_ZL zHJ@r2BM|hCSvrHe+8Dffm@hP<^d$X7Hx<g|0O2A$IPx0=@QBUnTwJDGh;mYEo?<@o zF>q=H%Kj=`3{PlaN1%TVIX%uzCWccCQ=7kww*1(rmy|Mr4lETLh!Zju8}yH4Z^#@% z<=90w^FbF3@HU>Xp;Q&4ZXP>e5QWwD8RV$v(t7UsNh}MvmWy`DVPhHe^vQ3p2RTjh zMIY61kkB42fI>z0;OK;lub27<C;n}sq=oplSE#=VzGa2FS+G8dm%~d|nB5l_Uj^>U zYnVTfKRqV6cCdTD3*(T7>~m|Uh0*>-5`?07tiJDU@awK#;P2^jjpN5gjbi`9x$d9O z+vP~H8N61^!(V};ZrVg8)Y21AV<9H+dasm?9xA+sO3X<qp+Zi+jW2P5I+b$HHKm6$ zS@%@8#=khnf`oONq&nsB8EAH>n1jaUTrV^Se76d9+WDmXDR<03GhH4Fqc4O=ECu;@ z2yotH-FhsdJgsMg)T+f{TxDWG;o9rTG8ijIvtdKEn};JCD36CDI4pN>-6U7isTzgq zMSAW<Zh2btcf-;xR$N8w&_Gsdd`{0^u0{NWgqliV&pq|2&J8fojPviqQ^nD<_Az9( z1-^=_6>}jn{G<Oco+hOuzYpe%nPsb+_7ClNdF;%av~l;KQWSpk+~Ly&QmT4WTd1S^ zpqj}N2TCr!54Owm1HJekFkyjk5RJMWI%+QW>_aA4PPgHV^G)dT?nTV+b=^M`i!wWz zRhTSGv9T%XYIZm>MC7ItqKoN`Gy|Qxe4{~`Nc(4%q;$@$Rav?u<n#hLE_4!MDDw%{ zC66mc;6jJLu<8RpoBLn)ECU~g3qGEZ`~QwwzMJQ_lZYXyIVhLI#gKVnCRr$1K!<{F zLi_yG%?Pnjtii&{wrYd`H?=rz6jSxz<9Z=D3DqkE|Klz_*^2+v2jf@;*|}&8e1z8$ z8u4Q$^ij2EPtfZBYvabF$7Y6lL$4x?rGvS{@9l1`6s(Y5TdrvLy2zIX2?nHW&U@LP z^$BeuRD&X|JJhcCB4%9N{$AwQVP%z|Pn)zLk<_oi3K;3YdvBn)*a<a?BL7j6<7?Bq z*{L9Mm%^wPru;oaP$=Vc9}8VdZTP0M(3CCKd#~Ev7S@!0)-`J6y1{&sH_Q1mUQi9K zJY6%lD2)q}yn}t=sO0J;-5+$|_r%0@*iBiEC$o1--~k_tI8w6er4HA^K@8rg)vROv zUy~vaiXZ)F?f(K87_DyPLGrJzG7Nh@?qdr+mXZHBw!e5d{{Q$2bbQ#CbeGT&R&iqg zn_amHMrE{5`E4PH?h|&7w@QG*Zdw~wwT|&M=oL-(y30WGqbP9knBwKL8Z+0m#?b&# z0r^`9t@+NNTx9uYx16Ll1ouoQ|2Ypu){%M{nX3Y;oCbo`0C&hDPMK23k(`{Z5f~rN zJ2nl1L8rV5aKh{@udy_M&(z$}<*g=`m+GafYp?0Rz?=dbR5;@`>FoEQL2AI0$v6?! z(Tv_(t^3XX9^LKihlny3<`B(PMzMCLzTY;Rlo+dSN3SN+I+qCA=g1IZB@T6n5A<l( z7WSubGNP_JhKQUCcZ$<c+7MPTBw#JKQuAha#HRYz$D<mvyrPYszq^e;$BFF^ulq)t zP_`_m<qw`nY^qdSGI|ZzXM|T~ey^9a?5)fXxsOb#J7&G=UrJl_GAAh<qpn3|AvqkB z;nc5HXJw19+s1@iNew~@2s+o?;VbZoTb-ATsrBMu0kdGYz1y4riC$4(zlY<!P)8I} z+kNTi9{i}+1u~DL1{7}_e3}kIm|FwPsl0pfqx6qM{_fI^J@JKDay4~J*!iKPx$9`y zJWlwRIQ;&W)}R!Hrn5AsYIC&RaeA}t9uto7b#Hp&MjQ9XVeBDr)j7^nj5fk6LV-*h z@?tw+9rB6_9qskfxkx?lxeNo0=8^gs?kq>52?$vy{XT@Jb`8!7L~a13gmgmW`Hl73 zPl<>Jqv^B4cNb>LyE1DZ3D{_;1F^$j!hn()g5W4Z<1BZK@(N*S%#=uT`;W!%>B;hA zc#g(+OP4VWd??_Mo-T!tUI{By*5oVTU)Fk)dlV&<AcFmh3vS1JQ&a`8>9$N9QU*Mj zc1aBsRC>2ugQTyhx=%I%yW8i<fQ&k1Lyo!8ZSXd^;WDLj-h5l;u0q*mve<pqjd$R1 z2EL)@7fOSza+3G}fBtlyyijj(Og}0vg|-?+5VkJS@I0nSt@jKU>DrtgaT4!zO3_>4 zP;yHd`z<bl|Cm-;6zzql6{6A*4~op$$i>y!-Br9I!=^q+U%PMj|BLsdcFy|1yW1;6 zPKN0<cy1C{4qn%!HAdOKB=CWK9N4;)<lfs|q(Mq~1u)vIkBPzJy%E;;wZ7Jl&fBaE zv+zmU7(G_XfaqKIuwP^c60v2!wlKLNm=A9k@x_hT(z9ICQp~85u-ey*W(nx*m-mmW z_DAW{F_|4>;Jl2qhd_GZ$_IYL9_DuH#1wEytyZdN)0r)j_?$AmTmBN&>rSwCj*e?B z)DH&!5vhf-ht1w4n{Au=rw6=2j=DtyG<O^bVNEth0cDf&cYwygk5Z#JR4D@EnyDEi z4zbDRW-5L7b-JINX^Jv2Vi5I=n`1EpaDS;@y+K+J0Z(%TVCw$WkEcr`DmKgdu=AYr z4D({d&n2T@x>1Z>(7rSMEXHK^3N>r}Eux;8{}^%H5R|(r#blNLIHjil7EoMSM3UM- z_2Lg%^E{y~+!yxeLzBt8j}_(BRujiB`fI_**h(+nL?MMCv}LWS1F+RpnE(T;IE~in z<FRt=e{*@?M7&}E`Sag&`MBTIEcm)Sa16}JT{WgRf+|`a_m*sm00!esn&%`fjvNbX z_^EI?7n$6*@UEmU;hE&xa6#3mixm8zj^>9@5eeJ7G@E&6QWYKP3nkO`B2Aiu5%ZDm ztS1MJ3BxuvA;Q?FoDGMYDHbSJ7e%S!AQ7+-U~8)$O}DcMvTUm8GzslU5TpCW)x8WK zHf^-1uI4VGw~(-#E{th4BnCAzghU&_dJ<kH?^p59eI8+$jSj3|%0bHmMr(PF&nkT+ zSERG4EkYCjURtd|@Y1lc7>HlasgP+TLTLlaH(dE1W_ld5u!g!-g@DAOH0~-#wHH+c z9G}XqbPe5Dp*vQ)I>Jx_KEAeuv}U(1Da!nXfdNc>?|EpL@WF7{`KC-QDOr}TjOs;$ z-|?zpibCnVu~V$I<XnZVZ?GF?P)JzHqG#C4P8tM944u75M)pxUm9j@1(lq8d93%zE zgx^=mb)QSeIO0*RA}EvhlkT{9Cu~F1_lem-i{wQ+hA6YkN9}dFDYaY_hjbf@c3Xa2 z6Q{SxGm8u##K)D0fZiL&mcb<oH;Mhsnq?w{khYcS<%Tt_&V{bv8lJ$~&*OSFI%)0w zxc}e(GqA`1>Fq>GAvBYr^xDZm%2@*K3b8Y0#B5B39U&>8#I9%46xpaezFsB{>o)7R z0HHDxBR1BFs-&|hB9a981Smpd1*R*Gml2rmG0G=%j;zT{5tWoJQLu*UMA4*KeSsgD zZ_?2DJfsJ!F;PZ6i(LLs+0UJ=V>^zTR6N1PTu{aPCvplF{+hTB(rDgP0nk*n-73fc zY??=ki*(oXDGiMxVT>T071kKL<fxhpdt=-(mq>WZ%(WX7PqVbxGXoZnXlqbZ2dZB* zp>=n~3nzQ`(d#2U&mEAnXxKd{VSStirHXlnkW;pVzJX!QR;P>!OQu{MGtt5mCT&xS zA-3(D+6}uVf9Gg+45Emlt)-!{&r+$!l7`DW0wOJb&kk>`LX)So!sjY59BXAn^-JxO zZ~m}FpODT<Nr0M5%hfwHe<HmJAsJdnY`8unki@W>Av1LC&3{vn{cOljB`XhM#&hF= zs1TTjI~!2TPpjNQz!4BqV!LF~<}56BEHMipk`Z5rq>wGL>8!=^z58%~ikyz&7p{eS zFgP@8{n-a5J!whY#Y7C)b$wt2@CQ7NuFtM+{NL)hD)@2totFE<iGmY`-K!>y>b<J* zSd!D`n`H{Zgx5g;Xr@A|t~(TS7Hg-B=8<szW-e3i_$2c5N$JjVj_rI#)@le*O}mH8 z0vYpSbHJ{hwv6GM-Lx-i)*f5@cHiysdjqMoke3;Rkq}Vayj8xEOk<`7sz4Q8$L~*b zd_f%m(WKQx<{8GF^pA4b%|AGgBk2ggd`e4U4dhf8DE`@>@F3SmK|JVKaq}%vZ-x9` zDHA++b~We@jzV|yKX)5tr!G_kt+PVY+cuWS!5*Y3J*_o4QNrI~W$g=$VDx=0@P>2$ zoJ;nZVL4{)DJF?UL}!#MiJs+nP=n4!H#{{5kXgo%Ak@=KH}LoiRQyZgV6@wyM7cHf z2g3NzVFrlrj!j=-!67-fQGb`T`$@xpcKuTq_8C7fcCN4f6Q7tl;~9cqmy3V?%DY=0 z8bf6Xvvp`JAuu>~AvLqR7N?N^uqO9_njaX+|5(kpiWJ>91wy-c_8KMdt0J{JK+hB5 zggo0|8eJaKNX4hws6K_e4P(ivb6F-#z#E$=+WgjMH-fyy$0efiVxX1CX{T^z_8hdn zn75xBGpEPMT;w`HX=9^z%x`j%7K>KU@^bhYMbPRVZ*<<#A@5QLuxifhOGY)Qhv8oV zn=y#NWme2gxYet;l{F$xA7s&z5g^TgV$5cVj7b>iVlrjKVP#ZlGeDTN#G9J(GbVf% zMB^m?kxu@t3ewOpu7gf_B!@BN*RXD^x^kZtLM5F~ns!&)y1vkHG#*)%m$Am+fUy-d zaN=@6WKu*4r`t6O%IgjoVQ^AJ{7B{i8DgU`0QuQTY-w$bcbJU^ANTsx#Xc9^m}1W? z*&X0O_yv7Ybc*X03>ouI3e!|ta6bhPF_%$Pzp6LLO2EP5(0{LLSnH23m!ZTAgLyy) zlW5sq)N(kyO<C>ayRU(WM@6q|7}_8}yPoVRiD9s?7byg+)a+UDjK&xI+zI5$Cwy0I zZ|?^2`%lyS@=QCQPxyy$Y;mmr`Qlmp7E{lg$dXIz70YT*3iFrHxxa_5@V<owq79R- za4k)24k?#&Npv7Yxq_OBSwk_GFXCSRXw2w&PPO<IWQ0=vzAZfS;?{W;_wHx~qx73Q zr-EVXrrdxS#muwzV3mLfkjf&cju-AtiK-5ZH$U2VBzw#Y(!|u>xjh>K^mb2cbU?tb zM7aqvf5W2I<-p1$j8-Xo(wQ!$;t%PupiED@q<Fp#9FAoAt%-d|yEJnv#wKHhJTaDX zdSl)vEwf<Se#fPxcvn$Ak>N&@ZY)`%&F#ZFgTtUCCKc#%nv&P~d*SC|iUlJnMDI^1 zQr|&`S}=6x?obap5A4&TxhAKGzcS-l(1y6%Xh}zyNY8C@m}z(?8G0xnySr@k8uou8 z1EPfqVByWG$Jj)n!(Q8{Lvj|Zv7#4o0`7m%WLLe-`qEw4?>f`jP(y+L7LH`y(x$T) z`|UOw;I`dL*_u?7h1{!(+2Um*J(rRX>rvVAJpdX8d_N&INBkw*kh}kB*}gSQ)1H?v z3Iu!oAMPst91lkO3Z)0>wHY6#s7ekJ80g^6PE;Yt5PO3yoEqUyDe{0J*M-pMAPQ&C zmvZODKvL-#{3tKut&{gX>7%482KeAx`%EEd)8~G3aojf;GdtdHSSlN9x#2#C{q{r# z57`c@Wx$B<t6Z-euF>%Sq3WBz>k1d9W1EegG>whMb{aIcZQEAElbpD*ZQHhOt2yD9 zU*3D~xAtGK_p{cld1hwM7#t}>O_M8gte5rC=$UgB1_;6NRen)wBO+ZBw|;6Mv_=LN zc@tF{Apem^q~waQqDnmDx1ccqu}79{m;(h#1}ev`1I{;pFj7{X4v+pY9deY!zfl)J z9_65kNHb9)YEtjEX$?3UlU!nr8^q^7)A+T-x=)W=Z5Be!ct6@z4wpI$m!}S0;`Fjn z9*mE6xf=^6H^3?f#(0D0`CwCO7AL3caIm=;lr&_1NSeTfz$?8_N4x_~6c$Vm$;mDq z<{9{WmigPnWaMF#9T96s*S?l08Hr!<k#TZDPliAJZ}d?TOcu(z9*s&97<+)sy`d7d z?3w=AndWkg?(FTu!#v6R&i%As-Px|^|Hs}C8mk392dDkt{-O$g9Kn)w?HNForGR~F z#{Ne*6dTSAM}y8wsY+gl)nX^=;Odjsn3yo6$&G_9!-uybM9-lhgPf7Ue&yhoaq%JL zhF=xK-L8;Z0N67M5f)f>KCBSE1;E-T@kA;FhvE`u^?aBtr5EoTk^G@3=HiBI)9MRD z)c^Nb!Ct8H+|QOoI9jo%VLHQI!D}%RODzLej>~Q=M57qpp_ANMDUe(-w-VF}E5Rcs zRu!E)fb6Wzp|Mfh5sTe@cxShTrEcQD^HWw%hz4=<mT#AWfgir7nSH@MmrzrM-xMw1 zL3@pg_keoBBV1>W(~&TV_=})j41LQUbQO#lIFhaNQ_9%*CIeoCSe$(e9tVxVvJTTq z9H#66eX>|*(WHa;1M5sQ&$GOm<-2^DDL~pcMSbOv3`VAXOvZcgFRS{9Sc~P7ZKlGJ zXt=gbEH-6)V^75aMD=r$^>%t4S`n2SOOXR)au0}&tsAuWxb1Vj-Tl6IUthSjvE`0Y z5srFtC$t|(Ol%PoG9o7KKc}t4c$sW`NQExEiCM%GQ}!id5;C4DDGH5MfQdSoFVj#N zC(DlzGq!S=N3uOR@>J<|@9Z0r?~(O|zl<?4p&xVB`DO5-ugiJofnN7u00<x!Od4i0 za`10HMDkogAz}d7VUvd+D)MQb0rK$~E$vP&$bpb!s)nA_scn_uHNN{E@2R0Wty^9S zeelO0aki^Q5;Yw6ypw1KKFe@ln@KHg)%v9@TypFleu^|)jq_hKk5Z&y5a(@f=<*?} zaTeySEz%5o5@3p9i<}7tdCJDs>u7~C>dWb*5E!^vYtvq^QXAzRVBj|(wlRIDLHGDs z9*So3d9-gk52FI0`+dy%5Cz<NEc8DtVZXGrH|oiwzU@7{?d+Cnrk-TmMZN{h#Sv|? zEr9QdP>LDXMBpN`7D=NdiXJ5Fm#nJg%oBe(9KnLG>Lfl7XN$$#evg&c9WM{-BtFlE zaxK$;vWjz%NREKFuG~2;2@{z)r|M)zUI_9&zSQ{BHgdUB(`ga?7<+t&q{KW-vt_lv zm8jg4ezLz;WDvxigqSz4qVsY~X;WvFzXmt2|00<9A-CjQz217UdTD?g48!`;sZFPk zDc4o;<n9h`Yw5~InAv$4aHu@r@-HeyIowvpjVdK^hig$~^7h~=b$fD0pwXGHw~@Ou zEyTV(ZNU75t@n;0w(?kqVYU9qik+g|Cdu6105hROq3AH(zH>cDSC?>*@AAXp&#G6G ziK?05UD<943}d6KRL`R67)?n}^2m!Y15n7XngoO~{=@S@*$HQvyIe7c1Y|1wc&LQ} z+>#^YFmja*6jJ#kznM3E36@awc96<_Rx%z#cmQ~fQX783lFn89JFSt`uB)iy0QuLZ zNXUIfb6D$_RNB$KvDyJO(l-T~LSx0zQ=*5n+e;u<PWQ*z{jz<R$NTe9Im(l}-L>Kb zUa+383@Yjvm&j@N!qWEA>cx|DWfTtzx$+easv*>RtLpKS=r_hZB>sM%Trcx-qTyX_ zCVT@MjQSB4jU&Y&@k#YZ0@qsb-OVe4jvr|brHNm7{2lec{A)O%tJ*P_#Vw80l#F?M zD_Q9Kx*e&y(()l}e8038DfN@+#_9B3+A%_pIv~9+^&Z8Y)QWH1k<fU{jqDiGp8}zh zkt{7X;#D*5dvR-Kb7v2@?}6%*H4kR+FNt-2>eJqij7LNo2xgZvG5l#=-M)}C*$x_r z8dgTXqB4t+3DUkH&Z{;f6ADk5r)sF3Qhf<e=14tH#2@X;flcTIBJ}~sC#mK6-`7%u z&20aM6cvG!r+dAnmqc0#*4n2jJ+`r~r!W|{)J^y>sA%Y&ai}l56Dr<4KY5xQ{+EAt z9X(}3?Vt)2sBa(K@Rs33CeH=Y0h@r5V?x_5&$k*WS3)|_g|dHKsgNv^is99Y2p}>g z<MeS(Z=v_>Y;2l@kei||U|DAK{&2XUCzbIOw2SjPFYgDiMF^lhsQ{+yMx|lyZ6U4a zye+M+b)~>aohB&5?-8jRa9F_!WEQx7LJ69DR+E48i@aQ``?sl&8L-J^h~J)Av+NCR zQ}up$9ChY84~+IR3p9tlFk>J{Ic6hJg+-r{%X04m{<c23b-WvkjY3%}i-td4_=N$o zwAGaVCSd8!oFnt9a0(FXu!x**z%1;)SN(Z?0XBEAG^r|PbeukIb~N;Rcsk!8fWYj- zm7uc?9zQayfZrKAU*3Ek<a6ucB|D7yAF*z8y;{PXM0t|y>oetWpVu1rhlD_zD5xB+ zBlXd1Z}+1P9dFv8^krPDQ4zLd#b5{}#UWBZ1rAQw%db}Z-^l?=r$g9nKvOaHD$%v; zISf%lg<90;NYncDRa2n0#ReI)OQP`lHH`Z46O)IOPtGKnI^k{_g0PnWdrp=IBoRGL zrVSa#KX#PzOlp|ZeQmhcOt-d^Z-V!kaME)l73ytH;R;RLFG)M(tEf7<P|TMO6K*KG zngmp223Zy;dTTwd+@-xOd{C|Ehc;}6MbB@Md&Yu|x#B7_je31Ny-HX^4%J~d-*MH| zrA4&w&$_`CeAh;|c^NXQNBp{dC<>+xL^z_ml;<3t`!-7H*}-1K$cM;i+I9GKp*&B^ z+&4wyF44%Al~dw+WU1tt+<p1FTE~0-qb_%o+bUIGrxPK)oB&_AoQ-J%hC?AdueX@z zhawBvy8E&)v!TK05kq!#Iss%ETGO7C;}ScM$Z~#=Y~qnh=4sMUUpiuc6K1e|Sc!*7 zbhclIiweT3YtsYOWmM$%N!s7pD}0!!6cDNUwg-pZ&}rnQ6XQ3(WrTa~$^{!Dveuh} z1`$~hNR<~jqECfsy?yu-qb}GSW<cm2ot5{zC8jS~ZNSgLgba5J%{N7p@N@T@zrRej zrIdBD4}Oy2Fnz2|`8+<MEcll*99llgUp=2rFRNTCRw&3r0V>X-hla7y`Eu^PrWGK( zoKVxk^`UqEqgrjQzoJ<PfEqm;5f$m|k4?|gR`(j1MSmlEX(*o+q;dYZuR#u$mi}eg z8qrg;u5%%iM%L7NPAz~<`yd`+?kSe;_+kjAR!*{RVYngH!HPNhOFPlee<gmm$jTW7 z7|h;M(FDFE+91uCqOPFj*mZrzzE3pQyZ+f#2u=+Z!J>oNJcm2A5oBCX)yy4$<MX%X zGX2p80tDuNvA%qhxm3Ai3Ey;AmX*u<o7qdoIia~W<Zxk;J)RimUlLDOOQ<cceV&cs zeC-3}0%&5QY73cf$dOQtT|(-^HI=H5yhe*xjVCoI-UUIwQ~ZUWhr2yzKrI@-JeKCZ z^!@cHORw0OuAdUv$~o12<_?T2OUMAzB+R38a*z?g9AGhjZX1QjJSLUN6mi1cewcIq z>fJ8hKb>5x{m<R_>hj!<sUA$9`1#I&Z!|7RgN2z!kv_+;+5<rRJ)d;|FG*HXlaC@H zOO0=NOlFeLqlQUo0`GUo0rMYYryMKpqy&Q4P-6_YDquwDkg({4bjAwCcQ4#ty;fl- zExC;!KZY?d&Z}8b&p^d=H7bSRaJ~wP5a%l$YKAeu0)1U2g;-HmiU4O5`zn8-Dlw_P zBuOi`05C?%zsgFcQhS%~)*eht)3){eZnE@Y^@=|~Vm2$o1F>2D(s-{_v>ttK;WAG{ zXXf>)nW?IcV{7_<R#1ybvOutM{OFNBp7mE$6rqaR6#ZSpi^3BZ>7<@&+{X|A@9G>K zm7D0tkKLk>1(V<2*x+9XC&K4JeXwQXI;<SBUS)vDEwF}g$esAZkSmK)UgnfJeo{ke zHj+RcleNE_pi+N5v`XkSWZnwhCTfNCwx#3m>F0mpe#_ds6zsx3yDgg2toOsU>cl45 zAdw#Yy9D~NPwvfIO1j4_Wy57|y-|FxSftX8_Pz{s%RQw-olFOreuRKP$TKOgTm?4y zUT`q5G0{p)#7E4u9W6o(dF?p%Rr1Y>Ao-Pk_)#nN)XG_*?i2X3dx*4(4dbdFk$;AV z*;?+6yVrx3zGq?|aLg2%j;*}eLtc0}X0F)^vXV|IgzKSZF(_p|d9%g>IhR8QqNn;s zy{O!iqJm|L0fUDn33OhDwP<W;Y5yU6(gb8##5Eo1e|AQCO%uPrP-HmmsG<v(_^ev| zom&>SB#j(t55nXKD$(N3VJgy$Xt|hNa8G8o{4JLgqPV=7>apSN={Pa_KYmP0XH2;N zBdz~_|J!1_gHPuKMPv70cjoDoa2{6;%*h8Q;q$R_TRfiNR6I&e5X+GxgP6w}bVz8$ zx5No|b|&`O-XC|wIGsbuKQ<C)(1^+9d;&r#bi~^a(wF@s9_}dT1mI=1^wjQg#3J)0 z81g0`!#eT_3_<~?-}#EzS$Ya%P4vs7kfcac?n1blA%cdh>X*z++sOXGtnugmUl!oP z=xRFnkJO5j;T*aSNl;Box=IuggPY4KM@_B%s?Dbw<&NJ~8fs0>ZsB)m3#=VYre4mY z6_d5`j|tzfpBt@<$Do49o&nF<bj(6`UPpDm_QGKo7p^#(Lv_B$*Il;vMA8@}b6VNa zyotX0R+3zC^d8J&E7d^y4H>UYfJq^`5#;FYcSZYuME?VE+Y;U_yXi^I$LHhB;&iNK z{yB|F`kg}DfTO5L<Ch?<Rfm7h*+WWcJXUM_B{`a&BxZdsRmmE3^-u<7r^ZT-#5)GT zwHfZAV$izSs{pZ;awy50b9!u6<{k|qopj+2M7QoExM-(Mh}OobCy^E712Kx!er4w? zqR8JdkTcCi?WX8>sopDcwH^DSY#vHe6x3+ONEm}6Cq=?f52lCiWZ;g+E{l1Jc?5bb zckPF8DDaeqU(tZcRq^vcE6Us0izKOGFnVK})vbmz(9a_#KLu+J3-A3AB%7_ba5%Mx z$NmI%O+;Zy)rcsB-dkW-NN9_d;%^MIHvYMnr=erBUH408L6x*N`^13h0w28({=t{u z&}JvJq8KCYYdV2g=)WSa*~7DdPNEBprxj7TTU*EJA3~*nSJIYKncNZo>j_p1dC&Sz z?9X+}`b@F?R7LUbg~)kOy+5W@Yy_F&Zm!|dK4EvsQAN+0gs2-<wfIeaQbf-i=TnHG zrmUrhw6Gc`<(OeEp%ew*|BzoHGdVeeh4K6IHE+0YV~*Mf4%htlRk3Qi{&7cGMFdIb z{;JzUV6P=tzA#)(W_YBnIWB}fqiav(nHsO70?n~8siNz<+{Hk;W0hJ5W>9KwgTC5w zb+4XZxxkWFHzt!{%4$6u<GLI~tt@77qL_+lX)ZrCzM*FuGm45MxDLK4|6wXBc<vbR zRJo79z<Gpcc!-Xd^O!VkQN-TqJNN$h9<j)^^S_1wLPMHnz~+TgH%vJH_&4WZ76#Q< z7cr;ZtG}re>~?+u$x~LS0Ue{e&mBfMiosU{Mqnxt7A(CuFg#s%8SO8^-Nd&yHStCg ziYicY>mhK+98-DN%iOma^QtpQEfB9Pm%u+J-)su0(M#Tte!5SQ$ZY4C*CkO4Iw3Y? zI^hFoX>}?(r{v)(2*Gypq%-<Va`*>T>@2ZtDTO_(Ankg07unYTO*Oy-LM!v(lK)Ht zlT%)@c&%INq$YMFY_-Iz3Mtph1T9;B#3G$X<8ZjggB+$ADy|?cpjBzzdDMtn1ybLL zIhSNIw<xt5-IlF<%!>Afv>)3=e$(IH;{X--Fq`Ojn|qdt88Wr}vs}(~79pd)=C*sz z+Du*GC>@xx2R+oKenkOR`Mt%pIgrRi*Xw57I)1skcs}nqd45Y9_h=C!GNQ)!y1)DD zM@e00bL4|YL>X+c(&!Ap_DzT>Wg?nj>pAAs_oc&Nn(;)-2!75@$900_A*)VcHs|in zO4}v%BKIT5Z(@%Nt<i~tbsZ#~3~`*9$YZIxT4<wf%tX-%9{538cS9H&(OUlezR7b0 z-u&Wnj4vYgkZN%wM{y#XJ&sP@_8m`F=!UAF8$iNLw?RNdF#+-ZTr`n4?59F~g9^-R z%h4?RWytHI0$05OdV{2&RPc*w9QNJ%X~B%nFD$r~GMT`r0FHmyAWzo)ys7|;zAH_; zi7`u+T7+dtT8zVWeR+_9iV=v;(^L3sQ;Dbh9H~i!83d_!+(e5Dyl3MooXRVi%K-zN z%SW0A&ek<lhJOG#LnDdB%}0tzbZikwigG10>T@ooja^$BER*FOZAv#q)S?cH;AZFj zs+rmxD<ak0fpa~6M-fyH$;UzyPI51DeWcqQ&)lGl+dp-@wBwx$KqKen-^Fja*cYKq zyR0Dxq&x-#o*mfc#PR#war>vYU(e~S?+{w29N5<SDR~x_=pQ`XUCu#1h*J47mlY;( zTs2~|2GH~U6K^zfrL+!z9DqX}EhH)Q8wvyl)3ip2=8<QlIDB!!80~i5S66MRF2Aqm zN+jzUmpLrPQ{MK>F6NB?J@*I06*@6Hj3K_C*}XB2m>SljX6Q6g>ukPQ^DH^%J|F6& zMvAFwS<ZxT#zQJ~;Z<AxuBlxg>JI8py^IDx>sx?I1=pR8ERLz0@*sk&B6Os<RDJN# zL;fb~+F6exIvIgT?z8lT3gP|*!tO&(buj~^)H{KzH|H^0e^2X#4bL)cmGmRpx_xA~ ztOqo%$l#5n)G9Tjj8u@@4USPgS}kGtzdPlGJBZjyl+16$2?sp;QQ0)PtyXXvAN8Pb z90gR*1ODM>mdWSZIdUwjiMnPHh1umWE_1-W^JV;cLaMnPvHhD4G63jryuPl02dU=> zAEUA}r`pQrVF!;2qQ~<)EYp)Tg2A}PTLG+GgCcptmBQ0lJCPXbOMXlRqmbE4$!3&! z!HCCzY@2X^zU(S0pUAho@RkOh@i#NZH?rVnom#jYNUxn0+(eiV(|-BZh8#FB@umc) z+Z?+ngaahRe_TE)aZA|i?MOZj;C&cgTsAU2t;GxK`SiC;U4CSEI4JI5P04nWK(Ztx z;}%#QLhN?Z&lr1|bdyyqP1~`mR);~iv)fMA2eaxyU)cDkJ&^Qj=1ZHS<ax0hoz{X$ z7q@{*iygu`rze`R)|3Ti3%FObJgv26cJg6pD%YV$KwUx0Q<8joj>htLS^O=@j@ts# zKk$n4u`u}UjY;J4T2bw0&C8}LQ`!@$u|9z~1dZ_H!O~)UL*LR6eQ&_g`S}I>Kp<<= zJiQG)YOw1Jn~y2|>!$aR{n`OeWN;<L`h9`qS>80dC5jxIyVFe2uPEe_gV3Y_bhkQc z={u9(!r|g+@;v2S$rY>Z(4UQ3S67cF*5Wv`-Z+PkgA`%vYz6{p0%vqJ*6Y|BA%|9< z$+wE|@eFtC1$cK~ijl%Yv>!t|YYD|$k*~jFjd>O9E82;#`_)y>0lZ@<xB%d|_MNu# zVcdF0G7-gpBP9<K5?pGwh6&-NjuJvXuC$_*D8NO2NWQ;FuuUzIKr0DHe{CW@j8nLV ziTDCEMU*tDuX3a(=RrKJa&PbXf`>WV^k*Pv@s5C2;K<kJ<S-bu>vlFg4bjvt@{C0- z7OKLivRq_|a}HaEUur5EtIFczRLfSK*e%tC2ISp*nO?@pJ7E=T+Y_Bdq!V`)b2PUQ zhSbKYr#7IuJZhae*vMV1?KWI!J(|3H+}-Nd@0W<%mkr}Px<tZ)+_cVa*Of)otEu>1 z|4%k+Pu*@<a^z(irf(%D6|;Fat<~Riz_lHJ=6MNG!IrRZZRSf_?aN{##$n4JCFP-4 zEtfJ_#B{vOV4+%Ok`G2{SZF3L@dZhtnERij#-!zT<I<ACgS*|^SgWKyHZs#^{Xjcm zZ5rc7T<kv2GUP@RW+LTReWhR*PJ%u*ay|X%q+Z=-#t&C;IZhhreNtPoQKqMKxoKRj z@<1apa!-{FsGr^ZW(CxM0-x%8^piEZ%WnI0*=3C_@Yx-x(77Uw!4(RmpkK4lXVOI| zOsJ^U0-%RUTz$SS-}$DU)yqSO8kvGIk+pOexI!HjLgmj`IT5vi+A;1c<;?eLp6*1y zgpk!COl=3czv8ocQ8s@Q5b#Vz;u;y43}saY!s~ZQ^<fZ7bv<4bSV%LfB{!=zI~$5p zey{B09B`44_D}hn?iz;?#&d@o@r2CrzA00yHput@Nh{s~R!z1dn31}OSR}ZNe`C~H zzWL5UQpg-Ze59|=9Q6y+?un>OXFzL3#r%dkj$H5(Wjuii+|*oQ#okNx>WJU`+v|gG zm%)tZCANsiZy9CG8N1Z4hUnndvM<K4jm)Y9yVyv^Dx@0x(VUO5znEdJAm#(uhGn7; zkOeK%nCI6#yZzK_Rd(JC8t%b5@U)ti&)a&PeyoQ-G39fulW)&S!6*o<IuCN25)g}4 zb)FO7n@34QA`Ogz<^PwY*?fwiGX@c~0_Aw_>>d7e)63O$d-gX@it6ep%<x4yiaCLi z-Ki`5Mc9p`bZ@8LOD;%sTJfszkayn2(o`~v!>H(QdX=JrBEw5fDB=h+I$Fa;(}M@Z zanjOEWheXQNKg#JK)f`F?Wf-BE(c){yW1Wvx#A~3sxw3g=5puncvBU(2wP2ff-E7b zaT#_QsG2tf7>9PzM>gQrW+1q7xZ3>)`-Frbm-6p8irN{cuxj<TSUPVCayu?lw#oB( z4VFhYX)~D_Y6`UyU;eIr^P8Vs9zSy`4&OFoU5wsfg<n>WV`73frk>2#&7hJ2ktlGd zKhvE*2tnQ^DrtU-;kV<9T4E!7h;j=<#vW?oAt5LdxR8=g9B}bI#`_O*&Bifb-VmTG zcbJPQB~YIcj4iSRGZ;%gSP(q5$+>u7{!d8F5!!LNhOdNp2(x&_eFa-m4E4`H2c_2d z7VmlkMD+4*cjaJiMnLh5jLulOkl({-=a`I?Ba+x(Z3(Ze!prCq@!_}I@GvedCUs3^ zQP<Lh6YoWoU)|<Ew~)gLL(4a6tGVz)w5hkC%^Oa9>{3GnC$VgW&v2Yg-8BNLCc4H5 z#tx?*@B}D!4mz71HjDSUaSl~iZ88SfH%N4V(79N|T28R8Bb<>gd7VreQl{4q2;OUG zyc}uE%SgF#b)J15G>Tc-JiY9}RI-kk-?+sJ-<9<aj7TwGsT`GPP`K9Z+8o-!){rq} zHeSj|-V(LPst4)!#k_MS+e|ZNM{s|E`W{uO&fVN9!X?e5Ns%0gsDT~*y9UHx{=<*T zL8Jfzf1uqt>9ZNt?m+uT0p9mMe^%P(^yAP2mU5)wg4hw06s!Pm*}Q;pkb~y<54u-n zw>z>P2L=qp(<RyI<*Me3xfsjwNcYaRd>gYpxSbFS_<YRSk(pIgsM2WT9Z!q-O$(lr zvmzJoxEu$)2^uH75scoWXquBvTj4FTs4rY8S@Ap1Re>87)@a#x;-%Vhm4)Ke*7ln! z0GOXQgqPRB5F2T>?+)Yw?V5oYmnJGFaFZU;VGV5;o+@+LnH~d4@~w5t=r`RP`2YI& zd1#~MM-LFUFqUx|QFP<U+D$@yRd)1o8d@F$M(XWaUopJPfkx^0MNBdGZ>H(yK%<4r zlM&DsmuW5G84#jDggs4kLjJI^_SD5Omi3-X!0YkhN$EhmYlaCY02jl5c8NE1hrI4A zTYcPs_57%7c_RWACnUQ3J+X<L-Hnrlu>uACdt0eSD<MgZ3RclvX0#3dJIMrQX@9D< zVDVsfO{$%!F*12rhhQA?V7Ug|95qX|agDm@Z-}g*So;LXoMS{?Nt%Zv-GA4ae`1Zm z*I5FQr$g`-mi7gwvDA?P`qsulx$|Zn?rCA~CK*W-XA8oxt$)7hK<jB%)gK~eMb!a^ zpn++dURAM+=a>6G&hVF7Z`9D>g@Jo4godWc8kL78icPIKcJ?hXxNeO~I33GJ%$1C+ zVF9OhBM6lnlXd5jMa@LAsPrA0Rvh7JyITXJ*GHf^CUoEDGvEYn3mQ3G{jfUbW6Q6% zTRtlk=>YTmJ|TK{kmy9Ur;*wwuj0_nl1m5^h|W$AQ5fy+Q5f-G7~P{bMmnD!I<zH| zQFFGC^(y0ynx?7yBYp5o8s><Awu5V2HgboPs|x34Vy4}g=hj^kF8l%7L8e@6-v=fF zF~Grk^Ri=R(FU;LYtFS9zS_>)Th)~M*h*XP+CXoe{(H`+(|feo2-hnh4NlMI7+B|w z%DA5zl?~l4R67A%%4*G(W7^!bYz}nlO1)1K0r92EpVB}>x+roEYC{J_Xbjx7CstpI z+;CrT7Vbz#UU(eob>A0d@@SGy>SUjHnM#G)#UwS?rgz_-Evn~qcin<ay=%ef=_L4S zJ<Kvyu9iC)3da;P!p)T9IbMHhBw<?<t91>Yi<37|s@2~ij|{cTgWWst1ZdjZYIa$` z0FwoJ3wV}2V0eWC4cu+a;s~T+`E*ixSZrA_sSsxQzL_L4%To3hVTr+54;c+oqe^)# zdl4sryw%bFbzEZZM0!Uh|EX^#d@Tw#>BD+*U*rkbtcu_dcLCjrUHFHy)?Ab7$~Af4 zkd|l48JsVD1F;{XQ6#DayIUkFK7CL|(m%GBiQO!yGFh(^DA=U@`lE$|ZTiH@S~Y4U zzocBVE5~<r0GFc?1sEOrUJ98L!d#*|MoBco1Xe_>upo5gKmy>js9U=-in@IlVzTNj zTe+g90>zO-C#$P`-;kyV_(<OD&znsaePHaFwc3VgSm@$XfcPV-GCUqR(PXjj)XL}6 z&v%}}gC>7Eir6KeThL=fsz?`_Za@CY?;4drxCmBwnlUj~k_zixB!X))%hON$5(Oku z^8v0arZzG81%2y?3m7>LTp&u1MT27lPcb)#_A_LFjQ5a5Ei0BUN@)m7_e;I`^YZ4! zkZdk1rg+l<e-B{B!^;`eLhu=IGwG(ib@Z%vC2qU(gF%x@3zaT@To$%UWbIdfm;u)4 zIi%6|OuM@SgZ!DW_XL{X#7Y`{7(PbjwE<#d82#gD<Rdm6Hqc^hLS8-KJ|9H`w~nud zc(b1m@`eFh%4se(lgiPd&vso7Dhh0*l$yBRBpF3p=GbYgGodwfkEwtiB9xxrX1pQU zMt{}AMpd4%NFRiKo8<mveSlr`IkP8sWeKA`<G8wd)^%3Fb!&}`7LAy3vH8|FAbin$ z)rem#?sS;Go*rM<_uB`T{rk?&cuI|uLj7qzaihqYZ$4lICmMhAJmiw0j_{3vOsVAO zR?R2G^qvT(hojxmW`?Nt=9}EVAp#FJsCHWS6JKLZ-4(c>Ht`SwgYwjPEMaJ^pc3Sj zP!Z~-JOEU`*4-ks!yT=xh_J)T6sQHX%WUMBYAakWtYjGS$oL*4GDwu1eE(Q<>=HTq zog*EJkW)QvzsaKG_p75^n=tZ?iu_jne)+bH+Z7~Yz(gBkZe!XOcXF&nv77>51k{2L zM@F1U`o}NTJ)SzX@JiJ0xGiIgc{PaMq{9!LP3IRlhtJMJB6fvY-Or8o)54eN7vF6! zf8-$bZ<bTq>nRg%kw|DBK_XK-=vD6Ei!7~ngowxk?d_L`e}4bm{m+~IlG3|A-@Bjd z1wYxyUf#FgJGWmdw<(KAd_I{zE~Y;(>T}+GMi(s1d7j7P&``78(=CbK&(cgho9dlR zP4}JtXyS$dLMcr|vR9GvyL-ewaaXc5M<vErgpdhVJ)v>K6AZ;^zn8<vN-RwTXYl?} zJ-_>kAMyIvPt2a>eMgcWKL+Hp2=#ek&)t-eN;_*f*@zzJDEmzKBLZE&QMYYOC4fI_ z1T3FQ3Ts!I?--%p<%*XGNfReIF`$A=?c9QWpkAAG6W9(otP7B$C%d0JaWqfWvLb)E z?T^w-Ya9(LSXc`@yymO6GC-iUPc}FG*NCEli>ri7r%k)5b1+v#tz-pscqGe;0H*Nn zOtOa+&eIq<3eIeOdE7svfWu@v_o(lRcvIu@rxv53!=*swcs*yTfcLuds~OE=4J4m& zG`S63(?;6B1a8n~5$V`T7bP_f@zu+E;xQ5mbvk<w=vRNyfOKB)$zF3(QC(v`py{;a z<D?fobji^l>5w4RPFQ>!>R%A;aV@uFkAv0eCD3W0<TP`uh8D?!_G%&qWW)=tZB~Oj zxd4q$i>zLJ)u@+c6gwQMM+%nn8lq$QHaq-EBFd<1VILE@EYGPqo(-W?YfAP*GhwNW z@?MuS8#8;FCCSo`3Q$KQ#JUC;+#Fg`WtlLaFd)lR?t*o(Qa8f-iu)Q@hY}E%rAvXi zBmde7u+?+Wa75No$?c21p^vV`gri7`OX~d*vHM$3ApDyE+et0>H;L<<<5crJyf`ax z%HLuoWKAg>eTi!IEtQYW8N0mlk%lBVNeuSbd`}~YInL3PjN0|g#8jR;)@YjsKf-Dq zHPY2FZiz#0SR>7m`=p?Pwwis9JutNsDPH{_O5)D@reE#An=voJ?~Oh;QVfLK-tj!} zBYPN1Y6RN(qZjJ&b?_67uAi^pUbaCbAFrQR#W}uD#r`kV-TykT{a@F&KZgCE!#{W2 z{a$GV-%oQsPCq|7uYEs%ZiAi#Kl%mVdQm_2qM5o{I3J-H9irs17Dwr=<c{2(__AI6 zK|6*>CJ<rR?!b+(MJW?eMo#O3G2QGxWS-%yEVtsQe^`R39qQ1fa;PYw7dN>za@>p~ z*!aV18O=VT-Z77Y8@r^xrvxG*eE>9VuY(7wdPnbB74zIvul6;cm%UYXQ&q@v`aD4J z7Czafwz@EoxSRmySJvn^QCl+B@)%as?E2-qkxUYa^16M?C)twXfr{(`E)IhwaBFr$ z)|gZZ-i2G#eKkD3BO8H?I(}HRDU?cWHb$iA20W9&LSvK=Ds5rt1F3{(X4GwH>1;zF zgqQJm3f6I9@^}G*QBhRc+z_GW@Ifr3_nfl}^TzCGb7X^TCmSh!d;y%az<TirT^RnR zy%--2`Y^g+AG4Y#jZ-+2Tw(T$WQYhthDVE<((oFA%bN>8YW$gv3M=dRU7-9gz)i#Q zcZs-;Ckl%`BNav*x2qEqVE$)+=M!<v!>!A1#$UGCm56~>Ojx9}is<mjUgm^tZy3F} zSOW$~-dZ{Zne}8!NMktZ3i1A|g=K!v6G~+r&d{W%`Cqqal9s-vCbdm=QN6ZPG<M9~ zw1*4U&D8!NbVyw!Z^!+OprdJs*nk8|tx&+o)MMT&!3;s)Xty-!czFb2yt(?Br#Fda zE__edvH@>869feTa!tGiS7ElYMn3b5Q-U~o)|AR1n;G`RqkwMoQF$=StP6Qv%{!-r zx}4RO`2u4;5Avh`6I&jD!^5mATZ6@<RzaS0gxxdL5Fbo<(;Yo4aMhh#lR@tvw)_SV zr9uUVR(gp;+4(zWO68TNeQt9LmciE0dxkDp2&!J6+t(Y=Sn?u|7umpURcRn$8~QkH zeCJ#Kd3ObG`lTehA1}Rz1g6rsAo3=E4Ox3^_}uu*0To(ovlUCG-a9!g{j1|^>=$^B zOk(%)m-|@RhOj3@mu<RJ1LZ(dJtBgcyWCEbEFUmjVCvtu=t;*shclZ5&{Y+rd`+#0 z1s#45T))#dgRE%Y!J{Q$LmHrUi5Wj11wqvxlilxvpUr|F#q;yKO#Tmlo8#@p58Aii zaqsg;K29W^M*Ls5-;zFW{a<oO+?!7$O|lsY5{(B@x0i+r0n%jHj`F$`muRFJ$GgGi z!$8sjOEx#Er&$wv_zH({#|Yj>2Itf!ZpG-ty2xjaGbaU@!>ft{i<^d7IcD&8=rp`# z^`HQQThzQkM+aOnTztH!6RZp+NfUsMKm-jOxOey+x|_B%AW%X^FaldnYo@2gc@YS3 zX97-i12TSf=}_^Bw4i7Z91EJhWA>)YM--@HEg4O868!k<^S$|FtVrr==~2=$waOCO z>pHG<>R0kW&a=CjBSzVDh7h4|VoH|@9Wqsi24dlOw*#3#qBAdtD=tAPDsSgTvfH%N z8dlu7p8Pr?+98k=I=8~(Dm%lq8odVb@#mi!mOkhUx-c?t=DhWiW!(Vz+O&rbDN4i} zLxjM|3t&>?VV+dpLYAd?eytv2j52q<Q%a6Kf`hMZ)aior>Cz~s3fWSY{tmKRZE*8} zeAx38duIyWCl-*2iFL0loPI_P6$jh+3Y~gHXC0%^*3u`b$|X|&(oT+<krZBL^pUcV z&RRK(SyRXpwi%06C;uZiX=+E}p3m;cbz=4>H(~eC0u#0PK<UA$7T<en@sbuZ*DKU) zFS~)7%_?0vRuWIbgY~nix$rQ5<fQA8y;-_zuvl9~NRY<c2Dwu8-Baj}=_x}O{3?JA zg1F$0QTytSKASX&&Q|ni{MEL@$8*&rj{77Er#)Mo%OTHg%XU)2G$98yP8Kl&94)IH zJ-y3EX?mg$3EKM<gN4we=J4+Asd!VH?XnHafE$F0JI8#Lt$0p|J}ZXgL{aaD|9yr4 z!e9GZ1Ra2%RN~D<Q%~nPO<4{8^fxY+00OklHTKtF&BK4rdX&u9<iE0~igWz#Mu)fG zj{WawP6(c-KM&e#Wy$3pXtv+41fR3EKOW{4{qB-->?E1WoBXMAhsnc*+IoRW+tvj8 z;L`ZX$H3qg9_Ut2L>Oa1xWW5-sb)e~m?{=$At762d~xbj_P;LyP?rEJ(&^$sM^}s$ zn0ff6Qbac6stT+zmO_+e#+HTVJNp&Jr6SyIjSp;|AW|rDd`w#0@rB-|a<gyf2duXU z<gv+aW&<8nDriD$8eDh(1`8T<T?<vORi`Bg8a8AZV`^K?+lzS*<%O^2aZXsmPcunw z_LKrUa$#qjU4Ixor_o0=i1FmpTdBynfw|{1o-Tb~Qov+u)GGst{j!mPihYficW*Ed zMIakQUu}9dQh2PPH42Kt0=GHR?sG9kA=I-$kel@&PFcK<?z~itG8yNzlVSa(Smw}Q zgjRVopdhn(PSkor^Agrb+K5w}06SYaxuilS^qbgG@P_7o@LS>#E5hiJ4I$J(I&ZD+ zc+jj7gF0>^I(_!!)^~-jm!cXP;cvD+q9ZO~Joeuu0Drd}x@nQ>Ihd%^p*775;`YEK zCSB5;0EfxkL!KfnbeH@CV9uip=_^oRV=w}t_RilBVPCyP<g5L|yAKUax_9bvps#qW zRz`bnbVx9>wFH|cbc~uU6o{t`r>WpG(>%yn?g)#VwsY#_f3pa|FR0+=^2FUKnMsY6 z&$YdZtpC!suDZzd-W~+8?5k^L3ZjpzljIk$Y5ykHi_oPCS?N{T^3kNjI3Z8PCH#VU zXTmdo@Fc?j%L06ZWnV`l9S$58>eBRLAj^G{Tx#=_4!S15&q485!K@e9b?-VSur4Fq z6WE;t<QUk)nq1~&1nnE-_pM*flS;n^PbF&R<S)wz9EW!IYkHrm3Anf4B*xqGIqo2v z!^`whgky3gp!qs@KJS$?k>q6SXj3}64u6Y}kN?WuADY@Mj`}>Y*dDgOI81YrKCm<P z54cgPOYf^=sGkWw&B%)#m;&KNB6)=V?CnC&{v0<ZE4ai;0c^P)z^?E^#Hz>H@m%%) z`FX&<H`X|qYN7?#>GWF78R{thK8OK|Ar122W8A#rG@XPHY5oo=N^>#Wls4&8;q3NG zd2A<ny3~a8y!N9l^A~fB(PjKCaZIzV41IxEpwrdleR`{TJR;;U0$e$EZM!J_a<nx% zcOLh8o&=HM0}sSXn{x#lJ!HX&fa07nE1XzGpAi#Ko8Eo{E7@2HW6M5j2fZIQm1a<% z9l>qCC`8GznKq(ieANoS9-v&)kP4~a`ZtjP?k|B?^O02IoLUxrf!5Bt2wMAwF7)K@ zL%r`#UB>EMWO-EwXGJ~Q$26g5B62W81mn(Y;18TO6W*obFT_v=u~;cK#^mow&W@mY za?;Y;(u_+1lrr!Awpatj-?bHfSa0-)=9Ta<MFvwI@g_9gKD^>j^CtOr2Cc%98e?2+ z!RtuH_;T|F?3!Wy(<UBzEBb%bCNd4iHs*$hDw*75+0nsZu7fj?#&Ip1CJyd=U<#mT z?(X-fxJ$Ek{Q8GgKs*ysHi<QLNYn~iOHOI)v9VWY(c+1h$BhVmQAwBABUVR51+U5+ zCYE;z3%2ArgeJlq%mW;tCmyJh^~WkL8qIpRO>)HobLGRU6q6Fgyn3NMJlLMPM^Z5P z67K=xR;7RwyJMll`s}=}`hYVY#Nads{I>M0>c+Hk!m4X)5)2M=A!OWt#1dtDk&lzv z;xn6m(v<dFU7+X1;WS4c6lWc*oBY~OJ;t>7FWv6x_R>gP=qq+`uFqG$N5VYl9$*<$ z5WyJ}h-L}KXoBkhLqml<J^`wh7l|(1mIcR4pW)H2`22j4&>{CQw&O}I+1BL`g>jpQ zjjZN}&qv*f0KCCZvfT~XYAWke>s29Yr8H#BZjBLP+E0hm+P}SVcUh$SR%ErOBD(to z_6*bSUuQ#3ww!Bj*W>dtaS0?xSEU(Tr?v1lO>~i*aJOm5A84aZKRPDdv^08WbX^GQ zkUwv{LCE|$p<^p!LB)C2-9U?JMs)Y{54?9Rfua~yu*2R;=bk^k`@FzOmOfT!r>BI) zM)l#00-+~=tkytLR<d|=3vCZiHSV`Ea>9rtL5Qd<UdFZOsvG34N5ph`yVx!SV7#^Y znD%QUoE4`z`*uv8%Qe&Wv7C%>mwR^;a4mXbSd4VWiEN-1oJp%n;A=;gX;b{S+{|8i zey9~z6y^#Ud1^m}R?-`xzcAH`jgImyv8PFxRJk>J<gQiGxC{;tq?zBi(KTwJhg9N& z0b({{DMj`On{ZhkImU5H4=q$Z`+Y=^Vuewj`NSFPB2uwxcB1Jqvu@GyF&ezq9De!Q zw#<XW8p*aEr|XbhH?FEGkEvqHp3o#h`Jx<;ua}<l(TUC>Q;<p~ehJG81%OXF`Nt2w z-PotAS>H2M_LT=QsmtxZp17R9n8Qu9k|``}Ca(*m(V8Aab^Z)618<H0)eARTVURlU zwnc3PI}c+n$#{-Y0?c)8ZPyZ;Fk?f$f+>D0Ikn*)z$?E_)<*N_u1ZW-N|x<yUV?tl z!WLuhzMrS{F1;_G%hiJZ?=O#nZ{gh}zLbeY6rUg0pIhh4U+of1R!YJ=ol8d)Ve?ic zNU1O$`Oc%p@Y!%}nAG?ckq$Cqp4%Xk3g7_`SqJE7b#k5u;IgQd>8%sF={|fFrF@`< z#O{IJh#}mbY9k<$odoyxHY3dT0krE~_>1n|M3G*-S(o}OJ*ODCzDk5+`Ezd*$1%Sf zfQtd%ys7CsN`16?wlj{v#eEfNo9~7wmki3!sfPB}A`I?=CODb=+BSm<sk8^L#wEAR zl}?F0Ph$Q9_j4$<EWMZ82qpVM4bE;?ufv|^d*Y$4D3#u7vfG?ag+knIgBJ@pa+$N# z<t(@H{<jB*3cIN;CKI_-ur}!GPVQ0|qV5}aZ=&-x9((6!tJM)~>~!<Wc!;XW)~a#2 z<AqVnLd(-l-DVwTwnD%{>+sV{**&xDYsxtkn<E;$s?EKj(UIXoM^-KZR1X#JCf0ua zd}AH&9k~->ICe)bffIZu-$>M}SMw7qcuPIt+%kHTJKGixIz5XOo@qachcvgaI5;;U z;N?I?u%b3^&m|5ASK#h2rIgBGf4T^1K$Z4{@Ifc<R1SVx&N;7iA;u>BU@t~&(AOYd zb?+Vb4h|#87c-yhct0kbO{9YE`cX$>=IC~V3&Yt2y{fYHHjC$OrZPvYOKQ8YA(LwO zG466L=zL{eKnEnTF+kQ{&rNyseEE!Tu1~V%@Mm1#E^Be|ICF-Y6V|Np%^T$KYU+8$ zi&@h)%V|42m1a10m?QrFuXx5oF?O9~g*V>*+vYlDcw^Mp|FQxC@3(^Q=KeSFAG2TN z52CZkP5^WO{5&Li>m_-gB@wJd__2{&Xut)?4tQ=7HAM3A@=8EL$2pwJ8>d|_K*}*S z3g&R7@jH*a{h79pEx7@3kXpzWV?#8v9o(WiR%5WWnSV>DA*6RMrG-9CNRR!U6la!= zuRw?(-j|?_{Wri2MLQ@ob7JYMS@xD7*}3^eWM>fD$B0ZekL8LE;6p5>=AB1jXGWmC z1Y;7FIqEAA6B^{be;M6C8EgZxoOMUR5J=)N&(52f@N8eexaJCNbpfurWPa<wnO5bI zFSwB1M%N#)W9YoY{D{zWo0p+R%kHKX_+AkYFs+ICMbM6a{v^Mf-tn(yVTPq8%H>=> z-9Gz*qo3AVF!XIV@oDB0@1BdtO9Sx-t=r7c;m+O$QRcSGf(6{-56-1v(5^}o&pI@O z)kK|cv_A4Hs0JyOT<UI|%d`vbEZ*nfQp?i(6Uxh$vbm;H4#`gwuK-mr?q1`!QZLF> zH%$Bu3?HxoQNhfVEPn)NIf<r)dCV2TB)>@7aqC0>XzNk4{jde~Oi!DKH`Rnp8GBuy zTr)AH4-Ss@2UY@Ilkv0vC@w}hMh_YRQkQBB{79nBV4SILL<%WM&i&P*58(7lU*BxW z>uGCv>c?rvv|d{J>G;Egt(OE!SbBRtHL39j;me^$+L~LZC>2{W<f_Pthw?A!dZ%G) zt>)?RXO>*m^0eu(z55;1V_te%{bZ@fQYQG?M;?=(U>nfqocmi2T=74taeSfNDSbSQ zTe9s{wygXdMs_*Hc{wk@KQ_o%rMR$Kl~&6_Bj>j_Np#2Ib$8~%u=EX=pa>dfJy_)n zrq&+HMfJM|b>XCqhE0;l2o7JpmYLcT^RzFwE^dc1wZElrmK{qB${!)5dQcBi2|b2( zo~{ImLg%b2+Uts}D&Bs#P4ot<Jwn3usmKaJ|0E}o>Up5?zw4j=@XmSPQ}n-G|GZo8 z9~i7S`nTnMZU0%>{kVDU_b=!3>2tN8TkgC_rH~l&K95?1*YdAV13%0ulkXirWF0BI zx`cN|KkKRJQAc=^i_3*5^y2nG_DUqK*7RyWrn1~sO&iWIbXU=SDGxeDr?ifGpF#C- zk;}tMZAc7w2=3U~nRGoF9<|mTxHrfmRZR;^R)?kMAqcg0Pf0m#_?kvM^(^kBDl2^N zLCi2Q+e8G~GLkuqpe(RZCkA_buWalrnZ+F*?%fE-EdK@_#bRR@2Rzb7Gf0&z5caR! z9*qc*R?S$0$hw*p?9j>)$5O*tthZ_CI+E1Ugonhrh)#o+%!<f_9wa;-E3q_oL=bu| zm0dppE>cs`V_e2iy4k-nBEFPoM@bRs8d~wPZL+Cks!@rA1C51KkNNa`Iubwz8<EoS z3?G=KrX?uwwj$!LrNux)CFABSX^oraR9fqoy9aGo!6W6_<803R>fP$%BQNChus}*$ zt@M{4x);XPobaIV_Pqio^3$m@X~CS0#Fn3qB&_n69#!8#`si<U<IVa^uX=SI1_2p8 zO+u?d04?@zSLHT0CB)VInekcuJShz#34OL!KN}FKM>9DO;X79Cy#Cn&e2t`*ZQZ^5 zduWw04~^tPU7%TOJ!F<dlVr`_5w6+`Ab_TKYd*+4m3i2%JDvEd)xf%Xc!<ei|3|d; z9e(mjB`UOJx%)+Xe<H2p>Z4xZ1NUDNz6Q`xirGNltHHCsE$przI(zbq*|u8k6;aH; z6Q+`%QhCW*=g1ytC9nE|EgZgdgd*3~Mldn`uue!F6aCO_jA0v`{ENj<!Sja6b;p7) zf3JNG&AZ-GazN?ZpYQhF-v6c+BK~drf8u`jG7%2n3VtYdcOZO@c|E17`tcvv{B{cS zy6@l$5aihwhgOys(XPuEV<w8A9hZt$4_OokO(kmOPSF6RNGj8lh;jd_XwbF8;7&dF zCl}j!-KyxYyoc7d!YWh}<q^)q9*6&^3u-b4$EqQS<<_v&Og5iL1L@?}4{~1@N2<@> z1bNba7huDv!$F_!HSnSFMQKuF<LrT_`TYZ1p}Z!S8$KXppvsJI12rJgoGlC8msuN} zc*TN!yG96YZWfFOH4Z`kn<9hOd5uN6>!_+5;u`w!Ev2ylZ3qMD2=+=|Z{m*+LlI?C z8NhNPugsohW=gDXJ_LNz5+B)yUQLiTeCjO(xiEs4(y^k$oo@a?xdONev-JUUo&}kW zxGbN%)^akddv34p;fNs^8zn2X5NFN84bzm`wAg~Pf};%~tr5bv_D?$$csj(4Wv9?} zRp=X~{GRZ=fSuaW1FA-OIE%hF2Z5JF2FIoTt8+T>W2PxEzfYARUN)@UzwDyqOaV%m z1<I)<+8mG%*aSLTEVjV~gL*V-QBrce5q^oN&vmT23P*J^0M9|61NH@W#%8M?m*ek6 zBK>`8p`JR!ExV6Onvamt^4nio(O;q>EyDs}x}v#5cM+3zqd(tqe&J@bd2DR&^1YVd z=A@=Q4`_&^UCb(fvmy+%gY$VGgnvevGXq0GGVwPr<_Smj<d$<c-o4omOt?X;iZ9>v zB_Zt@6Y=hCem5TST=^I4WVWS&t!K5??RPk+j{0liddmzBaY6ncc8T_G2OXVA>R`gh z!Vm}q+Fb7bh@JM|z5g8be_Oovy?*t7>4k;8SNs@IeCuO++lcpj`1|=m^1i?H(m2h9 zmMU2(u#0+y*OPh=$&fDU`~inw^SJYYyI3KCLs)P2i9zxPbuRq?0yy#6@1KUr)sv@L zvSn0q5sVB0?OA{v+3SZ|J{SFrd%+Va2W>bjvLBaZqMP=qp6abTH$632Cw0Ee{I@PR zxuKc~qDuHXQ&p|$Dl?L6j~4P72pUM)5{BaW0kqbP(HkRq=0wmBXP+|`cu$wJk7{ui zoQFeL=bA}6Y!DE0iBqP_N^Tp>?Dk<}0hb1TBB=rZ&3<1z8qd-Oo}i&_mR1Q#4V}eZ z$F-$W@5!WIGhgQL;@Mg|6UBL9Il(%-UI~#EFY6BUh<w?mRo!0siA+{f8u!|1+{aAs z_>y(Uqd=i#7diC`Nwl5?==fPNn~1(%&S(;|MCpygKP_~i#G6uU0nN3RXBoQ+j6kT{ zLHY}Gi$EwlJR}l4KSH#SLokd2j4GIj{Mpw!tI=>`l6R~vu6zRRuvzL3X*MnAqrUKc z6Ul7pYY1164NcbJ=}7X+{nYN=*e!=17}zNoE?C6gBl#OX<g@GV+(AeFef+(;zy)`C z&j%DB?Hpm8m8A@88ZeN<hP?zlh8)(=o;w+I$V#Q<ON{bHI}K<ETC4D5eLxCy+0=*( zOAF5g1R^^xO*dm%+5VVy9*#IMSt@0Dn(}r~>;)Fx{rYa(@A!+B3@sRZsKM94rzpLF z(UaxrrwTzuHq_{i+GXYT$-O1XATZ1@i~pp;?MHOuPEn2&AZl!AwUZ@EbLBmfSoRRN zH!k){PFrz!b6i}vKb<$^qd$FFP?tmtJlHI2qbTZc;OcLGv!+)14giY1k2Kj#Kkg5v z%gGn1VzCSNx6;GlAXu?MXG?|?i9}$q7eFg&@Q0pp(D@VwF`G4!CB*i{xwPrq_0-nN z;8mG0nq~*{=Yj}Q(Dad9h}8Gq<fqwyaM^e~yvC{Sr$+y~Lnhzb{|9P7mA}9JZ+`Ln zKls7Z)6?fZ_ql)eE5GuMZ+ufyg2MuYEdFC6G6_~32}pazCCZMjS8B_K`?ipW?vRwz zlKNBtCezNwj0cKZz-NGV%q3w+70oFsjg0@HS3O}s%Afe-Nh}T3$`Y}G31JNyW<A>? z896-Zmx234tV-?RlP6F;xeRH6+Xj}D#IX4g{^V4#wwMZ;SXDW$ui1ep*pBbn6JOCy z&%~{F2?I>$;d3f$O~&((WlB<b!!mDMscZ+~8gVB%SPteV@y&tb{E0SfgX38}J;GmP zJt7)$r?hEhaMUy2Z;67|kpL<roqb)-f^y^ye7CS@3IiSh8<Swg1QDM?XjiZZGv8-0 zBnsZtnZm~Ql5rdODguI*t*Wc#!$cHhumd2fL@_F>_!6^6Q4s{9`0A|(K_^MiFj^l; zB1)W+4J-+evFBr~W{0jFrq-RgK^uxhqKJXaKns_s-8f$~Q?i01KmOyN`Pu*Aul>|d z{v^@y2Y>jl{>8ueI@9s9Kl|5y>Zg8^nf~w(|JDEXfB!%K=7;|VzqcCIEKL05n3$mW zZXK*KH|>UxN8Nl?qx`wQLZo=H<IKjb-t<kJqt=8ErB_+KL~|T_tE(`F(-*>Y?~*s| zwVbt^BYv>NX%w+Z^vx^2nknO$(5P5LU}Lel(Uj|`Jo<uUW$>rHAg&lfA56N`76gZF z*(?3@_Qe}~+QQi2Z4j-PU5kOZG;$MwSMR$*m9NAgM$-()nT{Y}15Ps@DRM>}=fxcJ z?W5}#J7X8mGfJws!Ic<wx<14<m&Yk&FGpa-3h&&BNWR(i=y^JSK3$6&y<42ba<1jJ zX;x7pbp*M<dTRYqc<x;_o%JzE;WFX!V~Iw4_WBSaq>=LFmY*cAx8Hm3z5ncQ{Eg$_ z|Krzx<AV=AD1+>!PF+n%oiu8wn}n6sfQ0D$@J~00`mrDX?D$~|DS;tqnLF?_D@nnz zJ1b%fAEGDVG0}1GCx&2KjG|&d7s5l0CsD1-YXe$onWqJXMJT111jU`@U^?K~w(yir zT`DzddJdg_>^VvU&dUo9BB;x{e;W<9VFC^0pay9(cW~iRYzcb`4jLSdKh@(dZB-Tv zNu4dvS3qJ9;`2t01ZImcp8`ZFxUE(<{`Q);xhe<YVa^($6D#49$*}c(!+0j0d1eG0 zPegK_&qOC5!$n(&;y+ffG*2Tecn0Y>R&oIHMB_w~yDE`%zs&&FnoM)1#PH(`qlkoq zvYXKwHHb(~*cUp*g(-QJC~0}W35!h`oAT418Gy*_qJC?Ncq^lVaO<##L>Y;`9wY=~ zuZ&yF3(#TDXUd`C3rm;fV0aX^L`3HqWC%Rn@LrlJa?TAOLyY)nuMXdk@?+F~vm;QE zhdsc#pY`yx&Xf!$%kh{0^5=f>AN>5ce(#&#_{KMg`161D3t#^7&k)hKe((3b^{sCa z(dR$^SHJwFFa4um`lTOy|NnJv;2D;jnzEc0w1ds%Omv9YR+>|DG_p(4in0Ibhkvrg z*zS7eIly`}9Q$5o)8Klo>soQTJ3pm0rLIyqJELcj_Ma4@aJ+@^apd>XU(hD(P3zE7 z^;`i@{e;wG*=$<$IDA)vO338r&E=w~;2JPBjq66xjp_LoS2x2Kf^5}-{@^>~T)vQO zW(MYkTbeLMZ~&59?33mD$~U)B_%OOft=Uf3%T4)KXD_R^7zUzb{^y1f_V!nj)Ng-X z`c_uowF*>i#IER15rUkr+QuWo?4e=5@_GXjs05VFywK8M=D}N1zmuZvD>hNwxA5VI zAO5pn{ngSg`uJ~My3XN_tZF7Rwdoeu7lRV)Rk+ytvdBqZy$1Fahl&6=H(<5k*$3l7 zg~QgDu}|`u=y|>qHQPcKE<cJrS9JZ-sX;X4?csRl1(SqBVv^az;U>S+xMDCxI>xg* zt0PA3X`zVUz<qZRr(L^g<96TJwIF&=;%9|I!>!yBCBd@x7Bpr?M8dQmPV$T=i$v8< zl_(y9>zWlJ`e@oAj7PbEd%yWGXMkOSSvzIruG(O$vDorkQ!}hnAPS#lw49rqZ1A)l zt=TyhfiU+oQC5=e9#M#hJ|aHH7K-?7Mmy{>J2cs#rAr-E#Gcv4d=Q;YN#q8Wx!kS; zhB{N|AhGSxShHX?S&)UQoZrl&GE)dk`Ck%cA&TeCcf>?;l5ei8V{5-%F<5n7WukoI z6MyON{O!N<^{;>9*Z%ik8~WjQzVp40-n|py-~6rL8Z7*sKmKD8`Fnr&@BVlH@E^W= z_YpKz7;FH@gD5=dGQt1Yqad#|fN44`&4deh+YX&gd}FSg;A4&bHVTAl@`CM6uRzyR zdJP)V=qap?{-o~YWId7Iv*s2vai$F6QMbXB<jM$lD_^KG;3f=M{(#3h>!%ypniicz z<N|?(KoBzwl~%K{xkg;H$Qd~ycUnzr{f}ixOH+CM<@v%fK3}hvC9S)A=Ce5-T&Xk) zfhddl_V(<^@riEyJ8R17HsYAq*|DDRjIm!8H=;_rJCB&%jWry|^0-meCq%sJdZGBc z;}vMJXS1QQ==E5|tQ26#9wCp-wa`m3vovV13$WaP<PNI)1Pf?kIocOevGgrq2CXe= zR9o3Lkl2`l=g2cpB+JCja3E3-2|={j;PPVcgjEeWRRX1hTQKJ>ec0wS&PTv6l{ljD zk!t4gJpF~pEt4GiS?is1o$~=lTQvBYVZ}6$ZrgOyhQk65BMj>lXFw?Yuy$gT>d6Ac zHk@s+oZF`rT}Z5kDEg?iz0K$q)v&R<&HS@^PBj-`qCHL?Qo)D^w5-~%MjEiq>J%tT zDDXFNSy^es&Lo|4$AXq6x~@;-rkBHg+rj3ku#Bgz7H#E!M1#FHRJR0t2_9(-<D~g% zjkgIJcGBf))=#ApGK5<x4T^!5i4x0sh9L!_G>0kfMZ2QC9qnYHw)g_Ct?}(l8GAj1 zyx3k?g>~~6C!!!-@};`>P>+@@L@VA48ylx!5#eaBCh^4<C|)}ULG<O)LfQ*a!Tg<> z;$}np^fRCN%%?y7sbBw%-*O&f{*B-KEz)@CxPJXNe)B6|`O2q1{h5FLuYaHoK6OW- zsysojrRz{H)Rb;suQq@uDp7ghxm&dfY+`y_segsq!<=~WhV#2cRD;HmtY_=<Lj3{* zCgvj+9^uJsL<bzX!E>c3h4CzA%ydXMRNITgXqhqdamYC~%(CJPpkio41(@$d)Z|to zIwWF$%0{*s4d=Pf$+A<TgDN#lrtF5q>_iSyRvf)y3tywh2B>de5`MOZO-SXMYA>b} z#deZJJS9@f;?KdE5jw?e^cVZGd>^khTV_^n95U)BODdWneITl#>YW(P@p0vpDDd>g z-os#rtkRob1jhzyGBAoffmHo(FXxZz3}^cj3{pdLv{w-I7M<KS+(01(tFI_9p8DOi zV{4{F{4Ph!R$$*7zCqJGanr-~2wnE7OcU}l6K10_Oaf86x60M^HFpH)tdYQVONM&L z#Ron;|2*>SDo(YbU^+nP><l!4T)5P%9bAu<qHCvZ?p)IT^>KDHnKK7p(nnmKKiw5< zr9@3b9T=j5E#KjPbuAJGClNZd4Aaw1gxvlz?E$*h`+A5-0akPH7S}4Fkr$&)#s>Pw z^P{Yq72v|2f?o5+PSL+GN{F1{D83MqXh&Po-V()g;C$xyRVNm~Mp*#@wD!?f{4jDl z<mIkL>mR1X>Db_*W$JVoNw`g2EUHTs4{*{UaTt$j(^bEMBy5Ra3FFi5U=KAZA$4@t zz0b!7rfW}>#PCjQ&sAk1(K8|E977jCY)4qv4k<5GZ(~1?fa{{@W4903ih|4%Q-Ezx z;nCCDm7KG}E_T0LZ`#q~qn-Hr#3w%S!3Te)Wg|I$>VUs{_wLU=_~7a3nEO_UL=GpZ z3HDt2tDYCy#;f1vYP}1OT(~)T5)11_+9L;-5%$m&yiVqWOT|A>l<H5e>q@@%%rNtr zJ8hKmq=mn@SZRGXjMnePSc4rRbWZ<@oBY}8XnJN145;T#GP93k%ZDGTPTo1i+7o)y zq`pSGDu@jJ{tG;aJZ$|wbcrby*iAw#!^`7&lMKMg=xr(_D9{fXDS3HW=6x+b$CFah zsVUv6(O#HfacAt!J7)hpa=px)1CwF5X5t5%ajhb2D`f3KT$|b3&zeysbNZskiu%{g zE9rY(4n%?zE1pOw<;$ya&2%6;uhmGsmLtt1FzH(7)8kCH89y(G`$#9t9d1p3`Ky~$ zPOtGIE|&&_YF~TZQB^O8nrp_~c)1Rv<5xTxC73|<<!T7s*$aAyY8%*FKw4!w8GBfl z`;yW2D6PJO7KBFuspDULbrh&CKY3IJS3p)<;#Wl3<2hMJmrz%RuP<D3SDn!<Uth9% zJLNY-iB`}d;C`x-5xanI1FA&zk3B0^cw1Cg*@ZjR_m>Uh461+M{;J;>%#?Z(xWSj5 z2#+w>&3V0Pgg*T6!%uzc$DW>6b^c}xPsh{y@4x@ihaYvrlYrR32`^FqUVOd&7^EDl z(>WI`46tO`qa$f5iv8ciC&}cfdW+O{$dSn9R-de`EueQR8X;`|Wv!`8;!kKky2C#J z03ZNKL_t(FHL96k-1`Q-dlF>&rNzhP&$JOv&%B1Y;@8frOP9>NYYOuWPP@RY_6Cee z-W!~1BlM)fyK4W+5UMoYehPT?f8o%mLo2rD?nEN?Ia;yUXh4!w4_1iXT!G(u<5FuG zJ6(67H?47&B@xV4%iz>f_O>s88xwp93F7<k`FR0!U~F2=!u|^LpPdSY*N{xbaaHUo zo$@e_iPAoO+E0sB2NcxY42!%sY<3)c-C#v`aat2Mv7((xK+t`=1rfyfEuQ>V7vQ`; zS6>6?*);LH$~*@TUOxAzfkVf`s2niT(DAOrS)rxYO+>$-N6=ue0Rx4!I)FoYbqvyb zWM@m196*&Kt(rUa31)wlNSH?zXk<70&b)kw7RVuWm@?BRTu0$pYn)T)3@28Khvd-; z<9$6FX$)E{IMbS%CtH;oqoi}S_=1OHU^5HHjngMC8zbV`!x5_n2>W=B<QK++M)S97 zY%{VEK-X})QXpY?a@EtiSpYmQN|7k_P$;&p>j}fC8J{3N26|7$Ot(JFvlux?-3f?7 z=`1Kishe9VjYcC~X|#EjZ<+<!tjwQ@vRLa7AqfyBBT5%XP4Aa240WcYrK}k(p0hGe zqrngPm^Z^g9@gt&TkcpZFeSRIXe|pHILs8LH0yET9j$#9OwQEd4YAX`e@zt1L@Bw7 z;|yf>&q)`Ajrf|YmiQEoIS~z*w`NK@;Ym+YYl%`VjVgzerdJ&+E21F#t;B_#&maBt zPk-U*>G<RCezzmatX1|Oef6uK`OIhj`EUP@oTozbL{m(Qu#lWOBCC{wq8R_Tb8r1c zp974CPpf?!xJF4ST8o6WpohJqB@Rei!+b5FJpvXOGLhrAyj~Y@`dXa~a_g`$dsplS z8;QMGIULpcu`@Qm;$_-}9R(3fbMP>2VTd}RH7~;V9oQYWnbk0!-K1O|P0Wr9L>#e< zW001Z^B2d$9X2tez<KGlJs$=y5DJWagFelUDFO)uGJRPzW+-mJPi*tm8Zh&twLZHh z7f4^jwtf$oM}Y;)VEzZho4rD4l7YFSMb|2mm!T;4mRH+q>`bx43gzbN@mlQ9Gz=JY zTZm4C!b!6xFgW~6fEFAE)^x6>INkvEN(tS=M{|FwL{}<@?GyP7j0Y~TC;T{Zdx#k> zNh_&wkj)5|!_zqlXXNCRPfxuYudr1p@Dag&cq%Aec6}{k-1=1z;Uv7&!Sy-7Yz3?o z<#V12GgxA7X6sq3t|&Xi%+ID#M1ihn^ODCy*wZpOnHfHhgLcy5O;g(JY*=s~Yx7g< z3M!i%no(o61Z05m>5dduol$i-br4|`)E?XUx*l+_1(p*a85-SQ%ce&bJaRQ?qqS+O zCsV{sE5EIlcnRk+@l@ENnHoA>!D5YAZB?7l6i0g!qrXe%u}03LEA=dEBOqobJdVOP z$;)s!-!ixl7(2B!BrFHYnJ0W$)>oS;*sQBzqO-|h8AR#Qt(*arDB}D~WLh+OC9K&@ zl-_a8l4lAFm_0&#>I5{*N9%4<X=s?IAFNueN8PkxQ4gqNCsuVC-CjK)<-!BBVec`H zwxu;1TElPbZ3;V|S2K7+6wXAkX>|?DiYU{YHVt4q(YGgxb!{`z_Vjl9IQYyn#l;1b zyq+Qv_F?GAI*P=3jc5EeL^%m*U5J9>Lgd}Q{r~>$fBrZB<~P6ftq(u^F!ne}|LITv z_}~BgfA5!n`B#4U!yhWfS+owhlGRQIvpo5g`1*I(0EW5<Q#-M>h>7?(!v1WZk!bzu zuBupy2?CL(4=@vPb_qsYp@k?uEZC_9aR%w6U4XIC%jP|(`s2gFg3mS{e1YOG*OP3a z;rua~-Mtts&kYJ5w)5f4$MdyN(I5<=3^5rw2?cF-bbql^FWkEoLcVBvI|knV8HW<z zVO-xXyNF`Qtmg?MP;hr;M%woqM%Ks8^33pghZ=_00HUz?$NrfJZMn9yd+}}jW<{Th zii?JpjdM`q3QkL`9^{XvpsbSD<J?&!H#j7fo4QsTt7#2=MYsoRutXoZljG_nl7~>O z+*cmp<5q;cdfr2mAsiSsj~^)%24?`Y9JA=)k<r+)QWk8F4qQio0jYk<d~gZdrP5wi z3b$0}axyFDPH!cr?_z`Dh+tofnZWEpJJT>UC@^Q3+NEgwO<s`96c(5!m6fP+0TNit z&oB?W$^i*5<o3g)_q0s2d{O0Eu`pUSW6($A0yLca5>f)Hw)CbFUwL@gdvJxYZHG%Q z&miCd%_e}XAmxc)McAYFEF<GIp@<9?0l{`MAdFbb(q1A)8@l*H$|d}p&E`ZH8z&kP zx@e+ROvH3VnVVpN`&`=x<;x`x5~UR<HR^6t%)`Rwt)AZqq#pQ5kW75Ahl_PeT0k|R z1%IZZQwfl9F9TNS6^%3oPx}Q?h%m`wd^Hr>G1oaI1K%VHSxG-4NRK35gt8H;<YP+H z1dr<Dcos|L%*{-pfV3))BLOBvS(Cm3L`x64JHy8STo>B41kvJX6C#oy{_uyN{p@GI z@P#k@!5{qLySW+IiSphjKlxw%m;c3gzxVy${+-{6pR+C%gSz0eX3i-zp>#k9#rrxd zLPYOA{EISxKlv#iO{d))$8nyg-e!nMSR|D*e&+%)B~;L^Z22flT!=?NQ*pSe8tjik zljYWX!@4%&W}R<9Z-UV=e{9XF2?^c!`^!T{YRJqVL+DxkN|1{x2AC`9K*ZTh$$c-! z5-$zaaIqyCSHX=-<3Nnl;NeRo!d++FZdmmZlwM*DMgbQ{<>I#07lBhsbG0LtnRx-T zHPqnn*I8>pBP!4u>_-U^)J>8qySP}s6FKyyBqr47L9loqp>Pr8wTcncCHBQoCuW-R z<^ZcM$dc@`WcRk#uaJ57%MifJoYjp<jYErS?0inKCgBR${JUDeRpn`wpjVMru?;R8 zk4sNiD*4GCx|tzVHL#I4dn8^mB3_j4n}B+S#H|7R-uv&(9Kxw?9wf({c6{)R23Ro7 zf($d9#cW|5&1xoMdSX7txwUHejp!?cM#mjx7<VL0)&d=i(V5Bde+SJPiyrM!{p%P( zCsoOr>0o+ddQuHhbW&KVbI58I_Ec?g{Z*KS#a!;<p+BT4I0fSJA;d@7Q>SYqK@=zi zjSu$doB@u=l&S25mi;VN{S$-Ls%zS|r4VA8Lt?0P83%0kMzD&VD57yN%o!GpFO53~ z(V_On!1~}BO;2S4qC6=Eju_)Lzz^m95yO-`W^j%GrNVA7hm-Bl)Yh|rXX*lIY)mUe zhicNc6pqN@VF_{`PGlttGJFaw&-Zcj@M@+cxnOiZDOtaK@cf^Nr~$YW#oS(o>T#B} zaVFbjk;7|Cv0C_Z`LpwNO%+c>!PTe|#n$<pk*@1zswu$0U@%kWD&<HRRAAj|;6%Xz zToXkoMw6Yv8lw1UnLUS+)4b4TnP{S#5BD$31=dT}!AvpEoJ3(umK{hC%bLLyjD{$2 z{<kxQRaQ)+QfmQO{q{Ih!W{;p6u*qj?cL+gKl;vhzx<`2`SO>({Oxc5%Xec@<CBQr z|K$5W|MNe09Q;53FTebJzSG5Fo{44qGA&GmBvQN2)&c`367t^_1Ng^2rN8u+rGA>G zF~M~QG$_GAEs6PxqsXv(<M^qqT9ch5ZZo5Axx_Yhwo_7J;|zv9dBdZsbpsuQq+bP> zDb@7B@}vE8e`z{1n_tCcK0CkJ>?E^kRnbS6S`(RDI}F50-i{1qjbek91+HqNn$<kL zz89yxTwb=RHx0P72uXvtdQ&w4xe*k@w$p4pxDHKMrU>LIX1Bs>fTDcpJ8Y)-IEH4N z9F;a7MU}F{J8F9AY~%XcYl!!fE9SSyjm7hHSak2`>SFYAcw06Nz(9d<H2GB2vG_Yx z99=|x8P_2u+eKm$^eAb9vG^wKt>0^wTYOYOx%1g>&foi9MS<xwKsOziQ{91g`kTQ7 zn$g9$&V>N-{O4r@Y+(X9uOh&1R?S4d;~+jv8bt$`hVmq^Yh%1KPXRe-1ho#<b3s%E z5m4!-7CvGwJWXY*--@~{D&-l*i4D)wGfmy?lY>sxeunjXXa_P?Su*X@dOx(~E`Bl> ze9L$|6&&r?cGypmmXzsM&?gd$3Qz_g1Zv@a<_fXQ6n*>CF;-Mhu;k51gT}Eu3~THe z*Or4Q?z6}kLd^_9VZr)kJ%JOA#t^;t^u&2!GH!eYwN{lR?MsO=)7@9;1Fh4nuvbnx zGcyozD=>YYbl~QZ87Hy|u^fXL#Q+&C4}8Y?6=q7>#TwSk(8w)cy7-Uz)-e2@m=8Xz z%B~r}h+8m?CR;jDz_!QNhA12-zX;PgCrcRo14Q8}{>{^>);RM44yiH1BM~J=LU>y8 zzNQV$0}mfIDx2@-84`?vRb3!IK$HkooGFg3C!(j3S!2~^!7pas*EH*mD3if-&9LKm zPC!=`7kHx51`u5K{p2~2T}NajoC0ZMa}gIjkZ?RdpTGON-~7VoKmXOQ{)gZH!S_D+ z;7^(9C;rM${M>*2bAS4yAN}L6{nGREhkBHk&lGd-4FJV`a{|sO3>l(5r9i!%0sQJ? zkl4A(ss;sR&U|V5bSQ!$S&i%k<=lDPkf4Z|4LaS*gv7wr{!G%ibNA-e8{j&i_SmhF zCN1jb*o2<L)MPwUwwy)08<=S!EQfHM?+Jy1%*AuBD;CEh+_12?`sW<JW#Ur=Ps4Rr z^+o$|PLto-jpy<z43!-uqXsn}H??9i{UEdg(ih!XHO+L!dMr%$I4mCdYK<o!WbWJb ziMHo}`5}D8G@}frZ{pt$_?5(a$%V#k<av0(cQ|)*Z8hlR$(rnpsXWQaLHSYK*1+jp zH=rues^YLm>up;U4$XS-s@?uM(wAHOjt$AGxWoSa8lTs5KJ1fwea7qVXJw@8SFLuO zo=q^-2t2sbA`GU%n7xDyeiEI!8TyRfn;l}O$gZMQcv(JYz0#qha5!yf7R#~VGQht1 zZ9<BodLRJ}zZ&#_bV|2O7O<cm*+7%5f|Bn|wyO}aia;6o2fSmjpAqedkYpm#ZKAXn z5`}>)s1OB*S_hNt4UW|0hBLk2dSus%E_;VFS~vuu*VHV+l7O}Of<rPb<j;*L*7C6? z3T81N|0L5i4as~@E-tjXC6ccatEC7>gtwP5m<f|KcaS1xKw`hF_m3zps1PObfB|(v z?};c0s5?Y4M4iC-C{a1iluId;#Kmf+9I?l@A_{ibN+H&xm}^GHMqJDQ%0Kz1|HBu* z_=R8mg`fZa4}S3UbbRh}|NgK3>aTtCTi+BR$Pig-RyxR`47JBrTaSL>5uUG9DPL^> zkAwSW!WolSFc$LICxO1_pT#XmkS97SXS!ZJzb_&udIc7Y&(4|G$g;#aZG+P&rp7Ot zo~;LP$*kK>7<(R7bgVtJxw$3mpy+v`N80vX-Mz5I!;5r9u3|c;Ki!AH#3ZNSh7#@G zkyBCTsXBIikwzLFt;vSRC&ns%w6bnYP2_r6{4ipD{&SkcrE4-I{-{Gn;77fJeZ^Ry zMUO+x968ug%m`7Omn4DR_y|AWT!Lk;Q!H8#PTX9kQ+QUg6|DI-b5Q3j7Sc0cZBDOs z&-EA|VRJBG9{I!_OHdrZpHCm!OE@jM^i)C<6pRm;7fyq}!HwQeKY$e*Y_ZgzoP6(c zUAZ2&z9DC_7%r~b5Xch|!Sf=G@fx242OC(szTi3({Rdk<wbM?EGjK~9nP=;&XuC%9 zF~b5FU71P6sOq8eWGc}S?mM7od{ci+cf7S(vUMsBmx>qW%RS9?g^wZ>R1st|$WzNB zaz$FDiFN-v%j`m*`nXUJ9(7ef*h_{5&e&5ikfBrsQAQx$nuT`+h|-M5w7P@joPkHr zzOm@8;RiodoLG;`6@ddF%^P59$|v;2BYveE!ZuWFN29x}3VI5Ujg8rIsCyy}@6h5p zM`Ws2t=|g<NUN5o*ldKC&u%;eS72j=#5MiU(H>T7I8Nix(Ot^6El~z6=i$xH7Y_&y zoMKVL(A!APJ=8CDsA^&t5XF6)nhYfeSaB#UA*W{i?Q`b}7C8c~r4mJ^c@q<rbUXyY zO_oHFL>J`D*As<iU*{)))@N)MXNqah;z3<PqDbyyAgXfa0C39u11+J&3VD+#oab!F z$BaZtJKn^~=6B*^5`~G+=kuel|L)g+|J%R!pZ@i~ejNO@ul>^xKKN(~>MSm@twSo- z)r>*|O-(V<z81uNWm4hm3}82nTt>5I!V5Uvy$Em!UaRutPstD3HY;d$;pk(H>xcD- z*vN??a`B;NUbZ2{O`C3&a8&CN=AnEK2^C7M+G-7Jt3capO%(yEQ{?sq>UQkKt?<dz zfZ1_6h3|c!b8b{0DQY4tWg;}gH?HkKQ?MhCPnG~eJ#5wNuU0|~4l-9ou-38GY-j=w zD_`mEDM`{+S&@=8@9^ii--CvuUkh1qVI8w-W$?9a!Y3{EHV@7+@|b2tdhR!bK3@*O zE55yK%~y=Z^rbvk9^%327^uyf@5JxvZd*(T8CJJROP`!`uj>`xz4&_FT(f}&=pN~v zc3B{z<(}jF;ro?lT?D$?QoZ)m5?qVNBvnK3?d8!;HVV!0pj+5!EdkNQ+E$G)o~fQO zQ*fntD56p*totPPW8=9%H(pt_f#oST?k@ynryUi{TA{Hq@=FG9gRWwLAto|h7Hxjc zFB{%GiSdj)2y~&eTQ6q<b-!C!K#>W*V<S?UB;$dz1o`6;O=7E>nRD2vOg8Blqrei8 zVEWDyWXof_k~Y)Se9mZOhhnOk{cIS{qjPHTfhY)+ORiWGAi;u<Rzz7%Y1=>wL>UY1 zQHTP~ibOeMKbrkj?e=5a+jI`)4c;G6b5YR}y^?}vq3=SJT4T9y)}~3qt;r<qNYb~7 zDDjbOW{ND-o{lK<31$$~5Uv42fpD(Et*UC_ly7GW_OhW%0mO+?FWsyo;e?V-Vh8Ia zim#fsl!)Sb>xUnH^uPXZzedw?KH~dGGXKk0GcoZ6T7(5%$oz~AHeSD_?hPWqz~*-H zMAR(7w!lrZ=wg~SLe#{88cvL5t{TJt*LnuxSj!@d8|WPJbk*d;)z2;S(mQeX-}HT3 z?da%`S3RaZC#h*{VJN!w&I;umGusQ8;DE{;X`RVYJ7zR6wu`lfZN&i|l47B6f!+%~ z(DCEH-(J<vgLNkfuvNE4yHSgz#npy^@4)&UMRCq!9=%uf7ghoA+G!kf%G-xmUDW5C zHvIzAhXa0Y*o*7uKxfV^@5j5_a@lu8bVp>qRHzD7tALR-KJ8f|MvVPyqm2)1Ie_KU zhhyuHUk&?oVPP9j(vRAgDpt%|b{a*75j)GeC}8CAx2k8{_I_;5-TqR(eyKo9I#c&T z>a6rkL5wwT_5{pE#-;Vr-bMPkoS(}riY9R^mD3q+vT#{^IX|5}`U>0)-gU1rB+gB7 z_-8$m^4i6R3Fqm<*42{~^w=`$PoS8A3bq(>1Ivm83pw0O{T0;hvbcH`vmzxw+>B@7 zV2OBV!o{$qAxaMj>Ifkp#q3#_g_<3bL$7A=HsJ6qHMdx;Jcg>(IZ;Osxx^J5T;y$U z0#UR<V_%zu5mKEQD!@y9b1A{fpjIFDL;>9r>^hdsOz~xc9KA6znZ}EOoyFvBKa5?^ zop%?i8f0h6M6C^a{1A&9PFf4JnL<08nX<&K@slhe+KUT(hqSR{+SARh^4RHH@1c90 z0c>lD7=1mnZ*G5`L_IWUTg(gfQ>8Geb};P{*igx;_C%);#CkDs+bLV3mWsp<*{xU5 z%Bx>usIWmI%w^juS6^B+q0lDqn(GK=m8<d=buXz|lmQwG9HmKVo>&>%lX;$@F;muN zb_b1c)CrCD@EGYw6B*GcRZPKQhgv*HucuJnGi<ID${UsxGt();sGSyFMU1;lljIc7 z3!mwtV-F^7HGMkh1sA(;?_Ji!i`xi%HJmZsNx$A%IM#X65x!21?XIlC+y-L*X6^T5 zG6I`|;-%9$%LCiQMTNU$jrpkb_4xHhfG^xD5S@%~2O->;4~sh%cTFtV=GB`R!KgmR zSQf;71zmKu-f(Pe4wv~LI%9uQG?bk^?2%62KYw+#ub2?+l&V<<w&e{g9<%(gB2~E& z@Xbifs6G4A1&_FCR<A=lX-n*Awc$pbna<a0+h_QzUMk1o9T4zIDOVQ@k7U0ZGjpz4 zjYo0Ye`wzp7&jl<3t|V2qRLS9PM$f~qX;t{kajmmtvb-r>Sh#WR(Bm9QqCXZzRk^L zu}~c{we|_?iY~imJ)*cJN_sZyx34ycGR&043wfrbxt>Fmb5A~7j-zzx+=p8`X{Pvr zMvE!7BFY|nq4z3i6D&4_p)qWl<x%$-W+1f5XF*r^a52KWL}8QslJXPVWCu%7$0Zm| zuTX}HQN!jvR_((~6y_1LJ=aUTF<6=@$kl4%&La8aW*~~S%y=N`#nR9Mawrcc>2N77 zEFlirzVe%5)nN<>e?v3)RR*x;r#V$jAp4e1S4*Z^L&!}U=cZ~+0(lPz5{l*=7v>9V z=H56;PF){{KMv!DWL4Fi0Mxl9cv!@$G=;>1S(?S?o4N)X&DXRu;BGr58PAa#&O>2$ z2F&`(ii&xd3m(ofOK`e7fuUlIp+GF5YTP`ex{GaObC*e@t1{84R(p&*z*bB!RRemj z?AI$Z>-uXY0lXab=-IZfHdyj0^o@B9u|lnVb&78!0;jKU5WZ=pG_`yt7_UwTL6~OK zVQe~OaHeK~UCqwW;GfG?LsvGKD<kAVGg-{|N?(O`&<0K;^mlwG{c;d|Fi@j`BLx$D z2a3M`vRnfbAcey?9niP<-2b~beXToQQL5BohK)3{HFLbqow{aN5rvtfJ6LS`tGX!^ z?qcUH66yeLLGi8k_Z>SOVvZ&V>F>{7XVL@^+H%cyodwJ3TT^Xi?%GxFf^xVChT%D- zl9rh++w#{rjl%Io_0lB6%1K<4Fk96ha>B<(zMxLViZydD=ri%ESw(E6*u{9*Pv2O= zlHO0hvEbQBvof<l$_0bEZz`shx=FU>{xlG=t)x37tUe4zDPA@$O|v&^2hZlQ)JNM$ zA|-46Cc{faQJUNQ3M43l%`<Gq7rK`ii9#U2-3DmaC5~C#Whr|ZQCNLC{ie!7lrap3 z3{~InI<#NixXaH()Z;der^wF=3y$Y0y!ikUfGA=dWoHfpEOn;v^8%2bN#LmAv}gGC zOqrs%bz5Nno0)>r*aQL+CC&OhZqJgxg+RTMD5py>24Q8=aB9jjB>-<0l-FLbGJrY! zGk)82<z%e8#}{>hY05_9w=jSmCTy>SzZP08tC`q6YnaSTTGbbWnuR`Th~BEJ#GdUG z9g8NKy_I%;8w)3k$c!>k1@WFDn>`6cTG2?0mIY%bDK&>6Mm9Onoc;w!zzUps)#Upg z=H^nFtAyM7rGtI7w-@+>qAm-z|58&|uBPa$adjM6f7xeBD4<Y9d~)oAq1-ofhBeoy ziUyc6jh@X?`4~I*Jczftu5Go4AX4Yo#;&e@y<Hzd=7@G3Dfk{ZCBNX@2*(1sKzeQP zo9QKlel+LT{Va?5qn71<EN+q|d-lq7jUry-f_e3R7!M-!=!~vyU}>Dn#m}0C*d9&P zy4c5MM$|gYq9cf<R<V#T);=Bj*}HAC8x7BPv9=$k>Z$3nctWezqXB&80h4i`eS3hG z*4l3fNUNXiCp(wd5+Ehc)^~Agq1Q7QE&e|($>X|mt*Xhf&DD5T)LeZ?(0k1SK?#wF zk{ko56OF&lEv>O=a66tAH4)@=$(Az_5Q(IZL=n7sSd>A_q_rwkdnH=0U|EZu<tr^w z@IF{sWRs|zyq(+J%#;mL(m>OaVx2x+aaTG~EX}VvQ)tWZZ7LEK(r*B%mx|)frizSY zz0{ea{4dt#W&+-sxp!uLO?DXHw(g`#lyqJIHhwJd{Fc}2_W<iPZCf#`Q}-~8)K*aY z!xyIHSwOe(NQX~M-;>f}yxfZ)TdTxJOBX``5XT;xrDpqsvz<+2jbUW%XeLWDB*!4n zSkY{sm$R4``19FIZE<Q{RpYs{K|~KwZ%Rj++3h*v*qFIvu=&$Z4sPZeYO8Mld1ruF zKllpi=5cHyA>o7RoLeGn{F=m)F-r-AM>OuV&)Pg2^-aORuNi~!gM`T3g1;QLkju!q zABCoZPb8x;j=XUXpeXt{ZBiX#!~%}=QL|^)Pno~>KfD~qtH){niaP82hB1Cv-k8YK zNn_iA(vXQr&eNlrgN1Sh5&=1EA1^$C_b$^uk;n{>8<?4oF|?#QZLYM(v1xWBTU&`r znp>w1uh%eN+2!!N6{#ON2hV7Lx$3YHh~;)!7*vlct=_UL6a-}0Cx-lJt&IWCWkNU~ zy2z9q(4mF#ua$3c#AjhEruW<7qLfiX7P?$1<>tPa+7GyKEe@kc!SQM7OZq6()d$50 z92S1&M>@ncaqN@6%s`+R&9)Dl%ntjnDWIU%`*|}bi~(V6)pX#<nSIVQ&ioameroUt z6qM6}8r3^yY7&H_VLPgatq2POqpAg#r<t7?0L=PyAqru%Kk4y`y@~uMeIF}<LzX5( zVk)K&NF|D7qF9@b5F~nXG)NDN$7Au$7{B$3&Fo=$0qQeBn*$cjR(0hFvDXrXfhYpC zc9%qv1PdW<$92vc#Xi77l#pCtI8#*P7#pI*nZh_1EKY0Daui<)W7w=_)CmH<Aj*7s z5=AvIj)F`e1rgQ*5lD1;QYq&%Q^#;<!pJ32>h6F!yqQ;dN?*bN03ZNKL_t(M!9G>P zH@cwT!8pN)VoOCdlCz!**fXMVnh_QiKYhiWW2>#zH6=lv*x1AugTTb~MM*zoSCeAr zi~lRH*BZdOtHgD|aao`Y&a0pjNYJHJ@I!_|CPBj{Xh;{dObu_PJuj08vxt+}3wK5X zjol7<73^MJY`}tY&>^8Njba8Xk}m*Qm9<`YLZ6*+$-3<=XatH|ah`^c&w<HBw&nnE zVG-85-hhsRjSl)9#$>=>FphX<mh(*exM4@JPy!&$rd1}<ZlpzMM=0@+DWqeHDK^#q z4txbk;K2x*nx1K^>ReGQ#r?J|9Jxns!|3)xOrpLhV|yI%qK}(xa(F=*Zpd`w^1Si& zh+m)Io%{)XZ*4D+^`1{r(t6tSNXB-TjMq`)ECEPQTXXEPjdWQDEM_Gry8-(~1tI8V zo$X?UzP$$mO1Fcki7orf2vjvV{2NpKZSMxkDZwpuZnDN0>O3^yL|HsgYSL><^CAKI zw}rs%Crh?lUGt<ma(zggXyddYVxlLWZz3@)uk6&nA%cn-fP^JX-FUzaJ8^4eEr(-S ztV1<4-+%HB;qI?f4?+ah$~1oSws^mrL^$zxKzn0@R7?#qeKA=wt**8TV#97ve-qCr zHWMzUl48U%uKuCf`S@TuKub77w1g{BDE=4qU^HBlGAzNaW*NsI5;5~Z!n(cb(EN7W zmzCmXa6$j<wv!FpJ3_5G5+XyyhpFQO<|B58+=zUrL<xL;0$tcns7h{3!PXF7QA3&y zkZho$TSs*%Qz}irN@}yqp2BH(a+s;g!}k$4sBeg3v=%tZ+dWy>5uQVfM4|lOK+SeX zfMGAqmo!^#o4T+cB*ChCVwGbF%@Xr0o)n|9lPI3M5%wMu<8%lsp%?bSS)vof>mZ<0 ziHHui60vgl3%=YOVR&{i_MkNpLP=!P2Kf$A+yHe{KdpPz-z>AV`cy&9RdgyKcxKyZ z0vRk41>Fsk!R&=I4toQXwQOvOCks5DCAq%dpbE4N2uxg4kHo5Fn*qsz48U;sMphOu zM>SqW?RITiw{J#*ho)P#Wnm7vIbRfZUs}v6$ZL(6I#!}3w?C7Oxl6t4236m{nI0k? zrJd<Pv{Hg?m1ZJf*8s`gE9jh%F&p>d5fuYy`X4CRMsLLPMuf1?0sF+4Yaku|T-glR z*O~V%F7T<ES#0eAppDHg<G_2Pck#`_A%)k=;;N!2aB$c5i;U{@$!p`ijSc*ONj(0$ zMYt;a#*ia+YWi8Kv+%N^T)kIVzvWN-!_4e#6g|jWT@UL~Mwgxbbm<TO<}t%}zV`-~ zo9iLqR^bb9gpP+1fg;m(8>kcpceB5(`#;s^>{>;X127xbwDRf@-BW1Cj9&6T#cU)@ zS2jtD(;Js3RDdj_5`|423kvQA#lc&{`Qw5R9EPdU^()ixpr6KW8J8-NtEw<*INmJE z*fIlqSdbzd@7OfJgkfC33WJye#|%n=ZkY~>ST_tCz7N%Oh_KvtfS}e3MsFjS@clv& zNm2lx>fx^YYCTsAoxawlA{)D!H^=z|l5&R4vDq4m1Fy&Dz$vdGdff8H_-VX>R<1<C zt!D~j9VwV24X)};SuVyBY|->`N24g25Z5Y&cB#lSpx_t-h?<!a>`HGld+6p~DF0CE zOewI$iLNOw9JF1h=SB`=dP~YhkASpX9o9{&SW#xmUa4Ge;nqQxRjUZAen8HjvG;PO z>I<*8NP+hAjFhLK?9y~?iOkCFZv5e4xi*~^mX-%l-S}spx51)}6K(EB*63AGWRrPD z6k>1orUE8-GbzNuI1q0wR(@r#ixNVkq&P~m+O!La+8I+~it*LKr<`m^^)*x?$9Qxc zv(WnT#%bM3tXr>~F)gQ4xnb8yqbXR8%$(zB`l<?=*bvYj`Gdtdhs=~^qPA-70;IIv zvLJ;L%hj7mD|HG*E#7#~78k{HDa3Pe4Z<E8Pi~E_jMsaXu#kIaijt$<1qaZr;gS|= zv~-C&+?UC@wBSz69ISr2i+Y7=0JpD_tYc9;I}1AGxTBbfW5?GfW@9P3pcO5lX}9V4 ztRLuwo!-FWqM^`=fl>3%_ci34ma_a_UX^h+1lmB$2d4=Rd$bkIcqAbx*}OX|<<`*r zIu2`8k#iR#rbyYgTOv90UO~gXtvZ6nLojqP8%x`NHWpItO{~RYR^SpeO15CewZQLc zkf3EU<nKv*=yGg>_mwOZk!ogYY}U%XV7QMLJXm2Nb_37fX?Q+rkda1gx(qV%;Tj}y zF=N_hpG$yc;Tg<;h!W+{VXU@^Mm7+FsHW*T#|R~fj50`yt1y1qHH$^C7>%5j^GJ;f zQlfaJp92`I!2-Zy+Q&hOLlSpcN^@9oYs+d^jM6@wU~lJhB8n($VXAqZDY3_vD1?cR zMijHL+l8PKMGGTwyT$hs79&asIqf=~HH}WUsbHwC^_ns|)zq5tkzhIJfzNE2x_jlr zL&WM(#*yzgR41Yg?n>a>OgT#-?u7*N?%vI^e5{H37l6b)5prnhDY;9O=}2D8Yq6P< z%;t8lHU7|<LMgFq0gmrSsQcl8C?DI_zSkPSUUo&*dRbMalBi0u-Z5Pye4-W;Y`&~< zhS~1iQ4k7BflVwnPJAQaQ>>9Nz%Y0}RUC%jW5r8*Id{y(L_v^%C04_(Ys*$TE2zwd z<_yGK0w4|#=XGiC!L-$EV-n(1gd<d9Ixb2=6nz;>>GK_$V1kH)DnPj!Y&9VI2_DS# z)*U)gpxIr!fk7^T<xfsDnA1js=dFYrP=QGV+00#JIq+A@s8^R&p8HrN2G1Fk7Dn6` z;@KN_x>tTC0vDr957CQvc+`?<N^9ZB$V#TyMu_*r85{I8(@oGvL()RY&TwI{(Q%`* zWYA=jscmBBXhbOP&cHo_;!@cCAGwaSE|r_i<-52AapZU6__uAvJ~i{ghRo)pfhKej z0&J^ZDT}5bzdY9RC`Zptty4Nrv#{z1GoB-o>ej?509o~Fvpr8M#fqb<90oKYSuyDs z4T*@WUTmeDy(6X#lj_#IsDTU%MAPiEYRm_`!0<x56yP?zw3<5GUjc%3T&g-qV7x_R zY}xEPT>=HNzV~*QdfY_-vG(Cc7Msp<03c?T*m5-*Il_mO8LTvWPGf)%lJwz%D4d95 zyP6T|wo@>)=oV36ul10e?c_A&`&j`&{!CM&!lDi-Hfua(fo`zZ5JkU|NR%`lf%O?u z7724}6H)AGB8u&KIu)x7BIwe|nTXPEg^lt)3~9|>YQRhI!C|x3LQ9lrLk0uyk|>*b zO&g-@nq>i^Apb+eW-(J#(K{F8QA9Ko&`@-gchY1}^JqH(`J8|dflHC?yKa`@R*{pW z;+E@&4<|4#u6qd>n@i?aSs@lYoruUZ(QL-x(8Wt`NaAGph#6xO4SB^D0Ey0jk-3Lm zWH>W7qV!6A%$KP&*kyYj4Zze>QLHdk>@euR_;R&=7whU2D;D-*X6DA!);?S~pz@2T zH^Z*Qh)*QVFVxeUQVgWgZm;yr93-rBxvXM1tFuAbk$XkCxfH}fTWoUU4ajUQ;UClh z+pqUmo?L0*ZzLnU!LmkOynT6z36KoNtLhuXZy_U!&&&kmnXn(<W#bVdm6PJ93(c_s zKZ}U1?q=KMCS}V2>0)J<W^8>69I+(+b36_r83Ca9=55^i-k4-*<repsoT74BT!l*- zKsJ*C7(Po^xOwn;Q5)RNxpqq`6_#(hJ<qdqsUezC5^v9v3GKIL!wMWOcj|!mnrPeX zra*MtjugNvuU+=LZ~s0BsaexavU+j_3mh)e+j6V!#*E;OMx>AGe%&i5N>caLU|Mc$ z@v!c6_fEe`<JrhpE#GI7mccdyUOn0%>Y<rp(_~W<euXsSEA<ntGBS36EJv$Fp3)Zj z8{h~G@1D98XNneBS`K&x%YJwdi7zy*TcT{_Fhy`S0rPslFC5@4^Zm)5n#JMOQMXHa z62JGS{2N@aE`pVFSN##D_Ho8=@Q#FRd4lOJcyuP@2)7ZQ*;c4OlSf-jOtdZ4hMv_^ z(f4A)972y4OLDu8XF4y-p{EDUtf)K^wzjlNwgqrj>S)Y3k)&}#{A6KHiKTtcW~#k? zni8(Z-Pkd;T+%BXgalZ}y*y7l0$B7f4Xle0@o~(`G$VeF`^BX=frk6GpKJmfoIMad z#*8dttY`;0Gax9On~wH72jzIBTnG_`Se_PV<G}w?+!@=`n4pWLh+_io^<KIUJX3m? z*=`?;O2?c4M52{nbllg*Lyx#CdzAhB?W+!K{6M+3wH@#eUiqwA<N`#Xiauip*e@v~ zmDfIjH(;}eIOAIE9U+SV_tXcTPS#1&)^u^=GU@+Rp#+L!`rYHL?fSl5!lSSsD=v<i zDl-$u1+iR8-fPckugqf!_zMptH(>2snLol|@I3>&lCAs3(^?zTzk^ipvMX3G9NuUD z&XbB;)B&^&AlPX(w&7DKGt)r2YgTv5w@2e7Kq4$zLB9hF-Yi4)tzca{d40^yYLz!1 zaFpd0mbh2qVWN;z-%1MyiC`N9G{3K>OCgFwv3Z~KJuQ$j@z8wxBBJE?p+j{HMy((< zn@svNo(?B?+>~sXx$V)ydKB;1PcCMPkc=8)s)p`~5=5AUiBEGc;Y<UoYTpVLySbtZ zihZ_E;|9S?qO>VUE23!QI!{y34ts=LI+T7DK!Qj2#TS?X@T6!91r|_mX~|%$0Z5z_ zmW+T&)W#p;vz{*jdBIFM6QtzgYjt4w$9ugx1$x$*GUE->bc4Ci>0cseKFis#+;b(E zt6fftR_o`m5!o`^ZYnRnDwR#1z2FI^57UUzs7j!V2zx-1iOx>MPRRYQxLwWHAvm3w zOp4)wz@5dU>M8`9$<vutFB~t<-B>cR7-kNHFTKI`Jk*}0(j_d%DmipqZ2Lz;o-%Q; zl!V||Re>@4`!ijfBWJkC<e1N-B$(pBH!Tu!2aW&{PM83WR52?oVZZ*s%aYYxtuaWE zy?vbfYbPuK16j(qH=FaNHTvj+-4g>?y(wxj5L?d6o5ao9i;3hsAFl(bbjt`skb{++ z$O7lw%(Rk_4_wpqoWD4{kUC{@u>ndjA8Z>+Xl!eZdFI|3a=!kf618@{y!OjZGUD0{ zdt@G)ukhA>PgFC8`ci!X{4aK-nEI;3)%N+iN<_iBs^Xh|Z4(L4WOcT^?U(5khVy30 zfUOT#7i>|Phd|hwI;I~0Vz{2Dffw%V9WR`O>Bn+Fv-p*7j`2q3NYW7|sXKtf#y0aU z$2NdfG3SB)4X3KK^y6@}S)#b5vxCI}q4_>rx?N&kghjn$v+A!o%ixU4o~~zTroysp zR*91J>_il#%c<V44N+j;F<@*yboHl34VVFz{1o?bVY9f2w^7Zbl4CDuxoKgopR$6* zYOvu6k_VIs?)n7YV`j`xWKPEp3G{NTVM$>DoN>B4V5!#gk|>DJ9+o>%Yj0M(el=~0 z;yFigE)U`V6e3dL!<HzzyM8}fK6`5^6u0eY{TNX+rCi{6fc{(L&olG<hA6Zr%9hp_ zL_uo^B-q?4zxr_McS7eZ=}h;CB6~2mwB8X#TbD=_vE1*=nez76D-Gb?uxvYGxLZ9M z@l@KNs4^wp&NPW6sfXd6PPz<yyH*fZJe$k~GKGjb8NrO-gk~q9Yk<ZNHfh6{4&$x_ zY&UXSPj&QFF=IqfFz@(0<PfI`A{ETN{$wV<ENBdOLPP0KRI4StVrJnu<(P=NAffp7 z*H%5Z_XPQeTT3b>(c={YC~Im&13y4%k5LjNzpF^GMPG8=Y6L2KZC;+If-#mT;7qCR z@M(YdrZ?)&b$?T4wAO12=BIPZwQYRp)#e%5#*4#tOK&Toz!loUf{MneB*$aar|ZOJ zqvSo$q9+6s(Tf;qn+hQ0KB}G$77Ff5Hr&2oi3mTiSKRS7EhO=EM=Ov~n?{b|UhU2s z*7f8*udQP2k9ulGN$0uaSLh^qX4-@|@f_%0nVcIkS)kMkp3k`+31MEM9){sLv75Q> zr)9#PLm_&GrL#ITB;K!D)EVAnJDek)!jjQ|fY?3TQw=`Oyhz%lHHB{qL*3)rjh62K zk~UPI+N|z>TLMyHvHhG_kZf@=^yn)1b4E_+@mxOz?rNId?y$o{U#Gx0r$Q|0l;+x_ zxl8PP8rChxwP3OV;#E@OBgk;V9f{s-dmt8|h>do3`pa>Jw}=YI9?#-K{7fO3hV6)# z8fu>U;zlGw&t%7Uj{~muBM}fag2k(jEhv>JhmK)G6tf0b5^O{3JyFbjI2?ycl)1&D z0Bb;$zjwFAS#0HjSgU_6SO_*4uVy{G7HFMjN*R@9Mc7$HcI3NkF<^4WH`!WQzB8~; zHiymfUoqH<)>kuSwu@`oF-!MZF#qGScAM+fRiLMuz<S(e9($vHO{GKNukH<413*LJ zWhenOp(S4zRTHi5z4s<OEyg6sX*De&DIDxZfZZ_=swk-(W@y=<*E+JAHEj`dtZHi; z--rkeS*uvaWa;?hj%W@P+tgGhO~+Q*+@EPmaJEsos=8W6$fJ<Ih87$0S)g(L20RB^ zMxO($dZKp%%b7dDcuh(xYnbu{*pK1rFg};_8r}=UHb!6MDg$hHm1@<Cn&vdR1#`A} z$v;+}h4&$@#m6xoc^<i8#V5k8LC3j}&+`^#iA{6G<ZRwecBpbl9|M^~VTYq^fL&{k z1wJ7OWer;iDEWcw!#d?PF+-D=EId8PYRAcKFNbD5<dnUNTS=;Tm+~hsANE(${M+%A zmsNyeMg{v&*+DIZyquVtj3fl!REZ(>B?w*Qm&$a$gMs1WINirTlYY*q?pV1gtCRzt zv<7QJJdW2g!|y;=>cn*VyHu|7Hy|>}>HG0tt(`N~#H1w639&8w$Du(xf|Uuz)2aX{ zEmO-!fh8<*x<Zt_sa!E;VmYaCbrPo8W)Us42~jKQR2Dxd)zu7zC1JoGsX}kVV+)84 zOxD6kq}2vi2(*YmZI(Mo;ZGBBf`cSg^v!|RM)Sm5uwAJm%r)x`j<?W@&P2~7ljx$Q z@0qdL$Ohp6m<=rYjxZ66uMHTTlh{5I#U2ie;(#$oF(*uyO!RFpYv&BOt&pZKX6G0z z1(!tlu%P9NC?aL1TtLwh<)rKoY#9u5Sf<f912>k9BGSVm*r~l%%WlDk*F;GZFf35o zT}hKM4s2%1B~f5(Y}$}k3h-_*l>=pF>y;=#-6e_vIR7W}wBb6x#u$=+0sat)FTe15 zodG;muc^=ZCP4xP)zxQ)wLrA~p7?4L>dTV<5_{@VzGQKBQ`w)U5wBigizmRg8-0dm z-+)Hpa;Papz%Fy<!XRMNgNB9kadtfQm-!a#+^P{99T(fD`VnpxWNd2u)`S$zUzWyC zhF>>MG*KuxE-ns@`vXONj;-+}l8hIdq8`9CZ-M~+6;Rz^jY;c}m>{Lc%geS^^yCdV z3GvX-m+#sHh%OXtB+1Q-!#|4`Zk`G3XLq@o7%Yj94~%N~{I%XbR!1B=Zb4p6c4^+( zV9d8gxrHCkEwQs&@>11ywpbYnXWt1^GQs4gm-m}n60!n|9=&(Lh+3WB-;lVfv^}N< z#FMzolL<=9JL!MdS6vC~BOt{Tb2BJl6315sl?C&3Bw;wt#Eaewb|RP;t+VriP%sYH zcH-PCwZ@}Ftxg|Xi-ypChHA;E{j^BZR7`BvExMEFsUe}4zc}E(q&PxN%R(8Zsi+a2 z^Xn`M!9-6)C+A*9D@=z)bjg3%4%7h%t6uJ~#Jz1n9l+GV#90tb=6ZgnD$Q(W1H%3c zCoP=it4$sZLw8-X{N!T~XT}<s)d3-6hZPZN%ZjUDPNRf6^{>;1A>xvctbXs&iQl$a z7||TYQ~55bwnu5|RGt@Ni?JuS3#L3AU{R?1z;Za5BN8y_)P5bzxLfWB+5rpkGwc+A zk3HgNGX;q?@;Ll_S~h*SIr(<X3k`aZ&y<n4Az~cPv9HA2Ll|1Kc4W~2E1?k=Xi=g- zNh-z3*!im#U@T6aD{t?Kl9+H)@`~eDHrA7MvDt2|Xo!NSK4Bl=Ion~0fTXot;!JsB zI_a>ZgJ!y~9-JGDv`Cuu1e6#xO|xG7IDiQ6>6{is3LFJTF;KiA%E6Oi-I3bQdJaT9 zWMcA)D03C|N)4jxtdKCDVDI1_1fT+%0dHjezC{FBEwYsLS1|z~`IWUh&n}SknwVB- z{lyrv(PaMUj!}U_l5jHN=(r5KyHGiTdMRk`g|Ri(mbJv`hdod$$&<}=sM-8tH>u+N zU^}FfA;X)NSz@7JKZq(p4V4sts6aKdxmPD*#E}QHs-Ujo%b)a;Q}^w09FGm31h*Dd zro@mSYOWVkt(rYBXT!JZx`?Du;k7&s_t9OiAJ4T37pK(mWdk{=Yxnzt#^vS)6Za8x zBjZC|DnU$iKQ6C|m&7fRqa%Q;jBJxzq5`e?_)V^8({j`4yi8lUG<t7Y#kat)Nm|Fe zPo^++wDi=ZF$J<o_o(Xu#7-FQ#iiOFnOgaz{U%<l3l5hbvDx`^gIepN^~#@WIop*I zux-;?8b-8KUCTMa3OYjQqghU^O>}y1w%$qnq&}50!WDsPaJBBQu3B$G!kuO>-GqrK zSk?A`JL&wAbfOYwu*<Zy0!mTgzT}n`kky-ah~i}@m<2|goC}vk!DP#1qNro3K{md5 zQ<i2)I1Lh%)8LBIABk;nYM>2cQxA!<VUkU=5hB=m1)n54(CQ(j8OPAXLqtg!J2ptR z+CEGprW}thdtjy@IHJMr^9E6#BJ58vn*yaYQD=3nh_d0a)l5mWsA4eXU0IK*yQg49 zySFIH;oa53vL{OPC9%Zy0%wW=esu4=&GkA1*yH5UAOxd>;tM%_vuX#R9=lE)cf>~@ zfInADtZa%~4?JJpCPp0<C>NS88C0Qo#{tVjWgLGpTy?fvrih+hIqtA-R<UGdn1x|5 zO!0hHm>Vhlgz}I@j+w-BG70gMAfPdf0iiKb=Vb`DC=aAGX(_|vgEb!s%I;|lISkNN z74RJB%YkZMxtjAGM3>)*=|~K83tAH7{RSLXU9ntjFp!;slafe*sHuksts2x^c52-{ zhfle*G8O}WUYcIKw0=pWmr`Uxos5^5sHCVEHB-&l0McCH<(pe*cMOnw_VUhb35KTb zjenF4QW7)sINp{KEY~qKZMPb5HzNEXxUBoeUe{vc3qMW6Z7ug*GjpbU2nQ_R54u~X z0xUv4p%U3lxok~1wklfvEKOrx{J#B>nZC>dJ0uCIQ>}<rsY=4Jy0J{ysW#JO`Hr}& zDoL!Vl|FH#pbk;0fY6~E3zPk+3vd`JjKMP^Y>kM31Y*|EA_rr@(pVyQ1VE5u$kM#Q z%AFgkQC}=Xag-#*j=E-Bl3M84uyMku?6YHTPIf&eE`bSqp2uN9;4?H?ra#=Tu+(Pj zcO6kU8h-4=@Y;LLp-Nq+WZ^X}9q0CEU=fgr!Wj2n&6Fi9m<kb|@;JTQ`TPJ?s1hY1 z(=OdSpQB#wtX~r)0ut70Nk;OSZ02}s2ds&Y5k)ivEi0l#aKd@uF{ZZO+p{A|wI`V* z5v8CP(~nJA3f#rfKxqL<{gU6QfcTw66m-Uy<*6Y`3wR=mR-a;|-Q}zYs`+RyiK0<! zNA^(n(s|e1Ee&sG@uusQ5#TnnZptk7k%L+mLKjSkcKaIe@1=vW1CNgCF+DPaYI9R6 zDzn|?EfAy0o};h^fu$0Rf5*q?OtZmk<i1l4OH#CW-4+0=pb8bl5*RG3<#^_q0a2C1 z`C3c>Q&iZj0N_d%^|y$4tt-<)(CV2{Wt9QO*GX-H(SV5;06f@19yT}Ap<5blK^(MY z<hy96#%e&bZ{JQ-ZQ5X9kbzq5B}U7DV;5~}rIAynn_xI;EYXS$NpBavs}|X975v40 zNwsg2E9%0GhZ^YqJ{WaDWzZ9|{A-=d7gH(sspY*!adBky9$2Ay!cNyygX@7CU~N>s zv0z<L!C}vo-GW{0^SJS8kg*|aW3TUd0G#%D$7(k9Y`<}AUNZBWg3t>0J)h^9U=A__ zWT!kVTQy|EY+p9udQUhaf?C>_&WpD5$Q(qY=pfd@#TW(Z1G(alq*J+?k>$BXG}3X; z(1_a!rV$>cje@{AD28th7Q0zXCMqobx{A72=dwn%Yyx5>qs_9l@Pg=&6hJ1ojhki> zhg!h}K<PMP#WS_p@@*)U_|6L~bC8XbOq{a8scW<LZk5Il&~aB@p2T45W~&(V-_Nk8 z{e+Gz3`IJgx-WVI%lJ@tx$lr*SG%h-QF(<xAc}Adg_*Izj#$~WS)d?_MA@X)-zSOy z^QT=*NEAzFMWR@J?*kX5+e9(W%*tU0i-w(Ru>k+^5K-{84N>X^&6+@FDoALr6;bwp zq^H}NGGS?nvTCy<3R#l=%Gy+-NCo*OQAlC&)ORhca)7)&e8>1yaXvoP_4O&x?G+H> znjg&*#Ee4b`y{j3Y{7IH3Rvwa<5A+dl-(R%dBCRN7D`_5db_fbX1`mCw5(&#yP+oK zK&)xMfn2}imuB;333J6{juYIl){V{ro?lxOa6HGjYe@~MC3nP*>!iQ}rZvD9Japkl zmB~i0fB`e2Z}E{wi8(jYUi~8|!2=~~6=x7vy#vDjdK*i6-L%ZpDxi2&bppcQcOVe6 zuk1Hm)6FCzL`T_I&`hnZLm?`wcaN%R-grnpcV?sJzT?P(I4rYMCt9drre3edStVVI z4Cm2L4=oNJD|Nnn2u;_Ix8kQ&g^4zL-~$A!`1K;g001BWNkl<ZWxa#ALp+p<Vwa-{ zWRRGUb7SPA-?a6sO-`#)-}c-do%Uc!XtgQa!uoDDmCcwG;Y>eT7~3s>2c={nZk1_O z$mA(QNu;~)nCE#*wNpgM9uRy4-<2M1(dgbl-KHZ7DmHzyO*YebDnzQUA0FoIVYx#T z(}PFKm+?1-U%C~TEOC*VUB2FI>!874n$^z1r_<b(d>^Vbw>{?bVD1rRY%^vOS#NbV zb!!i1$xYG)B`|y(PbRZ}Vi5yrzfGTu^2XRTibP>D@9{J|p3z&Wi!G#EyW0y|XA=t* zu@^*{+}t>i@Y{HYZBMec<(~9AMBxQdSV2os#~U+6|CiMc!fEodnZnc`J7gvI1zdPG z9s!!R7O7|!X#pgwIw{K7&U(?J;;l{<=XLwkFw9<aYw(^}ATNynk|=L*y~R1e)jW+_ z>r|9Y-Q+YG&}tPK39)HX3=^wj19K*Yuu;rqPWYQ^#XQj@Hir#ku~{o*;v)*-0DG3X zh6yXJfT@`9$ku=IyP6r0p`Y(nb%7VktBD>p%IAQED4pi43LA+g;Ea8<thF`_R1K^i z6Is5d>C#}1{wUHtr`+k5G7uR|EQ28(3oJ<WFx!2-L>tT_@qpgMJTVs<UqxCc(dy$e ze@7v}%6MQnbj81`_V-&{b+rjkOG5r4dsZz=*OX@b-5MHi=^?7i9^1?95)Ayt5aW5n zoVc+M0vYb^=t8;Lw3IK4dVnb_R)A5+OaBGQ;Ta`bW<Rj1N)>WaDB=1@TC<0I@OV51 z8Ts19$er?KUNfN64s=39sn#`WsTSFgkD-bswV;%MvwBkI%h2r?<nd%N9GtcNwVSa_ z%jsWXFg;=l<!rg7msPTIgj1x9hjn{OVtboxmf@TSvlu{2!_e$#b1@NzG?oT80<Sa+ z_|$MkGMf|$w+SA`HF02INu$~<0*f|PRE2~3T~*}TtgIguZ3BA^c^ex}L(HPT1KaWg zZ^Wwggf^tmr8ZkN!a|fL%w9Mgo#Q<$l_>3>`#s*9sojc?WXRc39$~TKDU%J5%L~&1 z&irUG+TlA_0Gr7Yh?4Vr#($w2ndw4dqnzalqFBW`F<ZWkkFaHFaW6tvk>481r7`wI z;Yt*LDQy03^$V3V`Zme2C7<-<y_hLg1lfP}zO2udY+PX7OU;H*)KI0I5x58f%Vi<Q zxXQVXG|x5{Vs+t3IgX1LzezV)LJ8!1ySnaNuQh;AFM<X8K9xDg<R95<6ilX-o=6mp zQV}nQPo|f}Jk`Jh@t6I^>B8hDrHBnw-viA%X;H@Gl~z9LTAs=er=0p-UAqGBU??h= zvC6ordM$4?#92>pxEMSMyk5%bRs|D;TvPB4lyhO4Cu0#Gs@v-dW|TBFel=@}EO;X} z@`);O8{T$B8+Sy=B{5Vu)ntJqz@*+_Rn3<o+Yn49Hkl}Uhf)q`<Q1p>$8n*x_u7kR zsZQakgyIvLy0n(x=E|hGv4GK{F6R~FYKQ*|E-!g`<5ia^jR6;SDJ)t*LR)D%*yWXX zVqg-nZ{G0XV1vH<W0bI-tA%>hIkEvNA~WX6;bvWuQ4Zjn0;{oh9pK2=<x(9$U(AW5 zD;>E}oIs=JSmI{R#zSkG`jO$ubeL^J`jyzTW%>6z*8@B|>-SV8ZP6%?D=LUNAAo0( zL*G#ng`EThG<8SyRe!m?>hgp27l(jc0n(Z=-Fh}%HH$GY>b^CQjvZlA^cDzj76*L) z)Joe4xo<XIARm^1*l_P{mcw}*`05NV;27>;CpVk5ST%R8y8R8JIO}qCUU$tVi|Fc_ zdGC$o(~Ye_&xt4%apF~T8=O@!c0$VT3IA<|9=a11sOcS4j=9Vx-_&3=;a3dSVRgl` zNR+^tEnQmfYFE~!>O=v(HtQGBQKrNvJB=bYyCF*JVd++?V2yM^W9xAW>h@&a)&;Nt zf^ieIHM=h#*iLyauffy0gR~)vyIRJ=d-_JU3yJ!1D1NU$1_?G;+D*Mg5B4BaAm;OA zNQx>$e$X{xGfmfJ*Lh8KXvH*S#ii%$23q+Dt4^#@F^AEqNF4Y&wiI6vs42#6kO3v@ zMo(V7Sd=Abr>Q!0KSooSF`8`)GmaVAUO*<V0zL~g<Qur8vQevSe%4_Yd!{8yG|X07 zwU5>V=gsG$c?!y60nB+!Zf#Tl(PLW3fs3!LRisBFtP5I{cyHKjpRVbaa}YdO8)sr+ z($GHbOB(@E9DA2p%~w|=JZ^mT>I>m4D<U$|dD5{x;64c%vvNJXw=z(f;p3|VbN}2h zs@Hw?gEItEt*px#=BvZ?2CLE>L*`C5PJb`C>+J|@J1L!{G~x=tp3BxxZ_QCGGy+G| zY{k;lUp*YEYIG<GGd5P?CeLIz;jtN@bv462BQw_#v4x~$m>I5Hr*g!Io#CayJPNEb zH48369MxPXW?QBcnCz&}V=>saVn7_#2&8i*${q<qj(>$t4&|RsvsA#;M<QFI$jEM8 zJVuq*hHc!nA_`(D!Gfm~waq5(S`ekb%6J^p36Rw6ri2g05$c_=I~{9i7os#^@;stu zxxkSUr5jIJ?9moIuBa)IC^mOmq9j043pS2tdXOlRRqmE3sn~M;uoA_#)_b!esT@Gs z6rGMD+Y#lZGsP3g7ay)>%9+X3%#_5y0@9Knn<>jtB_6voQ<CkSiPBBLb{-i*+KmR* z;|`X$3i+n%l~tgpTh2;VnI)wzb_^9+K+jUVz}984r2W}87|)*mZyLFTbHP%=Gpjd3 zllja-6IBg0m7iTl&m~s_ZHHlVrd()oHw~PEj2LpTRUHg5LQShzizm781@+n(QH<ug zFbCdRX`P{VGK|FWZYB(;z%`viix7GyJ|u0?cDq=VAr3puQkdjqK0H5L!^9a^Fp3=g z2ou0U(qiRdeTIl0bw15w4%VHx0kn!VT5r{xkWOcfBO>R<xNyVyTSN(88fe-lu5F{J z_e2AnZQ5GD+i#n1STmfVd6fGwAJ@g7+tKK;jOI>QCH6MMymPIGf-@W4E%;fv@8jOk z0x>Af`<Ss`_nOC+kr|{*%#Bk8bGG4IMxgp}b9utrBmlwoUlg_~AbK>70)8uGu|I<a zV|%f2T6?LV<uI9yB^bv~w%MK{bv&W*iM`i0F!b^0g<8dvZXkJ%dQ}>LC`;Mqu2Itn z4}j4lRapz<x+mUjt&@0YjpLD?y@cEn28sJcduvwclvz~qPzTxR?}Pdzgz7kqZRkv` z<-^d9>x-&Lu~pE;gxiQbwolr4k^Kq!A|I*<o+Wydi4t2zt1oGgJbe>l#*e``o@!wj z(L-4p-PH;g9RbOaBAzRYx$gW-q4pA&W|b&j(j%Ue<jq>KvBQZnc0w{zs-{Wfb?R9) z$`7HE5U-m(OE^8jV!Ig{)diZhcd%NUiY~{VO(h2;h#<!D<CSK>(w?JphbVToDola9 zMDeG(betr*m!1PG9Z~G`*8qq@U5LWx6kkfC62lj+MDZ=J1LLR2^UNp5nsbh1APP4` ziI?qj-h{ggtr`4xcZl-9Oab;_AyEz#n?Y+>!nwy)6ho)E*%QP?3%-(gK@^xNq=L)l zHG(<vEUeyGne~?MHIFi0ttlVN^+rXoG$;AgYO1PgyH8#9W7|ySS;u20TKQ(vKHv-- z{iPYvqKLyF1E`RA%0+PZ>yH2IgQ`K$_yX99_SC}JDIP;$TgE&<-(5KeF$XEOg>>$I zL({@C0s*8lQY<K)hN`f*y_(JAkb5ck%{0F`cB?7QVIZOtSS9jEUuQOPIlLh3CTgq? z3z~7c@I7^E*k^`1W)=%83K6D@g6$V}4oino3W?RyCCFyoCn?NO!-!cqInRBOAWUr< zmGNx7Uw7ohr82&<9QJ7^;B?TWbnqnEd`J5~Oe_6r5D0R6E%!8V;{|9P=ih<7TuC}l zJI?i&2PAV+dSc7Y5W&_3_lZtzth#Io&+$fc!Ny!H?IiKLMwd1T+<-bAV;dasqRsTq z{xYGrsdv|qbulglhV^hce_axbX_b%QavG6Hz5^K=KQFs{PmFtz3GGFddJ`%Jy|yxY z4fPaBqy-?P_ei9*jjYaDQBx9fyb2Ddb3{zDblaVE-9&37Qp;h{4LK5rhn}O|0X7jX z2J6@OgVWo%8Yht91-G|r5+-+m=%1?-Wx8NlcUe?<TwrET(-CQ{Cb!wZUd#zsA5?!4 zr7cma&2Nw3xT${RSs#gg&Ho9N!=DoMZ8)x%M^-cw3$q5oCh@El=BA~vcYY_{5tK;v z=vN7ErUsEHlI$n|!9AdfDE>pHeG<=abG4=s@@=*`OJZs7QN(P;MQ*m)lY+CGt&Ux= zjx0tN{%2#$WLXoX%0uf52N2pKQ{ZgTOxmuyNMJ~aoJQZN9&pS0Gc#3T5oDwlEG|3? z)Tm-^njJ(r1))fSt~o~_P5HVY`rOnGQ#&CK*h8On3K&`nJHAye^s7^#5nf8VN+6iU z-z;y*r!7UAg<myAUbPtCb&F-ql4C0Sud7^?`07es4k`o2hw|tG_ra&(Ewn1kOcvK} z5f7X;u9o37OUq8_kI$@BoNHOps%YD2?}8vQcF@@Sp)8JvC7t8+BZFDNUaKx_QagwO zP61TrBgvj&9-sZT#1*Q*VlVS;N()FTXucQ!!R1^08514W4ZZXdO?G`jL(IIQ$}CQB z9Mc6Xm!oZh!K@Pk6{|}F$;WU5fZGW4H2}{iqCm?>1{bu+6>+W4syf)G63x{)M!zFl zOl-HVy82fJCcag~M|lT&Y;%FIX0>kKxU^#8`>VEE{|@9UfanMvXmU_+plz;5qnBLP zmFu`-DG^@VIjJ(!^A{Cr(J)%FOj15xXX>QoG@?i7)I~L_!feTVn%yUsU!-~=qxP?5 zLgpuDY%?|McBy#k-^9|~*iEeEd`AnGFkEG{_A*x{bRtAlXZ(;iZb20i%7M*JlN(VE z0lPFvI}HSJOO&Bap82EDmnBuQ?Xa80!UUzs;XF3?jhoBXkjz1$UlB!66|Uovat9+$ z?F`0uCOGO=Js}p2NW)K#Sq$0tx*q_@*#KgN4;XfZNga}uPTL@M0vWbGy3QNZ`1_V2 z5;O;PQZPu;R7Ikk0G*A?B#9S>Kt*^_WE+FbJY7Yh@|-0IpwWo>^^l??6fEF6b>S8` z$maz@A@PL7;$gWUN}?uOs+!hFvpzy3J+R`uKNw6i9gl;=W>A{`X5pPMQxZ|^lXHQ+ z6)aWG%sc9d5MrToMHH7{La;jq9YYR9;s*=TN*NfM+S9BRr7{yUpSZkg@G_ac@wE0y zeN>g-awqUBQ=lVl*aC)gtX9NBbkxHm#scnjn-6nQMGnk)XwVl#4}-<*vV)mLkLs<Q zl>Uy}=XzMdxD#FnCfsUT7z1L<#>^EJ#ZeeZ7?@d<Z4r%W0FJO{Dp2J}QJq#{N4Cl; zvh5}|TnWu$(eu#dbH-*oSCKUei+*@OtC%9~=^-H<9uSx@Iv<~M`mS<>(CI!sT5P!o znvsAmI|os50L4fRC8Bs*YQ5D<8tjE+A!~5d!`S*;PVw*u6FP|A<l?cjw6g?^OLx00 z=I9e~q_9n#M1}dAW5D!eqco56d-~d#T)hNbMgJZUm!7W;Zc$C=S{Adt(`<7OWLVqo z;1T9j-6XC}`mEHi5@1H1wMTM3#wI;2g_&h|X4Olb`rLtv2@_5FY`I>->h%K~;VCkX zIJ)c*V-?ZP)4dz|s#KYiJKu<itI35!3%jsUQ?azYO)$g;ESh_Hl!vX3m`pWpf0h@L zs#gOwSYFI*i;;bI`rWzgu@Fa2Ow9@fnt+k!!^a^Z<neYCHq2G?Yc0Bpgkb}tu~9K& ztwmdLE`e3otnF0gr;NqFQj>#iiM1E1?PQOiR0W45VVWwP?}K6>ibQhT($xgsS3#uq zN<8VjYTL&+yiog66D8PY@e|bKeEU&EPOxfj5M>EV#kSSViN|{950NNR##6bgDC9j+ zjAXc6w1$?1n?A+jOp*9nPn0o+lgW<e;er`!#~94Mx225Vlqks?(vmD?MXGJ4PL^rr zxweo-A%!TacP>RS#oue)z|mlKqm=)xnq}1-o*kl!J)bG&f&|q}QWXXh7PAY*=|}*Q z0|gRKq3;T4#(YvtK9=kCDbOjN7=AcPG4uut8Q$U8ATuvXpYmY+3EPLPULAcTh}{SP ztI9n!&K0P0a&*sEc_j616I2kG5)xje;*+98&u#J)NN-bS!swy4LC$gmLsdj9G18H) zmY<t0>@T~O3YwtkIgXa~Jj{7aNzeMPiI<U|oHN8J%~TyKDk}^+B@~|Gaa5DNBh%_N z77>$X(2K%I>R7UzLu9?U@w(&62|gfSU2kR~iq426id-*+l8u@S9I8YeuW)_YT&RrN za%lmueSxEy5vHXO(|Pi7h`5^D7`8=7R|s{pu}jM)v5Bb~*SVe8S8GEXJJkEI`zIzG zJYE{u>Li0Remu~OLDw;oNL38zDFU{9^qg*a<xImjl+*_UFW$A#To{9(Rjr>EOkvFe zLy$kcL{43_lZk-CmiQxzI`3b%?)xG$DJ?8`1{pLXGAg(}O4~d-CJd20)PQL)Rzxal z%or`<G*DAI%U6^jO_xO=yMrs$aP{b@XjUq3wNF1>6sutYGqMIqm(6+xspS>*I1Nf$ zxCMWqf_TD~PS+zYnsrzJy$tpMpFjee5ol{2j)c0XhfepUZomlFfIn<FYp*ekQ)TV} zfM8_OqSlFI4N>AW-Si7NnLQwFwDVj_fzWJ66d#Wf+KUe{9pHydMiG1C&1E}XH?Zg) zNQW9@ziVpBn1DzWfYgbCr$Q#v?mkhl(>f$ULq_+aV}mQfX4wQs;TDD;LVi-}5t~Jw zJ&KE05`|K6fele?kb?umOp$;GAPTk3@|4vLXSUZ3qD*q&#Jt=Casp8p<b0heSUW9o z*NP~c9y?f=g!TMt+c0mN|M_Fz4E%ZnSmGa2?&+h(MojjEI;^y$)}lY*1y68n&`Kf2 zSaWFCTj|adf}yFNI<FjMefZ*DEz|>paHF28+`h3ox}^}R<cXR_GoU`0q`DUfwZGtB z?`%EPg4w?kp+h}A^YMuZDmrF$Jb_R10+R@C*mO#kBUHb@5jTM7e%0Ew5b_HyA}c?~ zv={sngQ?Y{7SIOMfPJxKJG}T@Y|(q@YNh*|U7&)qZC=EkejJLuudor;^lp5;?b>EX zEWRo)%2pVx?Vw)8OiTEBSkP$l2|`U?zuAP)%^DhfmzYH06+gVWFB|R_n@w>4Je>Ew zWkeJ~CTJwHIKZ?qn^vfE6;+ER!m~`N=n~A0RtXf>usidkwaxt}RAIb-p^~SCmpIjM zRx`$H`6k6QR)v}QL0duQO50O;q?Q=l?^K;-s|pXLle8L2&Q!7@D63{o@>^XZWU&qQ zTBX*KumqI6)sZu8v!BrQ?@$d7bWlDQ&7y^7$MEd=0y|w3C2&hj=Da|Wg>6)CMu|gP zqIkRqE5vR9Nd<dXU<T|Z5!=NS%q#JvV#eaYTwZIckqa@MyimCJEM3b8A(+WZ%z|g# ztP#ZkNe20;T}vT~)jWS&qTo!SD_Ee}Q3T$kZzhTXQYRqm<gzO0sr}mNiYVBZJWiAo zY%@tjk(tGLvKMtP&04NXLzG?%y-k!@GTK0E)S*O_;c9#aw^!=o1w>id>MNq0kRpCY zK%mFHV)u&cEhE4p)h-(k{Kr)Uz;utA8boej$7LQv@-QqmoonbnW9gsasHoov)-0-R z#hctce8`Hx(`8Vj6;n^SubZopmEE33fq#R{Ap(!r9LETbF!>Q6Udd>haCp{vGKvxN zwn^<I)^eg&xh(A4mDq}(lw{`pux-`y%NnZ4DMEa(J2-#`!G34QDHd3Y+OT41Nh1Pg z#Bg``Qf5~&HZ|j1NEuiXW^>;3IhYXAC2T{%8_57gZMY?!)lk2@^%`Dk{fLZx!sF)L z?wr+I{Uh={(9pE4QH*`W|6@Y0`%53dRp(?~S+%~C14>f)R*Sf(%>g$q2aA!$;#y*F z%pe!Tj4|7HV$!3mQvHr||DQnV3HPbA(rz}1wsFZ;P*I?g6$a-(>$zkBgVQlqb`zL9 zPY0zN#WUs_nuG~0_`v!;I1aKj4HMk&9qC;AaN(YwipGlD7rL3e1dg>)_-TsmGnKzs z_n#E6sQ2*c3|F6eI0$>Ufu-0^{E$*6XBm%#q`9tH92M(Q2p@Y&1@>FjyQD;>9+Rc9 zVmio&j33U5)}lUwTs*v`qxRU?!zFz>lMDcHhJhiO=vaOjTnuGjk2qKtL`m4AcpnP( zwnX6wDIA*N3rC9tHY`1L92gnCVM6ZaPGaC5?Vzv%_FShQ*QsVt+j2{k)f_CyOp9fX zE^-G*Z0Uk1AY}#JUf4=EQ()`9Z}eR;2`qQ;6w4!#&g+f%qKLgpGE>u}5QV~<xL(L9 z;oP7wLI7X6D^z`}gjjQC&k6gPBCr(4WbL-uKorVP15vWLF7d(UPa%)D;it|9MGDQt zRzFL(&CGw{`gwW1$^b5<&@DstgfS~Th(B(Ha-WxHy$z*JPBO!XX123FGewa?<9^zZ zH>$PAZse4*>Z9Tt1aIZVHET=a@nLo{nU)`3&~#r70(0Wf<!DJc9aVNJ`{JVEjiWTn z+>^}M5?i5Kk$QnuT%B4qW=a><&DwE^aPZiaVx2N(2M6wQ9ZATtGvUa9Fquc?SPonf za?BXAIRVv!Ps|R_aY&fHE&f9mZgq6VQY^R!-i%!H+w1;0R;z^QZDar=^KhARyDyXJ zQVtD{m)ck&EU?H3{693VX}pCMW24gyRZ4nO(`1TebE{10#@UPV0zbh_;n=h|IUTu+ z9mBdT`c4G)58xeGy4ZLM^I6P+1;~+UA)lIXKU+D}l{B~Z3Pk0RNfT*oB@23oJM)=R zyg5#Bd&U$G)=hXxezcT>jwW&ZYD^Q`!;)p=Oqs!m7P7v?TZm~m)i0OL^Tz8*Gx$_= z{_dr9dqJCNkW~588Q70bSiW5Myrs5K2CpX}*Osx1&P(iS^ahrFvn!j5aQb(zB&86Z zGUB8iOo1gz!A`{-w<8gA+XDa1u*@Y(oEorxbO{rvYegkXt-YBDHa9l7rx{As^q16T z1Ag*)vK(1zug}(rSvXy%3xzl|yBZIYvSYJYmMorSSVwEyx0EPBvBL(BNEGDDJrb^F zimwAfSn4|D+!c0$%{rn*$T;>;1MSl2n`BNuUeo2bCmW)*mSNFF%~{_Eg=NFKZ<{Mw zn$6SPPF`6!mC}g1SC}bW7N*TiSxouMd0mJ?<Y6OUWh9sIn!w6prkGaF-J$md78S4q z?Cp9~FU>T?Ip{fnL(X*>!q7!%_6^Sjew6`?D$$gtIeApCiWYQlRpGL_!d}VwZtKdx zez7i#%l^dnMUYEsCK&J(d3mR1*M4>iQAb+aQ@1BOh@kRq^DbEQeIjujzDyS#cqWqt zY{wb<K(bRW^0~&Opbk7+XCQ`B83Jpk-41PS*PCH!ToA$CS0z^4{0uiujgt1k;!;y3 zQNAx$l&_a5*twB6lO}!zi)N`>rg!a;u3?Ywd5%XDzaBTK@pkU6IB8AymJe6VxrG2$ zXW5VvnA)!^_Ucrm*y3ZzZN?Udu#(@`Zc0-wP=9Xpam-=>ca<qcZ{%uDlKO#+gb=@E z6x6nRt?3T_Tl(c{c6x8{rh3C>MTKhn)yz^Z{AQfk1R<e>(#qn(gPm%#n&6kTM;;!w z;$#+Nf;t}aCBgRHiak>Gp$A0P(_D*DH_d`VzglyJ8stlj53}}#*^&VdkbO0Lg9ioT z8g4g|tlb+KiPA!m=aVujgoxs3wS24}(5h2GJ=7P?rg(V1j)k7xt)t;BDR<d>bXCfH zo{**AV{f!jw{{!R#rNAc*Q!|rWF=YGEX3gjm13}|RcO&^4Z2E1(RqU?*)SFtT$kd@ zepm(K#!4q+cu60&Ek|)d2FNl3vcOLiCd(dg5hVgri_hO~7KzdT<U}bt*bSnX_+l5B zu9(fQwH*171)`C_ohW|$>y;_cA*~Ka$p>2^tJxBv5{Ydj4T>L39&39(wG3VB7Zes& z^=39Y<*Uq?WFu?MR99^X4(P!N0;;@?Dd?@DTgJV;FufwPh!#rD2d2SE7g3PF`Aphl z!wu*Jw8w|;!?m%;EJQO{XGxyn_!MJC19uF-BHy<Ec5=6dgdsJ?j;aE&lXQIv^cP|g z;=|5)aP~>pv=}{S+sa)j-iMx46m&n>*E0yb`nP+x)J2L%t!}2ElQ#6}S}f98hiE0H z&Au0zrAturiqXEN>uQ=jdcEM=m0dbg5E&1xRTb4cOIDa?D~fovc;ePQ-sWfF6MhsR zoPgwki6##*$CkBQEeQ|htld-&OprS6O2856t_0Nq;$UXnSPNBS)mJ@|irsS#=?|J5 zI;kU;*yxa8ASokfg}243+i+!Fhv&eXrd@Eh3h(9M!Ye!jgFH83fdXVQcV=4X&J)GI zFVLODUG~b&gui`RZ4%K<zo-qD-UT-6HaHTZXIz%!V-u3PwNLCgB8)s(kiibju=m@B zaRoC{YP^x3;|KWV;SJP>e6ByFnDTFruu5~PxoUf=wL(wBvlw@RbeXvYPKchDd@TS= z*24vM_f=TB9(}Z0F$k4%s~ol~qzSus>=+wQIDgjrbv)ZPXPuta<Tm$#>IieX>p?Om zz~<B8UIC(jfN&ewBWAWy_VjJl{OtO7M)F!_7*V`RV0po~YZ|Cl49QNzI>KQ>b8=k~ zB{yr{t_@M@7JYnpQu5k_UPP3W001BWNkl<ZtFVw4A1Xw#Ahz3Dt4@K|;oCh?w)kOU zMxxXg7DSQDnUdE11%Alv7AwAh49~%%da)we5oiHrO{ZzJVvh*s5uW?CS!>p`9<yFn z!$zX$z7nr3zu`<2ww8W1X9|0QhP97}NIiK2uT*MpU#~p}m_btw`^V-#nzuY1WYu@D z^0`a0ne-2rhq^joAvVExnTU=<M-h>#n};NP*o<QJcTKlfGe**+^5Lajlv9?gLmh1` zc#{*{aK&<2Zb;Y*CwLq@qiO^1)VkSx&>qtj-;Jxu&~p);s(ge3qc*3V)I8P&48${e zCMauFX-<Zuq!EG*d}PX6W@ckOMK9WPPNj;^GT&s>!`FfWI%nHK?fgq}3WJdcBQ#)= zf~s@I9Yw`ze2eQf;$@YK@c&cyZd;DzI+h?drKoedXU+fr>U5=xm<Qsr0n$wJ@QA8v zTbUm2k{OKzKoECy)wf*Q7rQ=HJqEa*-K|$+hq2{5g`n%?!d7<qqDv)+IY`7LB(rO$ zqn2kcE-PsoXN<O~*P{CHcmZ!&6wV0K9@E-F0UOR_-cpvAOui3#kMSF9I$!wsO5om* z)ZLT)G4`z1=hfp|!jb{9r+$0u{qX2+Wi|)ten&~GRVU)B)tEWhb?UHdy`u)~#aAy9 zA8)EgHL?fIVb=NVVtuT7zwUvcQru$grR)`qf?*-nqu#K?Czh<+u*dmS(Y8aqA?1jX zeJEat)@4RDY3`r7FQgd)l%Abc!#NVz?;%C#hM28Xq@W^Yo{-|&Z~u^qKR~pE>7x(u z3fGL3egE#;As{oiuL2z();fx7oOTM=ooYAV;Cfy^c(bn?QXFNgM6=$!aUWB*VSf)P zZc1n`$#1Waa=laZE%b<q>Aq8V&Mh4p*Tdeh3tkRBSO`z)LE~RINrb70k+RnE*hT1y zlzmvOYsdCg+t;=hRVAn8a1CQpJj@L%{wvo{i(qL8UrYK?Z;*SG@8e2OY8k8k)%Ak- zHSgyzwyj&XT)V2uQ#{(mbtlned!jP|#t7%Hv@Y!`uJDw0>>??vwY@?Xi{gPAS8hoU zOFwz|?8}s0uXFC8E}pl*v~Z`abi=K#0YX^snS~bcf?>Y4v)A*4iM{Gh`hZ<kF3*<x zeY!QHQku?*q_+bD=hOyn>>jP-rOc;nkG{tAWUEg#jUY$o{{bYwbN!+C&$|~KlT9kQ z>fuw`K8%O*eM9l-x~m@NbOJtW%ZY$?v!tsvxC!5L69WC_Vwbt8sUu7*IlbIIzV?J} ziO~=ZV;b3Aawpp-xheiCC0tbCy1Z`LYTVOBRQ~Gxw%BCw+65d^6mr*HZqnblUhY>U z1yTd`rHX~fbXI8{o2ZN}wR=HGKP+J^iVrh|)$g-&Oxr$-?nl$1=KhdU0e>;=6+X8d zq@{5VbSRZareYG&R|z?+vD8>KFJWzm<(io3L&&NvB*bfgMQLyj4zCqu3h3gISp_~W zkj64=fQUPJtW7*TVK2f9eZ6485!_pam<T^e3S0V<V~{`!7%3j4_eB&EBXj5h3-Rl9 zglj3d_5{}k1Xp;%)!Zv5MH#<9%1gkSQbmdpFoMq|Qo!%!23oCNajTh}xYn4bMOz>O zYb>URWBxmX2@#)HI{jId<m7=At<cN;r5W=J=)<QE&gqF-G|ITPRq~P<o4KcQvH4ym zgMp&Y^M2WoQphHXLAY9lPmmIN)V2ZhW>!SogAuW^Bju6PFFU1abQ}X5bMr=Gixs18 zK+$Stv-zaGS$IE6Sq?oI0f5=jtwdQf9=!vjh*gB)$){hJ-y2aaZ+40|JH16pN)>CH zKy8Kte1ha!5-E`Bc^iwm#N*e3lBZ&dPB5<kleGW$-cbKL*UuDSQ;A%x^%k(I;q|h> zyb_@sOuy@({i-z{x0gq@x`Dl9pdMwGz5j;`u07?lY9==^a1<uD{vYRzH5CbWWgcQW z0c2miwHggso%PS2pw?VB<axGd!S9YW6iu}x#X5}@MIyp_EtCw==E%oSzo#MEUme5| zLKjxWc%%KJDgyd<K}Q-gS(U%Za2A!hss#(eORd_x%P~aw%@XWfqR7PI#dPz;5dj53 zByG_u(guKX;<I8)M4rUUmWs0znC%X?g~5GG3dsB30C3~F{Ug_$Zqh(UoUy|tclftg zdPl+t>7-Nj@aevD{T1M?uG$BSlE3ttn~TrHOeSpaJI?*>75G#Kj5AkV1(rS3+0N7` zZX+A@v0C7yQsWw84MNZEU_clb%U8S7U+A`3v+Iyy9w>#ft^vZwM}Fn;hV-Gjs~YtI zR%`RuRSHjQ-~v=8vFn>{5eL}K^<I0g*R(_kledPXxqzahi-ekziZiQ0H;d@-%uk>8 z(wcNsYM5@t6?&<2)AGj5+bCkIx&oY2qLv#LssNsw^878AAcQ$=|AiPDAs<sU6;3~d z!x_Tba-b}rL@R=lf;aMA%Nfp7(y`44O^8PU+N1;Hv7r)~Hv?S(LquIoWvZcxpe4lV zo-(Tn2AdDikRqe5Wu%NAYCjtkSbyj`08$kxRkbKg7bm0?f}~%<&Ym^NMSZruF}X_Z zaUrA3hiwNST$}W|SO7eBEXrZNRHw)wxiMzzhnYNRHDPn~CV*0RO2$QdPn}##?4zNA zA#<gL5mIQ?k;X}r*?t+hWC^XgX_Dc|Yy_4_aYF#pj}lA*Xmgv-=)Y)1O4hFLNO8Ji z?UA+>hiY#~>3o}ais2=Z(gOoC7{OZ~l~qidAqw3p>5W`ff?2Us<|<nNxI(LKU$eWo zhB>SkX{3ZKrlf+Y(TpwaYn5gsJoyP#^&m`KA%zM$Iu*jOZwz0Jw^-T9keov|^gG80 z8C0D&>Rh&=ICvUT0to*D6=1(Y$XIcu-t@vnFXdk2Tcwc;)e_fVQ=qDHQNvvn!6t2= zU$(^u*FCg*pW{yLsL_6Nk<R!n>3uEdv#Y`Mt$Lv<jn#(YmV@(R+oX^OWUtzRbYzu9 zm@dt*aTjSTlHxz%giB^A4&z*gETZc0ucXH5A)Lk%s&QdMTV(g;E0ESrujQ(%*S%)b zsY9GaBCT5%2q+0Mwan?(AC=VsXV@X?=TD1r=DN66u{I^1aQ&&eyM?A-LGj*E<q58r z-~HVSa0VX=9vY=C>{vv!7&Heky*bZu*ett8Vdm{#6tI^<?jAevafG>&AD=5fpL2tG zDtyBYH@BW-tX#&SuSgGib_Evz-L8iPHxaCyVB#joRxtsw1VXoisKsKRW@<|*?5@&# zP%D8UHetH|J`0dOKy1#5_Ou_p1>m_s&2Zp+JL$6A6>G1HJFow*T<t7szgLEm+_Q~9 zc#sfcl!hk>63(_0%%hH$_XU8<8K?efNSINp(DAG}cfDjs8_8@3GW}9aH~df-VNPf& zBy9&tjW-JE)9XuB8Ty?-7B4MfKT;5IMLC;tC|3(1q$q!7$CLRUaxLO34JDJk5j5u* zd_M?#$lQ(;{_DgQuaJ@pAqrQjgOHGqF3Pog%H^e}Ve5;b8%Z_%o}@pPeAh?mq~4HH zWJOj{d@YO)2gkWeM1fc{f9xBFAKO!T*I;`&uH(YjW;vEA3Uga)pA$%LP;H09j%zv} zcKm9k>av`hoznK#(E|bYEL77856C;E$q$T_cf{EvA$h{5wIuvdzS8Xmp>&TxiXLgZ za?~;`iDTQ;0|<E#9Ax0S5M_vmL5=qiPMi8e`Rv=*&lTW(*X6}0@Zq_eF+KlrJKXui z+g@5l7+j+*@qAO+6)Q#naX=h4zK@a%ro+yR)2Xs@{;TAN&D!ptjxkE??l#SuJXxha z@-%Ah&@LmD<kSm{bQ*tqm94b;^}4oO_w0TwfP!?YG;&R2$bq_8nr@(eP{pcMIsr5f zupA(xp*S7kN-t2JOlDoG)}VHO0Xl$m_IK0LNK${VL$GXE{{F5A|3NP3@%;rC?mQ<r zhYYHI5|Wa~%g|(!<}|K=eZK%YWA7!WtH-aua>liBtX-D89%i2vJ9sO>78sshP!8wo z5c(1g@&OdL#CHAzIk7sErmeay;*ztT7L?E_PZ_&IU|@T+Zq*LMx;W9xFU5jIzFngH zqiZ<+osA+2$qe#~raTdrepL#nOP#G%E{z+G0Ox?Wz1wF>T~xwto)2ghK}`}XMRDL! zkx|*0bQ`NO<pXO>Og-k7+iqVi<a)8?9P&)yEICG|S)P)eV=m>#%-N-e)36yO>u$6x zJH(F4YotiXEGMLdT4L^%DKavv-L0oSwZWUzK{N%+ML+AXYY++r*S3Y!jMYJ<2lb;a zM8c-FX;!(G1(P5K9>IYYC4zFQ?h#ckBu?`&!~F0lW%iLuZmz<v2mO9Riu5v0YUh`c z0SGBoZR=}+VJT$6$whUd(vtQ1GNc@bjY3VM?)`U2=@hsVn3rEt4yjfD_J|ZXQl?~_ zIZLgCl#c5NApue5hdTv*{&L<a6*v^&pp|{S*(vLyRQ8S(_gZ6!%;*goeMK*k(sxR{ zj(18+E2y$3;wwgqS2WDcLfkU_?I(7@NKr=0X{S&*3DstN0W$8N>_HJ3;R4}d*gtgr zSOIp09uYrEIa{vXed6`4qo%Ls{LF#;iwdN5lbOttLvQlg0eic`xfR(#xv_nze4EA% z88TV2+tgRSTJ_OP{cFq8>QKs=0ID;>GBPSTNV_?g*B}}AX5J^3Ze85=T;o>JH-pFH zZt=jv*nrCk?EjOjt=R%CQe{<Io3XsLZ8MU6LOk;iH<z~UKfuad_hp_yy5ljHSqY8i zz+nUJ`Fx{husH%R%^aFkE3R3k=BX!}(%%Xad4F92^WDYTORm_!3OnqL!d&h1niT5( z@Mxqh1(JkEKHt2`Z>D_X3U0^MbSwlNqT4D=+hUGUxy8k$$uR58Xg(S1fs)wI+ktZ^ z3hNDA?XGNw7rp3qw#w?l1=MI%2a8LJW!)DKU5?2W5Sl-WZYpM|WYb5yCr(*M>T}v- z-mkCk?#U>G!=kVo+Pn@87}Ew!06SZ7X$-Sgo|oJJG!mqxdbTTG7e<C%A8Q}(LL?=* zLF=$Bx_E!k1<+XDQ9P*8bQbd07qp|8Rh=f<h9W`p2>}||z76rTm@PbMiy;s#BrfSq zL^u+7|E^CgEB(YZMV_XL$Td<h>QfxNdWCBjh;{o`wc>aE%1MU%av<GC{!OHmh3rV- zk~}@`)NK<PcH0c&eZmwh+9f}a4}(M<6q_xD`#EK%RjUo&$`MO&Zz|C_y!bgsLN?Ju zZ7p5TIUwa!YKBcbag7pe_aRawl7VT1+~N92naPDNks@+YCA$$A@08p=6vOoSPFc{S z!r%?pmIOZh01lC-o?Us7$?v#Rc8;NYMOZGYR`h(${O6X{-0ce*$>>KQ6#v)-QbgOK zR+KQs63ks3*o!`Hn%SRIiGS7yI0Nl`RVDE1;M_OEd0SWhX%V(`!0+rYkyfra%0Y@Z zt6NTS;T+}R10np2>7q`ujEN$SN}4H(-3i5fNO@^~Z}9?_XqTM}StuhC+M$iY2IIIg z+F^P67rVgv1A}V7_+VS9Se^-Td~2B$GAM;c6OyUFl&Owk*wUE^A2DAuYDIx`r3%qt zEQJ>7H=X49z|gAK=I>w%bLGkaNJ(6UX)qx6Dr!fx_04O<k9u$Jp<>0!dbHtg3P84r z)oI=P)9$|e;M$d<@2S2SAgS?Z%xRCvh^|P}tIegPk0cB+C7@(8FnH{zlN8+W`i7Zy z%U#y{qxnWdyAw}B|KQyfTYA6wWY<9wW4_BdOlcd(hnV)MQKz)}%J+s9^K@xs+n<*d zTq60>LENejo%U8R94-66rw_kJ>vP%SsQQR^BV@%m|JEk^3E2}3etK$e(t`!C9ZLrr zH@>hM#xDnxS$5khkDLRx=ym++gW(@}#`e0wj=7`2$Fk<ppTNsG^4VSLx>^fP3)!zz zNL8QDaV;$3Cynp%M_WAVF(8d!)Wmw0JBb|}#D}$$2O(u&&JBhC22zf@;}ZhoH}-Fl zOTKnGohgJLY;nB4#Y`M%>dny!OliGmr0fv5F}1d@*qph=46a9#agGjBL|{b~laD7I z@C~HkxUX6A{Vq~YLd@a8-=MCmcYV&oN!TmD9ACjrRPR|zU(2<$c7>OgfzNZpHrt!? zJ7j`ZdbcK5^O|lKat+LD>T<#5SSM<~?~h+U^#GURF-{)EBiJFki2?^s6-M^0WKmIG z-&`8r)V}kH`F-FwJ3AJ(Nrym&@@RhDKILAa=48Dp0WI|b`wQIo`0CiC7o&X~3SIOh zwt8F?cWqj?o|K&Y1eIOGK08dQxv5gT27{%p;$W4Eg@AtFcxedP++a56pi(+TarVv{ zMkQ*i31u@E4eJwI)ONbnc2VnHsw#ua?zn?<GGp!e7&L)*`{M06^Iv^cvx@zDQT<Az z!k$P;cPCTJ$?|c{0Bk^$zj(LLKM88}X1{$M`CM;C-WK@#NJ!;0$(tijmz8L=;`yEX z^5wO&svm6w|NF_}N&~x`iFEYeKB)K@ZYaO*?_9%N=-plk?|SNrE*yX7`eec9yIVdX zeE|dyB_n1V=hP5I*>5R1el<wNcRZ!!o@~g^7tXLqo@I9l;;pBmUWl;v@5qRT;Lz^V zP8~CoUf*kL7E{uXNdGkhZMJ2C7IL`k$g&DB`~qJK{p|F{!iL$Ys5S&oDKT!<X85bV z+u?_DJuK<>bD@P2#JH`O>*DU$&P-f3=(jO%i~#sD&&|VmoDT(XUM}S7TF_jc`6Er# zn-Aebj1+Zu&br~0WShB;`=uVTQFl-he0mtvzj7n`+JBIuCp)!|f@mi;uou9iszQ|4 zWbowG*K`|1*xq-Mf{R$<I>Ga^Ck1Seoa#y`Q{Z8zc+b?J)b^HOe#a?I`uS#y!3uwZ zB3(hIX-bNw*|pGq#jYeX+q}<8@PbYIX$+2>->-Y5lq13i$L6&(A1Q^YG4vX<{ae?M z6krax6_x}w4`wBfy*fUvTkRuZU^!WJF3oYJ{V+aFi>lo!IUMMz=)|)<Dx1us{76Vp ztigoaIto+0MOk)ruhS}%IYgH3NsH<dU5PFruUMR^J)}Ao$8SIC0NiJ&kT8qRgy@u} z3Z^XtEE{{PS4E6$PG`afA4WsZ>RIEHzO3ScxaJ35cG1e-_~vo}jRPk`^s6D_p?fH~ zs^gT4WnVEF17OaF2W{&yc+O?%uBVjMhzd`g7DA<M0XZmgHz&;RUss9*E$3U#;Urp- zI3bweL#$rO`9bb3OK*lQ7X%u}QDIvwBK$D-I>|rD8e{v)2F+))HCi>M_Uq))jc@A5 z3{2ArhjH5Ys^C59u>(3MQ1)V0|C;QRk4?0pW}}>vl#phKGrDVFLW!feGTGEU=vA)^ z=;EK`@VTYBC2|?T2B01?xWDKc9oI{HH}^J)Z#^5=RXys3-qwkf2ZNQUJ%PE37%&k; zhagftYwcgl85>rW@$#B?Y(Xi{wofPM@A%}Q<vWin#Y_+eO^+|7jAh@Tm1NE@otNLL zBjvCVsgBlKS}q%|+yX(^F*v9dif`0>c6w;#u~n}S94^FKJ*nb-KF4b`VQ71hPagLl zX2@lPQ$`XgcPQNkMT70(7LP05=kv*fZ-KyED3C%<)X3#lKY!lul=BTbhn#ev^<^|9 zV}Zrtb3h6m4e?d{Tmnqi7qB)RcJuI&=4rGT^S6<5;~vD>NF+B%kzLDjx4|-PTysmi z>Xz>}M&GZ~d@k!nosp6@om38EUqn(gI)Q0)Xd7M({M}mi>k_tSq)_qQs|MywOVwkg z;n!L^;Ut0qiCOoo_^(_)?*nWyR_+Q{wrWhLNXDNrWwGSR+3O$y%Pl2&<Ap7+do!qt zo>v~)rO_~U$@Wz{F1i7>y)bmj?%LY4k%KptK^jvonoPuY7PVq)UwgP*6h9{Yr7M`^ zc!tuA4wGfNPB1gWR;cl*>gL|Cl_no!m!|2!%+SKmp4tdp4UnSw6ZER!2{16nfaRLn ztkeEf%KT`&Ju6N{4R9ruxIw=DTLRws&ov~6pyn&8yp{u9G?Mx|wRuk0JLUE_YGs+i zwgd}JlSpJ+kZx1$IZnidxp>j$V_+5^p-EI_!xbgzXx-{OJ8fE5YtPTMYGNc1pX?V* zE1K)qsfQ*->zL8pP@xP9z0w;J#Q0QnB@&F2u~!0Q2&iZ8U#=PZgGUX3Z_~VI7p4#Q z9y$10XPBU^X46S%@A_%5lkiodmHl6Qr^mXyvkTo{Cmk<KB^~d7)koUt1IB83G*`t< zP^Q;3B1tHld_+F#Qj*8%rCSbj`Nj3veWBpyAKS3%?S%^|@#(9y3co>X|0iLsm|mLZ zAwF!lf9w&qqfia)Y&RBMiHTkc=zwjmeB%w7F{=?I8XZL^-svf+d*WgY>zd~wGUSF{ zTT$N&ARMoZ!mVX>co2})L!;}A*RtA?BHUZ+IG?Mvu%^8ad*5y48%QzJVu<y4rBvJJ zw(EYZW*{Rxx>YT9eU0o$5w0So@~5J18FN?(x-rA(m5nn}yyS(I{#ncX9i)gOMNUX5 zO=S-k=da%H6sei&H?sxXX!`r^76K(l?$xfplFf8m%iO9S#;zBtAUJcj9Zpn2?2_QG zu7Yddpze^kM@sVWc&Xb}^Nmhmd?#+0?ccioKpUj=*QPK?c|dVj5ur4nJ&8e@s#24> zJ_Sl+8cO|3NZW!3Jlv0Tt5O7Gr@z@}eIe9*w1^g+Ayq@%3Z6<;{Q78IG8#jvit&~( z_t~X|h*cm1c+J>1LPv*(gl$5mieR{zv2pqQ69ifG`V{*yf`b-up_0Lse2q+QG#u`F zPkV8vfy?XCZo}V}sz%Ff5c@@n>bFPyHnH&kwu{mYLNPmh%@-<I$}Qm?r8t`_EOc;w zxD(EM?dUNrznqPDB_!ke>T$Uj52Vg~yrIB^Bl@;hZkG>pz{R(&?<A{#e|$7vgLtEs z8q57%=4n4v)wbA`tA%VsoeAw@?%FUg(6<4ftgdi+O>}<YmhznAp7MaA=y7bpc&HTD zQBL3PhKF4v<WF#MbG(9+D%*x+s9qWRm<b*|=W0N+Vp<_1)_cH9))PWUn@^oWw~6o! zu|KFpI9)q!F1wtOYLxhP>%igiw<JmJw~c;t{@tpuwiG1>!iM+0kbvaa?(xzXL1`z) zvNdu^oBQr@+Z&xX0;2$W(z-|xKhkiVASCTvAjN;1*+6FPw)Ka`C$~EV8%<*JmrR*- zzC}UcjubD)*g#qx+8fAdkIg$03W5)l>fO%W2`uS+W3pT|`bc0bf-)pqXr50`c`r18 z1csRT9_MppUp`=-HtoTkT?BPGQ!Rer-N50c+QfNRpKYC6KgV~ZFh=T5;lMVJ7o)eA zow7+SjHw8)8=cXbjvcX>7fAV=itrDMVA;P~2}WgAb=Q5rn7t@=rTMkG<Qg%ms|hNy zd=dN=;S;9lF82b37|Cb!rV>k2urgYhormlkjXP`9KE=cqM>X&Alf-p*fb-j0R-s!2 zRjBI)he5JbiZ*0SO-Wy%Ou$OH8m{>DWqRgwWx>oLqOX`nmXZo?z_H2nC1jQL9Z{79 z<hr+eOrC|cU2p*{9a<VM7&Ti=#mxq%9jcm*kSYq1Bb0PDC$N}mLW~N$Ra_oWe7UO) z6_&9RM4U108Z*-x#&^h1?aMt(>aR6)`Sul?6$yk)8Uu+UTzU8?N2gLJ(wyfvVqnfg zWv@TbW?3RH&id5x6WRm2fcG6<pUM#p9K(X_&1F>0|DBO!Ds==@v-7wpRUUFeW7b3t zt*^SE^bbs#yWYYHFuNp|8mdORMG=BF!KTWtRN~&kR&`nJE~k2+4}h`gJ9iV6Ke$2- zxL9#We!aH@f4h7LYPtd<`eulT%0$0;T^uX8OEzmgBgXL)GJ^DQGPqn+IxRnsPKlK8 z029QiPqyhTEyAC!XfhP4SIYEuXe$?>ma>*TcRJ>CX5um1QBMb@Z=(Wsi{W%J5p;8o zKs{q6g=V`GuR2bcLRhZlqQ}kyLI&+fp>JCVR($1$zHmgYWEEw8Q}zE0f-u=!#C@9@ zRGQ~sgRRezNC<m9s(?>6k;)bf@f5-tICE*akcMc^Pabt*(dJZEjxIFH5kq7UFS^=X zHd`pT+IiedoR}Qx-ZrEjZdyYs09$^=WBwcwe6F*qYKd!qsScz=a!KX^`LI1YcsqmI zhGn5M?#Ytr>yfF66sZLE4k^yxD<vRNObZD*$tiuhQ{=>ok2{6q<h>k#i7GRcBw9;6 z;!7(f)`w)M3r9*H*;l}}_U;P%aL%?+rphXqqarfg*>0H20?zQLJNQ~cIw3;_km*~) zYls3A@6A!)_j1HfuOH?BmqX2^QeBI$!Om_8xDJ%_RyZ1F0qDCzq5fhf#Y-<yRCDrJ z+@=zy>ZSbPQCe1s#cC7%%F8YF`>=v5?YCKFd{LWFkuS4TJQ9$LGQ10ldqtTcA@6F9 z0&VXKy*l)Z4sMn&mIgD%P|{ZT_Oup8STg$}BK%NIi9y6q>riAYVoE~_Rn@_#kn7F# z%D%c8N_z^<q~3(_q1XbPm_r&WbaQ`Q`jg$@=JBT*Hjh%amzq-DM<<k#FW&n<MElK4 zOWz~9(oR#-yidBUij0h!E@|O?i}&X)U8<Ruo@V@`9=-8_vtRcZm;FXJ?>E*zH4~2+ zNWmu5`9pa;JQXTY0>t(m=;55)6~Q>`-^+^dC!hF!FIIa5b+VI<M|VV&OzC#Mo7up- zzQxjcjBjid0=?N3#ElGZm$|>`hGATNrRArprY6r4B;U4GAIT|oLzC;kyNgCQfAv0} ztJ&U5IeaYg{UE!7`~UzT07*naRGz(D?z}?V?t*UZm-IBk)qHNgy+=y?7cdWfrakx# zq)10ffTcB4X%D_dO8smzr_plQw$x?lTckX;$?QF`P73g0EjLIRHPwjtKsh3Iq>M^n zO?|D@n4vTb2R6RMc01}PQpY_0xfev(t-;m&k?ozD3U@>2V?zoljeUgQMM|3v+NW(l zDiOwakaAo|qL`6#A4Pwbp)Oa~?`g)hqRg|`jTXY!u`g`fDTNi^&g6USOSSFswo@Pi zWeor-`l@Sb@L$)Ik~PziqNknm$D$m676Q$iD`cqBoTTwYX##igpQT?Iro6Zm;=RSg z^%KS+_*;3P8Ymne^1mdCxPIfRqkl-cRljUW%D3hos~qL3A|XMs>i8#y#D4DBDlIqU zQl+YY&?y*-M!A(k{=2`I<2LmG9%#XXHXn()E*HS@y$FTM3WPQ{YFQRLSMv*P(8^fm zyX(C1IcS{=Zpl;~RC4hYnf0+~d@bfRtsrA7>>thLF&lDG9-mF&ER_8yW$}+*9*6FG zuv<*(M)QaE!1{Hs7E+aL{(C<IIp|WS*eofjgICx6F>{>CdqnOH$>Ve8izjBXN3Ug; zbxMHe()%Ge(x57Gc;UXJO5TTrrPD(v&}{(=mjc|nZGc%;R;*}~BTlz;|0!mDZ7aJ+ z=uSBlp8vrvMVJCpdcHCj9NklKu|icnhh21zfAa|62G{<lwPmX2TA)sw)|=UP+e}%W zE~wG^t&3K<6-UqAEl=-yavOVnGPgFitV`U?=kv8RARud2VGzV_1m7myZ%9!V7Ml%y zLrT)<eM$41Z^IE68Qp^t4*As`Ko>}f6U~vrQZGmx>nxYZRj+r-R(+Sh@(LT_q#2YY zd!sExA}+5*<)9*pFUldHa*gZjD%K+8xGSP_9W4-@Eme_w{5betEeRJ$*_6f-&$m8q zNV!<booF1i7aOGJ+slnEdVv(-of6bFb#>z`uCvox-p=;G`T0S&)AgOwBv`(#n6}6z zQhXk|Q`haTR}kqoAn=1^9kx;t&84N*D?zwyUqg!jRCjl-f`Ti5TV-Qn$F=+!nf0e3 z&}!-MeKr=Zq(Y&DDyuVYY0@5?=7P~=ZC(>hG(**nr&NPi=2PZ(dghembT7hAm80X% z@Q)nAo)O^Lt~O&$S0dk}9C(LKEHEz?HAG*r2I<V?h}jHLEH7DNv`11qm@_{G0+Bg6 z?56AqDwAWMoic1=%E|QC`!sJ@Ar$8DSIhD-hg(WqG`UovlX09{HK_!4JP3gN{|K)S zOIFJf7S$)9;ahjWXzJPBN`n68qQH5H=Eju+HAt1V;=-{N`fn<I=dQ;ss~gpw{a<&T zDw&tB`>#P!tiPrwJTOTcbJyu4?JRjtI<g}QrSz9t4;~!qq`=tL8<Ed-t;BUE*34qg zlP(6hFqFXCn3w?7YSR!XeBsXMl72O^P}++%;nt5n_1#f0HV=;SmOY!Sscez-qTl*~ z&tG-xXW1eZa-NGp%RA$%g~ezKKCLt&vU;cAsSc#a`ozwKx9-LuhI#xpSfKW=TmXXg z)|(>3>U|$7>hRSf>*|;xSK%d*LmOfaj)EEkeW!NNSNp8mw<$qV>dzHYx#sh+1ypd8 zMci}KY)@y|r?b8KD&`EEn0m!*KiBq^*j6q@p?Dhc%ZoJm)>`J`T)vtu{esJ=g&;H3 zs#N>o#tU&8>%pS?TDT_G1w$+!-h6e9G9gouO?h}#q5ISFEmB+|!7B?~=ZSNS$NCg0 zZ@$g6q4_<ebT#jYlorkY2~zIYGB3YP1~{rVcoX(=j}$Q;Vzr|dQnXb9>Zfjb@9`@- za<7)Dw2))H@iIK`lnbUB(6i*gxvA(k)OBQ<S11F`F1Czsd4zD#>bJ(z=i~+TluOk} zHJS#Z*e2Zp_vf#lg+NPDd$b7-k<pn_Yc1w4;xbTWaOtM8_ICDLGLP*2O-0I(+D5VP z(aT(LsmVEK5vng02YOF16zbJu{-8!v+3o{BYT4J5LaZWRNH?!rJeN-+W2&s$g<8_@ zr0aDi5Yxo0PjFU@HHjR@ysu-hX=J=3Me~*0GFG7(ogxB^<Vp@Acr118znh@D*758} z2((nq9ZWS{<OKRSDcEj-0#$fW>B>awzs0IB^0su!`ii^((oQBt%C4Wp7xzxj4PM`E zUvzQtM!R5SWURrk-z_YGYL%>~=Tu85$#``wv(<!D(lotGH4CUH4nfvO?Kf)(IR?}8 zaB<O&_0zhlQ-S~LelJz}Hr^Pn%GGC8W^BCza$ktC-D064`dpeWRA&kKwv>3Q)}N|s zA<~LXOB9aPVlNi(yJ64m+M-pq$#AS&fgKWa>=RCLl-_|=aON!e=m&+?b<Q+;c;B-A zq7Rlkf<e@%l$e$arrVSB-x_Cn7ESR4s_e$8E7yvYXT`lJV9ANh4CmRxBmi6tyXWi( zsf!X>%`t7bTYradShKgoyMTz9Ie&YFvQK6UDkR3&9_PGCrPwKwCHrGcBeg$GFN)9t zugDHXgWVT$8Mc68L^zAuC#^LLYaeID#iFC|@{MD>&Q>5Y>)!NMBxy%)raws6`mR)k z-8U1G{ZWcuR{d8#Zp2vV?JTQYB83FnLkUGxy?u+`6WSEc#DF~=eH(WD7f9&_9X=Gd z2S1uE%g*JcWg8Uzsv||!bCOMNd|bjdNV;~+6g$R_(N*vmfq6RiM<3?^ginyd7gsJg zEhO2<l-`}bZNTGv?vZjbdns?v0K3R`h@7nJDJK{3YD|e*?v*p;T6+8w*Uvn_sm`pc zdo$IOpfduaK!)RUq<zt}4c;r$lJqN|QXbPj*O0=U;HCBf-^ejB9O2e=%^7*y4qLwG z3SBDJo@96G<{Xv=Sl_zoz-?0K9zIKUKFDe;OYK{of~Bhej7~!T8>Ksd2$cg1yhcua zjhzlQzl0aK486q9MJ{1fQY(VBeyi@Z`^4Kb5A^pFuZscIRI&58REA8uh+Xb-V^DoB zE6dlmmOUmp?MG!zM^D~iygJkyUh;OlKX<tv8CD^(=tzj938;u0*sUsy@<wZdeS9T^ z4%QnVZtXl3Po2cN{wM`kkivVAmD`ZzJ0=!hLE1sKn1|Fe7v#onh1<v5{$l8%7hxdw zh`dJ%UFYezKGCj!ybpiAyzYhIjT0y6V|s6oQqK$#8*gc_wcLXv`AlhuovMvm-@V+7 z2_a>Y6MI=DGMXob#Gb0RPi0vs56OE`v&80_Vy@7g{L=fd|6}myQGqEucSBzj#|Kdy zIz^VOkowL7lQ!nMpG}W9>pDH#!H)X#>f0;v<M94W>FM3v4#QGu&iyTfloFWqZnk<9 zl<A&KI=aH|{@E@cH(b-%pJ<PN>6idPmFt4!$Yq&5FNVK81iG~u)=v(Q$q^`5YJE7n z@uKz0D6f7?LN_}l81PZFJ{5VfjlWzHZS!){Z*&O%7WaO$uaRxT)lZ)zyKqQlOxZRI zTgWmTJo(dHOX|S+u2Q0+jau{@5Vd!tK$e4-{mGvqg+lK6W9s1)GeAK~N=Aq4D*5>e zDQ_P<;zi<Y3XhgAHRQT{i~9WmvTE`;^5IQ#`g1vZKlK3fc5$zrqy&4wP+Q*V)XAo- zA_XcebnLa9QnT78ns@WKDwR?T&kE<I3#yt6i}_HG%u8O#FPuCiW-X>_Ldn4-Ul(Y> z0|)y(``a}7F8j^N{q-zh*Su|NaztBLwfS}`<oq{dW?qn5D;dMfvLq5fG@}BFds4SO zK^3B+gRBsNqoYv0Z+j}p<<hB_TjRO!<sw9gd>l_T9{0Uy?Xm~UPOLFVlG0{)L8Dnj z$;sQYPM=>IIjuh)N~E!^PSTr_A6yWJ4j7QtbXt5{md-}NoR<m!y}-Y{M-!Lwqq%}M zXbhr^jK03Z4Cw7lH~fi6*C^vfet`OAEv)+<mX(#VcHTkX^N<gWDB;Vir%0QukA4@* z?jJ!bTJPz|4Qe+vmVfiA@1?x~8CLx`ILm>BX5Sa*>2noyY;v^}y|mB4D=mWg+Phec z96E_gg}O_Uxg<pWXn<L_Kp-;Vdlc)PuGMqxG#1{5CGUQep6(0BHntOPy7J&mSLER3 zTfc5=6hFSq$#WqCbsUl1wah1TvLdnVaxLmJDb{|RhNZ*IzO4p@)L?0Wmuq0bVbs{U z^*YK^1tH~~_*fRQALd-`b~n>=cTf>p%ZHbHdk(`AS4gK>Qhb&w(9?r{Ak(l^qv5zr ziEM{8$jondh~@n0mm;WcNa+!2w<1DT-@QRf;Q9u7Z;(Q%t}OJTp1Q|jxlV7Hy8qN| zwpS!nam_HyFo#L|H&CzTwTGBL9K0=DhZ(Vud~gd2ASqAWjZ`3d-hfoAR6Aw9*(pcQ z@Y|iTx})<WZG?TcH~X4#%_D`J-2xN4xhdPqYC8)GMoPeWisOWo?KnMx?2lYO?E{># zb|%M1Osx4&LeTLi3Yrg5h!W*~^Dg37!F_{E`g1F`t@QiVeqbr+Ey-cG3rT%(!qvH^ z04y#x?4V)8lDK2YiF+n5D%*qEQoJoQ*~EPj10!m~H_@25bm`Qh1W$`PXt|;wg+BJO zqG$2tu!uWV!`iW&5~m`v{x}u{Fch8#wMskd95U3TR<DI@tu8rI)95P7Wr6mo2WYDY zXO``*wPdJ=+m>2NrUhAkyGQ5F5UL;;km)C^NxL8PK+0_ppsryP)JCPBX*hAR%|_U- zMo#;!?sVd8dpa0?!`gOJRx2WAQbeRZrS5L)Pvz_>+8O!0O*&c~a=L`ew~XEFqXG<> zGg&!&Y+@vkc1*k8v(q-O(s^QH*=NKHqu=XWx|fSt0wkG%@NE>LKz}x@dr+>{w-`Jj zz(6EU<Xhk@>_WS@*R?}&zqL*HcdiuPw^vYRv@T<c4veTYQDD4`1gZ^ISrgtTS(*bk zG+j+GW|6mjqADoK3S9j%-mRyv;soL1pT`i&?RCO^S;sc=)vz}OY<a53wMe~z(^f$X zl=|!}usjUKV*MItQi)U|=X}>upl@s8`5b54IPj!U=N4QVi#m!!M=-{NgU0zeQj{RT zEBz2Dk)7LW+qCP5lvbYYIP9n(r4cFRu0lS*dxPs8DSJik515uTr0lT$5Gnh7Zf5&A zQf_t%Go(L;lx_TP&2|GqG!w=>QkvFUO-lzZ#IyPqQkt9M9a1pKTov`4?vb+NWiMoS zgdV=LmK&s~ll0Y2;d$P$uPau}g$cCWmWS#6LjKD2Qw3N;L{bIV2uD(c`y9sL$Pl}& z!Pg6fBD;~Cq61D>%G5>3iAlcqZZ#d!3c|Rw)u$dZbc-6~g@psQs(@`h+nkUAPj&;R zj=1-k>#*z^hatd9IivV+c2}_dsgA&^>sR~N$r`3)7ZM?#N$JeerzkIxhYFU4i?FnN z`68F&5B?W1ud(YOwvdq%RJI?I>fr3PcCb><iL5vw55>_ls{|0%9p9ayhtTxTq#@=j zAIj9Utq!+e<|6%esL9P!r>{IF|GMJA^-^tHN3&)vq}Xl7uGDJSPDqWZ>g~<yf&j1e z{Ne_Mh?jkRi!P$NHsCiffwc6w6Yz>ZiMaMBwCuDhxRPvw$<2!U68_+IK^M2ooV-YR z0vsmjhrWfX_}z!Pj{I;QdB>i&WoqBwLbdh@C@*W3JP~)2AcQ%k2h~0V3oA$8AfEzs zI_hMO>LQ)51|fB6**|^tRqDd3{}Gz@Oo?zMCMj#GBq3RP+tig#X@m)2@Aw*LJn@U} z*YYgcEVc5WJNJdeY-2v0WE;ayUuF#3{7CAkoPy}Fe5mLv=@nnOh46Y~Rl6&lOIZ|d z9icX)7=^4P^+6)<8g@z^!lRfEGD8pKqnl2vT+TY)seYJ8_FydhX4oDQznzsxR9d-} z*(p49CmVJYq?ByKxc?<0qNjzFTrWn79)``VFV;_vtSU@yN7&vVr6SZG4DI)Ig_I?m zt;9sE>8XB<lv-!FugG@_g1R<S8hoc5kg{U1iAgVU1&ow}5CgdS%nd1CTP{vL#&rgp zJYp@X$GmYN{uwSl>eq$FjcY5l?;s`D6Zfm+T9_;LVYM*-Gg5fABFQeKOm*?46H*LH zCWZ$=^10JbSf5z5CiZ$`UQ)=TLMPR^K;C~~#eeI1d~na@HU9m-6OZtw5d<i|ETq)C z)w666#{~y8WG+hsF=a6oZ@xy=l@#yTmDCS@96scts=-DfM1Xm#<mckiQzY}+lKJ5E z`?Dg7I}WdeyYidoa9N~96xOD!u)4ycz-D4C%hCbu!@F}()G#su`R|xjh))cWk|~}$ zcNILTygHe1ogFd(1<c*A0!l6B0o;2#oE9*FNz4HG0?(;1FfOMrbR_bu)b#pdL2*=@ z&hiFF81>2O&`IccF=1BiE+lH4e4z*|aB1#V5_@}uW3=~M^zzZqu1{jWuP@K{9!Vto zfLbADp^)lGFil4<8~F0OU^UNcnj9-KTp_&i8x<WH4;>oF?G+Bjv&3-v;3IAKgv>4V zZ-pE62;T1DlwjFmjIf=%HZ(@nklr9XqN#3f`%YOb4kioyClhWn;uERsrz$&<Ab4nT z8>sUZKh#cBy|PR6&*`|BuYYcq`s-i6kTD&#p9+8?X5~2|DJ2J1hli>vN#zl|s?y-^ zc{TRlsNBWT$VDPNubbkvD1l8`zDbDqQIARp_Mqm25jaibWH4UwNG#C`?Jco{I1W?5 zt^Bv*OvJU{Jj)sWxoVZZ_aGGr2K?d704jq7Jz90HOFZjOD>0O`IzE1{kdkBae9(|` zJedkoDpUu#l6GaUhF(F4oN7+;;e~fdae$cmK{8sG=$y&hVJ<=vf2hZuEQiR*Mh%Fa zLZAqBv`>}Lff%rXxBO?Dy^Qu2DQwT51f_U3hH6O3JN-P;&yb=Xe0jWf0^1k6Lx4Xy z?G)w3jtUda)0yX7V2;xNj*z0E0W_h$BSlZJZ7z=eVAN`X+IdBbIyuydjrx;be9L~# z<>W8Ffs{S$#V6@bt3V3UqPp%FE*l$CR{dJ=(+QkCMx#hUq&9Kr-!3MhF27&@{Gb2t z>Z`Zc&#ORF%qAGk(|>d2C6wARL^B96Ny(Lzh<oh_CQ?tYu+}#p3i|D5cIE6l-=x>b zR!7S5M4X7~O7vV{PFJNcOc%N6IR+{X(rBvA!%0!Qcx_@x^iNivc8x0E;p2qKQ$hQI zaH3kxUJ3#B$aauf{jgP2ID?3~vN`j>@rh?Pc33@ZRnr%;pgbe0)BQOCMKu|3nHe>s zKqsrRo|J5VDJFE(Iw^&*9&{BZj;qVMRh2_k10p5Qf}divr&)qxd+FF}%<^V3R~+=y z>!;6Cg6&13smg?m%ojC3y+)0_y1C1#xVaC!M0<w_Y+$clpV1I?FDmPI5hi>S@(ssP zXzP}@uwf17?!MR8_025abnW-9NLVTUbUbr>Mf+5U``^{C{Edt4nj#|J7VBbs{z`W+ zwXEHUjt7Ot4<sx1tdO3Z9#sbY<WhbGO=lA;?^f#JLde=P3U@F@#&5V&uzZ+P8jfAs z&=e&R)%q7pC9d{z8V*@=ldY4~LnLj>N|CF`Q8@xcqN{^DVUz<<hwS^J3{L+g9MXrW z=~W&9y(;3@s#mB;A=xaq5X%|K-Lnsc<7K*5=C0ZdKUy^{03Bu<2#jRTr{5WJKbF@h zUAq8B`9j&lh9+xvnqmq`jd8VKP#Si5htg>_$=B4z1d%~X`A+QYBU-J1gw#=%k9nuE z)0kdX?d-JDo#uT^<v%r%B5nuImxletSEK>4cvrwVf<;-82!*GGMQHVc?rXX6rrsb$ zorp~qQax=D0=267W&sg>IH8Im1=Y54K*~DzT6fl5i{>uY6H+9BmIVvcfO(`@<-Nuh zfyF4MLZKX1pb*rXtIAi9vN4wfQu;#7VIC0Kkz!%b69p;EE_V8#cC4(3SJ}PsG^M86 zbc0kZmV;fd*g{2$-MyAD-QUYX)Y5F=z7`||a(c8iz+u&KXSnFs9qGGvlh%<Hvo!PP zub)R<2M&%ISt4wP4}n74deY+Ss)rm0%Q55IRUNoE&EG)^q4o7`aI&FBo-UIk|2(go zKlI0ngrq&Q-dK-~co&7azom~%un48imBV-p2S1E=7}jP`?g%T3kx;N5D7yTtn%aos zgqiRWXv$4A=G4Kd#A-F}DWl>b;HLdhu`yT%OXx8!G^;?JeJVAmW?o8drH+)Qb_RZ9 zyA}%}sS#~hhFE$EdaOkhiTc0o;?Uy5cfvc!eDTCqR!y}AOo_G_)#tgtK@+HXcy!2$ zg;F$)`pvqSLiIb_`h#&Vzcc^1?mW#l5S`Ec!v1SZKW+o=VWvC75JsP?Q1?W7dFE}- z*!Jg@SSbQ)M3>FsF3wz2dDBqa$6DO`eGT?+UhpUsMATHSh$U~A2({K2?4mHO-1svj zntcdKFwm;;@`|ery6ub{TQtT_om)}DEig$^7*(`g7}=*Cw0B&Z7-CZzo0~;ID(HqC zHf=3vYvFnAe0le)kdw-oj{B78_r85ZDqxX+N*r{zYq{GiSCVC#MFc_}ch<0vq^|g! ze9{-xwSP`j3PuX*gCn7*vG5PB46b&$ychzaXj6>IAqoB9r9bIsQpm_Zaf1{Tq_jIa z*_sHr__1n>__#(&ijUr&=ir{b+AOYIsT*1JbEI4z%@rw9kRlZ+1wKd0ym|${i`bVk zf$fh}o|){NWr<_Bkmt~pppPr06jjJ6bBE7{5e*BAe{RwEjFb~AJ|3`n@D=SncW%jc zVH4g!VZ|LkP#FZI(=SmgCA;@ID=u@vs=VR^1{sizO3Md-OZ)vZIlvK+$TLoNZh@ow z;Uxd`VoX)px_+58undFzIzZT>ac~0rzqHl;HwsQvpCRQ6cwbCY>c~FE_%S6@nkq^X zdzB`Wy0@HY^=t*?V9JZ!>W-QQ>2r|$b3HW>?)1_$buyt#_d@4@Rx34>&?+%x>8pr1 zR)dN8iad8VfL|QvB8UWF$--CG*&F7n7_nvHl}fD~&k8_D(~}C^fTdG)i1T`p;c<W- zdY{e!3tdqe*-C)}@k{YU;GRbPvCG@G!m|<oAYOK=gE?uyEdp6Fs@$1Ipe=6yzwru` z*Kmh&Eido>sCt<6;jy~=6&!Y#1e^ltZgKV)0yn^|KQ(DI&22;h<sCP$1<GCJ@z|k< zC2L_!pI%v-E<{_2zzm`)0%dLmF8o#Byg-8-xh=7Lg7&X)spqoWqTb=ge3(DqU&rrv z?I?%tnG0kh({R1|?eG=*(NP}E(syFk)9AwW0|OLidj=ZZnvPby1pdfM++|N)xHlt% z6v5J9PYqEI<1d7KBj!HppK-0%O%V}&Cd=h{a-C|-%<IGE8{u5g3?ovLvy=|(JXZ-6 z5;+dh6tqqDph6$k!ZmNzo3-SQUZK&JuxIQWR94yund&5&WHB|+kvS9u1WO;y#JLNk z#8+2|Yz}G>(MQ(AIN*93U`t{M&xbU?{vg~p$nnpi1$i!dzVzsoD*WMMEuI^%9!B1G zN_edYeOq^mif3^XPeuUB7n}MX=`-*WaUBTzLe5B`=7<XsL)E!%iwM0%iiXC^l36~x z7<ljsK7T`Vt3dbwDHq4DhlI?LOWTKy{hs1UL&^nZt~i$rLvVF5O-0T|K0*o~$8908 zQ-<j9bmbk_9v0D&qEdEBQ^kXNr6Q&66h?}Cf|S!03>N0?#|5sL3CDx#S}n6#=3o-X zO7Y^-x`>A(<n0Ugb%!-NQ~uiZCyHS0A`f@jj*s99ht}H*{BOk`6(U2w57p4pbUOY$ zbQss4rIFK(w2Ah;?!WCVJ(7`1FQm*jS(Q=Rn@Lj?Tt@<WdzS-rf!G=1s%_hKDVnW4 zLg{}l*CC|d=w+%Nsa!!Kq*H)pmZ%n+>@(I@#7Ng+*3H?XZ8?!OR_n$Mn4GGnU`O=I z<mN?mfVt0(i`I+FGVFmCc|a#ONiL}(32sWuIFTwORr`p2-N~ZT8{1)2!w*lf>Q>T8 zMTaGixlN(zz+nVAAiXT)k6mxat*Rqw2&F<=aLT%iKwBx=7-)VTmVl<V`J@;&!Hctc zdEMKq5}JY9tm^|JFP)Y*E*jMau0x-9=<GAPWIEdBbhysCafx>JTa?Ob(j7tN&ZxDD zAiUXGqoeTgE3}_Krv@gmbFKm<!gRRIYoDbG?^m@)9zXS$4Nv?E_oSA!k~PxAA14N9 z+_8CoYpOiw!JES89?@|Rl8R8CI#*1s^_Do;Pn(X-G<gN^n~<@6R-+E<l9O;H(z@_` zq=(&NxO`^R%-_a?yVvUq9rrhc?)0c-qUfniB^@*#jO&**79m4rd3cUxb=e0vO!R*r zLjO*06!r=nk#gl@K_#uR(FR8d&q|Q7YmRTcU&swoIQO{ilvv1Kay*3cs2kL#G%IDc zXIq){pR6UJt?KhPx69bpvM<DmM28oMa#`jKs44?Pyz<%DmiY;F9c2nW*RHmFtfdM) zC9?MucA@krwnyF`6E|3Ek$yMxITl{t*jHgt?<ljs@vTmBPkxORA91a9Q}f8Yz-Yks z+dTZwBIOTXe?kEcYV@mQLwWPtEUOX1T@yp(-Yy%jidV*ydo#(KsPXrNm1DVI&dZ=e ziyh@CgvO^RZO66Ub(luVm5n5tkA?n>!0{})UERgU2Yb5OQ8f)MgIpv9Ontrk>I9tG z$n~;Ie;ti-eGoubR_^dbZ)N?b^)}_>E2bSMe&i_+@lx2LsZe^ApTrM5)2hh~JFdbG zv3YyYfNwfhP47I>U?-4Tsx3Uk9oB)kcY^od(thQGaZgS{2i*trhRi5uUZQb9De8nF zO#lEO07*naRDD`@6%!~lRaG*|Y|66#p-CeCK`<?{j<8DjW(_=_b}rUC){o2KHrvU$ zf<dOup9}*030x`W)}XmC)#*>NBDz~Kk4vhm{->H@9nuDPe~zBWyJ}DbyG8&D>I13% zALPDI{qcRCTsr%M0dW33V>=tyi0W25?+IT}KINeeXrq6|7+h^Wr+9lvv8q_4IlqKK z-cG0k1=kH`1B+0TAyznZ`B=>m4}@?!4@DsIwap<sBv(O<;;eYW@&GUHQRhF5pq66S zb`rRf^RZ0yX(5J`+3zelid<uPA2w`@Z58}ew?F;l_8me&(~(=$;{M|M(^AX<_2PMI zL>+67CD|6jG|!V)Vq)tWBrbXMKCCRQM|13(@d|qT6?KU(cZyhYxG%h#79+uSOA3g4 z^7mqsOj$#*lf+@D^9@zp1Mu2!sZ@t|)WwZALi<h5Q0r_hX0l={Mwjr5aJC1Q3KLjc zh#Nchow91kM4jz@EzZ6!kz(2=Zv$SAn^gPc`&oGycDqhHC8w98wPATak#gS-XWTrS z1)McCc@Vp&^Jr%m2UeUC8Jea|aJx96ex8E#XB1$<WG;2NSUg&_=!;Ev>?Jnu7geZP zebXor6W?H8rNfi7(|{m+7XAtZw##b^xZ^ORXw*i`+0CqeSiz>E7#^kEy9aCL@adr{ zjmxgZ9bt<ag<`NjX2UvUsz5YzW#zRA)09t~cdw4YQ2`(mFX^l&rY+&lO{l9(fvOB^ z#Q|rOaNT#5x@1@-l6-I4i_>FlZ}MFPkGEM}i(N7IaCa5RM8i-i4-T73eisiCok(E{ zft0t=qJ;S-%o6H)J9rAwO_FZ7iH|<9$bI|z?uc7tNPf5lkESz_+bokgfLm7cBN6KF zkYuD~seRq83XQNO!DdmrIe^9+r0F`$^&LmPqa?oJd%NT*g=_dD#qxJ`1qAl2vv!uJ z?9dLo3@#|VfjZqUi_#79^)0=f0;+{Vw*7r7RPOa^sN-jcgIx)o{7q=N#r+L}hBL~w z<&UTDRY*WLs=U9dq;gmGi?mAF?%9$9wXW>^l<W;QHi=en@ukw9Xu~#l=*?P)blp(H zf0wU)Clbe{+2psN`!C+?1Msj1+0+fQJ)%B`YP*|xJ?92*6hl!dCn(kM@2;fn(j^_< z=c+ktMnh7hF5i+h@VJ#L4KyHJQv5#cCTEj26O0O8EC)Aad6f{$EpSL&72go>3X~TA zc{+$r(A(~*Q^Gw`f~TqK-em3?wo(%c8Za}nL@AxlzuL~7GAe0}T9>0_k*7==rmo9j z<&fFypI@`ZsMEllp9_CffbR#T|IXn%ha1e0o~Pi&PRUO$k-}5h<3T^%DQ^jE-#hh1 zQReM#SR9c;A&1w`p3W4Y*fKiV^Edq-_4EDaO!-^a&lO-dz!=w8(XgdMRmXr!hMrry z=gkFlj@$E0G_(Z`U9H=P?R;f4cLebJmM*5q-Ch`L9-fwKm{TsvSFzI&iu9_Gyt}D| zpE8iGh+QQ>l|GPX1hi8frR(pW_s39-Qnz*!r?eRlN?k(pmE5cg`QAMHyF6WPBkmPP zy)KKo7xoo+-DZ2=N?BG*yz>fM*+DqYIB(!0VZ_$~m+7W&v5cYh#BznI4#%3S_=TXR zPHLk95g8-p;EJEXIAv3BXsa~t2h7?#GX*`T(}5w2S8Lc8l)TUsvKi<*=>Ydv*RlV~ zMeg6AE+(@*>fw6oA;=(PXX2sGUKe!B(jrj5PHoA7C#SvNVEmy?7$+OPQKm=2pI5Pw zP|6l<@B8><W7?rnOE|aC@Um}X$AUhL`^~|n+u-6Ya5w1f$Lxm}i){3~>mplde1H55 zkdxn556I>EYE!3)MVbHGlrD)={{(|#2?<BoXV5tAyJPD}7u_=a<s=Mco!<RRE}C-q z+J*koVcTW;rhToL%&3H1D7dcA=d;P)sbd^zNLv(l`+7S4qJOFUTqgCzgf>CY!{3EE znjGLaOsvU_A---N1TIslK}fl|T2&!Vx8B@V8Vk9mKD~-;zlo$<SF}Vv$~O1;dpm&z zb)CFq`PucbdPVRB2sInSCoAKEZr=idNjIJ0G=(ElYy*Z5qfhAfkrEQ)ai{E#T)x2v z4>~Nlpghik)o=^t4X*F!b5A7E&aJuozJrwX+0JU$i&&WD$QXyBO^5khy-oxZO%~@H zE`gx8NV(Z5O?a%__|33LR(x8BTpbISTP)<p6A$Nwr1@FtCBEyG9@aQ1uHN<2>*orv zhH;2g$w-kar=$xrB<J&G0;*_;K`rF5U#9)0NvLTcchfeKs)>WX7I?kyu6Sx{9mFjT zoi@X3al~G}FC+^WDS*Uocn)vN`l_pN{ZlG#vKP&&^NioM{T>Ufi%9Zg4|lnW!cZPJ zrOdcN29tRCDOIn)H{3K}lW^_NW8&<|5gSSQ_ySz-P(IX19aT$A_X+#nOIwy|$6q&I z)2Yx5XP<4+i*P+dIqGL|3&D@-`oDYKhuX;7X>Ydb-?+BJz;{;X$Ga1giWN}<1J_Df z;kcgxjd0f)Xy+sc&!U!H!NqNg#kxIp`rP(_nk0U-TiwpiO*dTe^0=(^FPchRhdm4~ z=?9e)0sn<7Y^IK9$-m!TEHY@VVpvQed>bn7lUs_)jBzT3b-eGBr5;{Z`xtHaH@R?s zuz%yD>{8B2ILlV0T%L**@_<zIF*@chRw->?=)v*AUyt8?&{3~5XAaO>Vq&o+Cl$iE z7&hvu?&j$}pM5enl;Hho&TH{^t+IUx6~!?XLbe-&GoF(pnfjt`h&v)aZjo}hczV}Y z25CpT6mPt&+z-Zu;}LZGP1vHPWba>x;bUj2H_&6GP|N6olo+3pvPkRYTRVmQHw*d0 zNIAU)A%Zbsb5a1){KyK-=V9-A&3LV^{WL?GicU;*M@nCY-&5+<Z9srgTBu`~zq3=M z?D|@e^A-q@Tj<sG=1yT&5WHy3->C~X!?v|F@R||xLI)08<i3_qSaIZp$69v#T?DHS z(fRizjGrpN5iQn42?>9u3KR;B9o}l8h@|YQ60TQu?|7<_?aiTbo<q8PF5287`9%oI z*|k=vZ6-N-L%oWd_=r*$pi5+@)Y-8_MOQkUB_yOR9^YEm9*%yB?TEs${0)v06X*Wb z5l@*q7N8><M!4ZD+d=`|mzPT8_EL;X?QFGl3rXLK{W-aKOQyVkB2THgvduIdx*8`? zNdpQfSzC_OhC_^B>0?eS>YNjvX=+5n2PB|#2I3+VnGo8ba8^bRI<RikT&3LHHxBdu zqWHB+<X7s77XWta!1Z;A;P`{rDcte&_PVaz#S#=)JiXW-mk3L5W41WCQ@{$N8Y<Jx zKur}%=RBEKlz*d}<KM>4wEXLF4N~-KBp0HzvTMPhe!*_1%#Y`}9Irdg_n49L_CooW z;En=}<2L%F@G=>RT9iN$1t96ytrh-?;?2bZ^WjxE4JZ589WXlx>P7u^1l>oGwQ%;L zBdufYCgnIWo#e<S9xc$T_Yq}52Q;f8@-nyRS@3%Jt1sqrDP=|<&XXuy3Id<>6LoRW zdfSF+nguVCx@7rJxGiV9sPV_);s?Kl6qj-BubU%;D^YWeTx>{r2)BAZ(BTbIqT(wK zUkd9&`?w3>l;+wW3<yl|*kkh1#i<G{<G*~^9kz`~b^`Mx&+f5k{bL)C3C%WQ#jh?( z?oFhyOb_zLznln<juJM|Tp{JCr5ttm3Iw#8-ur`!RTdj_ZF%iT2`H`Q5K``l<N_(D z2O+oxLPN^FmU!y8Q(_6j=U?qF)~Ngjwi{9`P4Ao>^8pZUSTXMu@r4}QzjFbqpCLuA z%6;t*vcSgm3$7QE^}So0+{VV+SAY2W10LWeMtFZRx+PO4!<XlOClBKT(;TX+IOkC> zOO>=!0RLe{TnNN21jWZea9pc`mlGKq>SdOxk8nwXsMAX+Ikjt7FHEaTDeO?vnMR^O z=B8_ty0U?2aCB}wnQ2EECY_16rR*uZ(dCk=N2mr1gdS4rkBTWF?pULU=`nQ9k}lO0 zK3KI^PzF?j_OaSbVCanYjq6sZhrUBS`~s`3(ga2*(5za}$(L@Qo>Atq4RxtdM5S)G zS$Xmh%j{jZ*pAu2-knz3$)SB&^dt_n7PRNHg!mw((J`2}HEiBoKWOpt{;Gp-1+*n9 zHsN4r>8YxcHtT>3Hpn!4liO1?Q`>DWKE^_zw_y|Yt--sIbhQ{bKhpd}MMXyISAAjd zTS4(BuxQ?Nft*aN#r6~vVluU8$R%Z0l&2GdpnPBrFYR$Q7qVG~8%x)M_8N!ZBte@O z=+RwB$uJAw3*{d5r#Q$Yafvog{;4UczQ1fZmMs(*nojqak_QK-J{$pW=5A6kgP{** z?b&61`69!^7LyAt)Q8oO5$VojAe>EmY~i+EA1mZbp_Z`OnsRs@lqks?UO_u@V{=8- zZC`K{FGYE&HI7=jBSS>3AyBSGHwZM1`mhiKom#Kx#JQ3lm1UxRj_J2yRkH;!3$<TD zE;GGSu@j^7uqz3w1hh8i3<uDB7k@s(3<kz^cCR6%6o|2ET7_wCNNI)KLLP+oQ;q)~ z_W8b$rXCc~aai6_$$9u%)=nwJuc{Q+re6Fuc=f(hm`DPWqrS1Zf8+99#!i+3BDRtQ z2}N6D>N#W;#j#D#2h9EN?j)i{XDJ?!TKp^#sJ{-;hnU>xhpDP&%y8odYmlkJC9LL# zlt?8Ap5PxQ&Fo5AkS;I0s)$(@3v}CXnX&8$k*Of2q&qhtu3M18U>~9{Kli2<Ci8Bm z$Z)SmoX{K@(bmhPD^>@oO8T2ixxG{!6ylAbS>c4pF#i@_0+s2pm@Gh)6HjTz1HSf< z2h@y@qzig!+C-o3TTC`3-(PuAgX6o`j}+iu+m;<HH9EmH4P<d5w5>v;hU}!>ar<UE z_1Z+X`nruaF7AIbJa5yyGbk;@tpEb?*b70f>VHQXF1KfI*iRzktJ;(I?@CcF5TbJy zKj#@37vgPbiq|e7av+N?o~h0}>Ez4aO3Hgt!z8ihQNf>4_pGL_^T*U*C1Emp?YL!j z&KT$fxbr&tb)b{;bz{5TZ?(oq7JFI5?QKqG(XAu=SET#?_H{ukSL#pLVtOcsx_onZ zu((vzDn6~erc%eWT(*O~$ejmMhDe_eVMF?fo1fPc6ZE^zmVM$B#RyVga1*wkhDnnI z$*yv-q3g`}Xnn8c{Wp=D7ErR{r2L6rZ%Czow&8d`y1ucoIYUI8*Fgn}CdG<)s~+|H zC#go76361EUcpO5WrX@v2@4@1#l%A>Iri`{3Zo<jXb0h1NJw>i<aTtmY3{pNX*5IL z=?--vtO8{+6^ZgvM{Zh;65K8W7m<JpCm1^}R^%QF<*b~~K9sLTbDrUljL2<zaGjB1 zSvkuQv5-lkGiP<i5*7>a2?Jza0jVfKkj=x)xRAUp>2QTsg-W^mMdkEoA_c^oz%6z; zpD?y^sZNXt-x4d??e)W~KWZYyZGH&js1tJ4bC^h!7mjT?Z6O6I&~(ie1Qw-K?T|O) z?9j+%RbLCDW3AB)j)HTT_lj<2YxhuLc5zp#DiV89(jaxGAZ(yjech1a@SIuu!MZW? zE84}lPNX0=qoj%}aa+~TOZ92Sb=@gt`5A9V91KK4AosHO)6+dFp$`ick#H{!>P#}- z%+8bF2uxl6HK!U==8=6-nRGK@tO*a#FNDevb*)uhpI19T#<{?ONuq0nA%G4O=b@|W z?8v5W9@bH^-@EC!vSO4s{h{ke3b48_V#$e-09_mhE<*}3ms8@W(qPOoVrXN?(0V@! z?w4W-xDAotZ2!1^)e97H@yk$}3X(u?h^`VfNSidu@YXQRYH*YEsaoYe8r?@}!s{_7 z(w#MP&XC$Um@@&>Q?e=SGyIZys^+Xcv@f*O)w5SQJp-g^G~daas9M|es)Fg!(1`B> zb$L{T_spb0jw2vES&Xy`L8dSw>lcLq)Q?!$Ixxt%V}>iFL57aJpoH)mIxtcQ48sqv zOjzwmdq^r*Ofg5*B5VPsxjCt~8b6M+a#pW+oBt8oZ_H~alK1M=?Y(en6qX?}(_RAV z=G^l#e!lH??h@NFIA5X$6}46l(Dtv^Q6fi(c3p1y<OB4wpyCcb-ynCJ?CASt236y8 zwi1@;PpHZmTy4)MoSDno6EhB1(M314>GG)$V)ffwRMk_nbN8xrGcIqIhJD5IB$j9# zqpk?0@qA$CdmMg$lz`fW@_RBfW{EM3y3|EwOF&;W3D$l>i(tgGSD8<r56iMuj}pz2 za7C~VNL3~0(9ytIVNZgnGi;UDLVF1(ao@2w6vAuSKi?k@-LHLh<jtW2U%$V+GfriG z9nDPNO-x9YMa8CceR6wm;6>_g2v?;0pNUJ|!IlaJ`}n+^9ftfyHf6UpUOnYZG_`^z z4y<dj<C(zJ<3dvM3@NaF%gelq+y4Y9M?6MiTAcmlbweBmBfWg74Ss+W3X3Z5?Y!wg zU?En=X1u!Jw|B%>5`sDjxlKXY0ef@BPykmzsK1Q6Mjp+=(ih_2MyY~uv0Saam)Gs( zgG3l9-f4m-dF1`U?s#JK-t&~|S`s1JzdS62kkWP~&(>BKxy1h94$;Hkp~7=^FCViF zWwa2N=ufcvE7y-bz%c3CjzEV{=B#GOWjv?VK;D50SPvffhEHj;Y#x8^xM5)PFcwl! z;WC6NYE{jy(#6%vg+$u7=;~*Cc%`U}HLF|nB1m=JZ2Z{yjP~MnSwy<reMqQ|BG0>~ z8h$ejPtMiKfubT&fE1!r!y)-jNCj^Q%LT5q5qnfka57~%^5?beD>2HPN~~Ig7%b># zMm(g_6jFXGR&u}7mZXGBzrm|%SJ6CqOOLU3ao^)<Yb=H4GkNH2aj&ixnFyZKRZ*Q5 zW1sQTE!J1c$A2@f`Q3H3g@16Fo6MAaDar7W{<}p((C4Gu22w!vvI5N&MSfIMVHe4) zjadR=odC)~&_$AOVdS{4g+jPTRA}T7Y*q1|t#0E*fl6m_Y8}_KZc&~$@7|Bsuuq-> zhz^5%Hx3^Z9o{m2EBRMmu1($Qj$$GcOKNdLD*#vkppW}a66a%aczKE%n#*nw9n?pW z4!=GoM5F%G6ik<LP;c9>DyEo254Be9Xui!&Gl?TSoV{?<3po`-P-YMPzLp%;U94C( z&scs@3GCJ)ZhB!P)Z(r<0--8JscVg_8IzXlK%9Sd2$&1d@_;YTBy`W1XnEZoQexB0 zss>zWjE0>c7^VaQT};NjjvIF<V-ix*GdT%USIWTJh=i0w8RR1nP=2a=L}gYA@j^$3 zwY1%dI6M54nW^K_jcDhEe1w$tECbMm8^l7yJ=oE(>f1;`RO;$V$R|kQ4K?YJ{aGK} z>IDo@BzICNvrStGRc)0WDLa9M*ZLErI4;upANGq+c1p~A1)nogH~^lIQnu}p71OZz zQt*7bPP8qAc8YrP@JC45c70AWkwWH4S}8)zxgPerNGb6?dd<WC*7Z{la1@i;$yI67 zC6Tc3w;ybqb?M-sg2?4bQYYZa3Z>dpp7k4%9g5Lk1D`&>ia@%>T=0l~t9wmKdyVYu zcCkl&GcIMVJ7)6En;gORXQ*%`d^G9+<~U_aJ)`m(0Q(dqw{<`VA*hGEu{soKeKFF~ z68l?NXtANAPqCKSIxA=<cm6kg5Jh~>0*)GX1YUc|JM5Xd1Sny$BsHq}pf1l_+i8j- zfKiR~zsN-X!1Yb#;Qp$rtMc~w?I|(Ahn`bPSGpdQ_KQ-_r3hGLk2@9U+ot*vcn-v2 zK@w~t!O7N;0aP)R2oqlym&^uLsQU`YSHb7By323BuQ$>W^Vywphz+;+5|3>v-Np8# zaW2LNHdNvL+HWtHA;O!bOi}?J(1-5;meNub6Pi`i2*$DLU10B=&&?DAaoYDV;{!<B zf!pJvJjMvpcAJ#rmf-J?gAx(@gXNs6fZ!z0N%bBG2#3Abrp*bEyEw=#tnT-5B1Lrq zLzTifSz+koXu(VCL?E~&365;{g{W$IUAw2C>~dIBc+>z}<`eJTCWeZXBV}$^QeDdD zG2!-LR4Tk%3xyVfuso@Z@Q%$bdXpvlGz2st><gi_q}Mbueyd0*R|~liN6mZi5)YBB zqrFFpg?YGm5>wSKVC-1l75<nlp;+JQjm%-*BBfotQ|>AA0(xb9=EH5*H}&}KPN{}z z*_GJaol@R#rN-A~TBtMOy_^eSpj>}Zee9#Ff;OP%gu8*&-@+lS+w@omp7%Vwzxl^v z?GHV`K98Cl9R`FMogo}gQ5(FKm|^2-1aFZmxLfV5<H=dD_x$aa3b?KjY~^AxDZsLL zTkdq#`mJQM81A%VJxl=8V<VH&J=Io;;>!fMP8H3WWYUO$o$BG246w6eobNBhM0ZB5 zpzM8ekPI}Ut06*xk0sc~{n_Wp+o*^g|3lNhS!@I=h>um%h*<ULU(dLXNr`(>TqU3o z<<wuo8>uZmI5LCHhd|89D%7~vz~W#=m^Wgf=;xgs<f<If774*?f!TE^s@?lAV`X%h z`#{OwWHG?yu(BYF)Ea(UVBfCq>MvJ`@%Q7LzisudP=k=8gfBW?#37K1or<bXh_{~J zMClmS&kTdL9%3MsrBp<XJaNVa(kiu@1Fx^jA!|@}3RHE+>f{Yq%Q&f!2QgAC3T+cB zQQsfVmW!DF+uE<e=j`0R#`^~(SAu2B?Yz12BR)&kuX8H#7l*<0V~(PVa@<d5=1YJ% z6TC~ijkb{jH{0NL^m4sxG!_TaH`<+hfM1Nc`OUx+yXc(JCG1_Ki<AR*5i=+3hMR!v z$oGn#7jpQ##@Sv?=@MQ1#_d6{K$JZK;#=rO3M4CMQq;GR!ei|VA)zwoGpGpD9-qvz z*gZhn6*<h;3prnJk#awQ%s;x8vyaQ9o6=&%x<n=TZ?ENIi`@|z(^#RQEs*8D$xt0L zm5?)1HV%`Td^#Ag&HN&O3-G#4TR290t<UOPG!|>=kFb<f)ubp@5N{k?pw~O3;9{z! zi0-#`iX(HJx<J+tMN$wdbsfU!O2q7Gje*UpmUSeGv(f%|qh!sdi()?;nwA2mQg{6o z4=)e?socE}H_!Qs#AxV4^dTyOm*7jLs6JE%<d^6}t+LP*`Ld$w3eUS7W?-0Wt2{&> zy2{GvLshV(w1p&nh_0BTFUS;KwEIwfst%Dak!98XQk|kttdQ9WnM3A~DLO?aWUi8f zL-d#E@RER0@8O|KNtG|vsdK1`>O<sd3tVrp05GpgtXL3Of{HIep#$<u<e~an!Xb1B z9x{iBVoZ@2bXaun>mmAp6}X>*FOdm-imu9gLj^jAC6-}`&1#4~Wj;h#@W9$H>)Uk( zzkmrmRYmk6`V@u8OU!ci5*5)0R-}p!(V^2bpV#0zM4mdIGKZ>H9n@jpE~R@JEA*Gh z5P8UaKvoUXDe@A$uqr(wc-Dis6GWa+5qZF>biQoY&$W<Mzwrf`mgkQlc#4i?(S*DP zCLmrwawT#O!IO+CLl@!6Q}rR3Fi*#F=naM8UFL*7R3P$Dc?ux%Qc=a%#Fs!-9=1~z zf~V2*Itg^Bi0FVkAw$P%bztA>s&uMff`3fEhloB@hrw`7Kwj4FDY)%?AS5KC;Z@P} z0aekLs>iS|aOo8N5`D>h=v;XJC3A?O>80`|R(Wq-OQ9a#rkNXWK1GJ$Rm-s~3H57H zsi*M_k9ztt0>+nbE`CtzpUXi06dBg8BM+FdjT7^kM!on)uzDEioUc_i7l>vpOUr$T zDD<J~(+(k6SN(~X%0Ge^R{1rB8Xx#lRnae5<q&m*t;Hg{)J-b#Ft4Hhf;<MM=p^Pa zWQ`+VqSKh3K2%q)g%#`g61*%nNu$^JGoj^7X4}Q$`|)Ap$jexYak+=9I@3_24=N!S z1wReukOu^!Pc>{tC1F?*U404ufqVZTL-d!bc(;}5e3FNKRG-Ylu)jD4ICR#&1*YTu zAp+5-@c~&o<xB7)6^Mtee=cxI)=7p8$W!D25#UAR<a~6oM|=sC>h3@ly1EmXvBGOF z=~M6!C}eu00C8*Ww?h1zr^1Jk8C5pQ&ABUgnV`i+&XOx35ovj4U*HR(EMwjK8DfN+ z|Bm<14<s8dB3;*VKP9DoRCEkha`-yx%rW_Sy^vi(eLp8+dL~z#DxIFjWTYsrw2|$N z^4VJMQFc8nn82>?-xoqiA?p-@Vn@oXTi_lk_gIq<W@vD|UC1X$d7I;-b#C*tuHz$r z7AgC+3>i^`>4shKOCutqP2)J*_ZZpM;&Z!P$i;_^eH~)#Z{EnLxw-#>9?rw6kUVh# z+p`g~vafN1!<ETT>n9gT>2(TusN=Bfo%eiL>EDQ5YHRt<QTgNR@xeWp*ZBAUW2gIA z)xVyOOlu<V`J*EGSou=!(c=WTm%BPwV8%-@y#lY>z3qmV%QR~BEKT`=$Q%PAzeL<3 z9kr2%mG}pS6Uhr>N>rXQyN*{I$Amm#c7_1~@D-j95vV?*w+g$=R9+>ea7<sC<v&Cc zGb~X4!5>D|fK{Z#+Z4O~Yz;iu^oGgDp#%6d9NYsUf|t%=<LLu{$QR(B03uH}=0)+q zSf+(!003Tq3yzq+YByz%7nW&YO&3GuA5*6+>u|LVCI^y%d`3JqAR=EfmO>(c>R3W5 z+=iioN4DRFVs%Ecx-$=0;6#KC!CP0oU~Q5#@NVuc2s^4pUWSqAgR^wkaLVb!9IG?o z1PCmW5U|!zi-4`8K&Y@-Ee|l&y9>ZTxk%Br6dyLsOn_Hb{WM!Z`lL;D!+!t(AOJ~3 zK~w`UqAOcTfk#dXZsHkhe?ED1l?k`+0TU66fn~gq$_j(Rr|D)3>^cUff>H#F^1~PB zAW0tcK@$C|N4&);GuW=1R4VshE;^r?QHwtaV3J>BbvtzWkEqU+3yn!)M11D5sH_Kh zAupE8{nPk&8g~j2B$P3TYwYm~zFuXVB3tP8l~%Ba(6e~UFWVWtTGo`}9iPUEB~0cG zDGw3FScmSiK*7osi@>O2KgkNXR9>c6gS!q|GZK*rc{q<928ZNM!;Fas11_htx+sSJ z7P_+qI!4DA0em3})og(#GF4u1Cm#YM2;Frzbq8yb`TEao&UyXEzy6hHK`g`3fm55S z+{cFt9u}ge8^Hzv!ey~HY_u&+z-jk*b>GN~L3`W}^dfc#*tNgV7rNFy4y)v?<ZhgP zSHw=2$-v__x`1ULy5VDckbXMP0e`Exkn?n}mU%a<8tvtv<gO2t!FdHcz;|hqz>=S< z?{3gtH)8$0Kz}oA1hBRF)HACg#lGbBPRN!b06|8#ox*0;tA*UJC54|hAtZPkY#Sfm zZ7WBl2=(dlg@8{70SZ!jJmY!4=hrs!8>G~yD43+)vv^-Y%J#YoqyTcMO2zddQktT* zt^-oc=MkpizLtiR_PTo5G4#N)!PP>pzGcoc>oF0&@gr>2zim{6Ts~>eg<ah3l)HsQ zp@arCUu31OyeXvV;rtY?tuHZr`ro0Xi6e`Ua$v=Ms=OV({`3D_E#&R>BLx`${@<{Q zx>NNf`mhvBQ?aJVQcNHii1>aa#VaO8gp6AS2mpxqU3lS@IkW0U6xDT^#si3ltAHGn z1;KLI4%qd|H4Jn4(10)1X9_J4k*}Z#<Ab3sI+-a{#xx0VSk(k@TsY%(d57dFA-lut zzprZoV-R2U-^O~&@Xx1UiFdJ7*SppnbO5x~*T!=m2zgNDX>SoJBA5fBGW;NZMNFRe z9tx(g{B^%%>DA`WeR;g(qJ*bw(m^+C^Q>_H_3;dCQeq`}Ku-lkpG!e8i5@HFatSw2 zUzFJku(a;6^kfr(Ag=vplQ|t3_VZe9F^fPQ#x*P;8Y1$9skC+^n-Dp?IwF=wSRvM} z08!C8<cu*ze|ZU|;3Gb+2=w7$jX;#~&?zH66gTKFn_KL~i9|)@xhjfT-AjAaUBoLE zAvw#M<V$3#`Zfvbs+->D{BnDfV|2WP@7CwW$l^hian7==7!T23G>($1F!y_Wi$D%u zQI#A}=v=kEB`q$F7fg?^Fjj(My$0kd)L|%h&(M6r+@2=ut11RnT^a&RcR~^qurTZu zk^ex3vyw%lI5`)%igczCy=+|^8o2o6c;s24l=GO~Da2TJgl=ZCgPWG{l3<Su=A#nH zqAorz#o;5C@ug`qEfivJ8;*B}uSi%w4Jg1P*@LsAm4HMs-|7V1B_txGC#mICE-?bm z6bu7|sLBf%zyP4DYEdo%+0g^B`EwF)6ySgVN9v7XF1KtqD_2(6qTK(Ze&w)|b)rll zvTOs_7d<~Dco%iVDMIHX#WhsvJVHDW5@DQuYLOI&h2-wWz-dx3tY)JZutZDZV|hFz z$ku0a{qneeFkU(nDY^T0_Q*6pfu=CGVM8kQy_UpQkWw|DFcBi3$xj|98M;oOSS5VF zFQmv3DO0+o?-tj{dw_90A8s_|5`4!dPf-m>8L{a|$(h4vdx?}y4dAN`TaVXfYiQSW zdLF5Ye1McxfH6gM3`MB;CU;#Zz;BRpjq7`)WFG-WO04=(!)^M*zLtiRc53glrDb03 z`XjE7CJB3?F2k|LPFXVZH+Kp;^vZ1e<GLZ`VpukfC3tUkiqJiguj`*^OEWxf&oHt$ zm&46Y@%F#OhN}WRav>nDXzI+s(m#Bb7So0-?3QN7BJ13+;;sPmf%o610RON5B^X%F z*x@-y*_IXpvjnJ4bEQR|CdO(tgC)4&G4N1T8G;PD5Vck!Ljt65DK2#5OwCu3>5fCS z5Ys3uh840KT)@deT^?K}u2C}m1!nM8q5?$X%&?PnsnN^N>;Z&oHusQ&$>Ofi%ma=$ z!BfwzW{p$2b@Q>xnF#l#Rkz{TLIsxh&%9kCVOd;bk6KyDd9Ve(I^>u3Zu;}WY$i)! zgp1FriUBVbg$yk3J%&4u)FpgBpA<ue@2!~uHs;G6touU7jLcwgNg3i77|0}Gg$Sk^ zxFR*ef@T*Mp4Ru*TAmG&hh+}K4P#DjqQg_Ru+(XXvI^#qp%|75r~-Y8C3R-2J?NSc zn@IDVxA~UrYAR2#sK*s2yB`lPLYUk?4xd%-*Q`>eq?Zt^r2%8q#25{I++r)B@IE~) z%dTaN@HVM-)?)W1StkXZQ&;!=8McmQ|6@yP3%}v%h3fVYYqK}P1g1t!BWewllf!iz zyLt6rMJP7vGK8PUMWh%ZXQ+5BM0E)0T+|Ar)piW;=-9#K%o!}TbT9%9Tyg=fbdSKw z-v@rpR-h9i4~s0&SV%~Mk35+|l_GK6lNpqDs^NWgN)86-ZMy8(aO62xp)zt5G;$+* z1ryE|A{1%=$hp}bi|_=Sa5M7z%^F$w?g0kySi&%jRSwz|!ROsi=V|AvI=m|WeEoB= z3K5ZC|N2*AFbQ%d4%09n;WMof3nWP(AgBqM(6x$my9pUC&9I{D;AU!!wC5%&au7k1 z4O`q2d-i9oV%^h;S;CG+6Ato59wekvc>`WfaxORNl2n=nZ?-TBTZ?Y|Ex^9^W;3FZ zaGAev!-{$%P&ZaKl1~rt5OF&J8qL$<9JZQwdWcF+YE^Bm{JTskxHo@(yoU`0%na+S z@^{arN`@x+d4I%>$+<7~mwFIK_mL7RbK1DPAx?y{mc&9MU+44eY`8{>zaX<85rH<m z(FiHQgN>GHJFhpD7$`TCrD=>8($LHYXlzvK0-d{<x7coOLnQ<G3@I-2^wCa8>BHVE zq<Kw40cNDsk)=@ueO}&kvr~2sw%?<!Z#0c=T&=~+Rm5>))a8QvC?ltM953aC1SKp3 zYa&JSwJ?7k@#Wg^!jXa<bbe?{bZD`zlAabEBFESwAhw3drxG0upZMY@3h<ALV6AXC z^<aAFmz}Am**%u!Mon#-OGeRL!0<TGFLS}-Vfk`wCb9P1s~+Z;$uxFAJPi{joPG&c z+k-pSHMqQ`gju9EybzwfE{cwPiOIE#sDA12j6PApm&ik4amXqvD`-ofA|c#_jhwf) zdY_+_Fa3|o!z)w|@s<gY<@0ogWCcMyqi-%(+b;v*6v0Ed2U5z`s`7>GkglRnu^@AZ zij03&(C@;CX@v^l;RXL-N~z^Z2EUlD`VWz(;7c`V7a~uZ&kELE-x?oW+0m-%J}9qr zs*j8d)m2hvKn7G~ten+lc~F?&Cj53^HoUuGC0K+0lV&-W=Tu%E>O0k1Uk$-i<Ud8M zA-JfDK3Oe+en~itb!8I|j|TrwDz`N-hl=}bSHU#RWkOzFift|Q0eumRSNG&Q-o?CX zqA&5Jc)>&D=^ps?@We`rmUZVV1wVbdJ!nE9<K>n(QwZqrUUL7#()-QQ!7;aLDWed< zSM3`AD0jj_%Kgt_N#pnu{c;3_m5QXv<t$x3d|hveaYmg_E5WK#+`=!BhdF9hMV=8< zW=1o!RSc0AVD&H-gVwoH7}oU<pFJ2VI<WYj)dJvh|1f|1+7GcARRmv}y$2NXRB^mx zMc~(k#Cc(xV)&m9E)6cX0J|b0c$_uu2zL6aX6ETUYCy2On$9SeiuiIBF68^+Y!=I? zAOI{U#q(V-RYS#E0UGe~o+L@9Dby2;W!VIWE_)4LEi?HR?`#+N@<Swm;C3t91&_6l zJjZxM*~D~ui>NKrtpKYgtv=Gax{`r)sEwIHWt6)w!kVzWxmIz%(0@!ajxDA$t-2{@ zwK#B=MZ{(0AqtggE_is4xGmN*bR`w9lpz$VCVsG(PiA`Apg3o<11QZfWg)U0%^Y7` ziDmgXboh8Y<<~${Rb0!H#Vf9^Bs+#Vy)#@lMQ9fB?#c;gLSsTN@J<ivs8iy#C<*8^ z>~gvI$)DLXg_ItKj*J3x$f!WcQ(fk>tV>b)jf!c3kfK5n6Cp($sf+EoT0T)1(ACNl zpra-V_EcreTuGjrCP8DKY>?FAaewkqtL&0MaArFtqFj2y<ONbJ{~YiQZtdGmjO3c( z(%)DX!ru}p2K8!i6;}KnURsrX<C<#`GViKOr@mK-blLpT_4Xw~Fd0|d1nPeUDafa$ z+jcqlw(OKR0GDIKo?E*fRl$~Nx>%~U%1Gg16P^kAcKKcim#<be{(uy%3#mqpYyzYq zlle{wm7%fX-LSIl6eilfilB;VFtAuYm}H0$!u>!r^~z!@H>5C~I7?B7XR=}hP6x+S z`v~NF%t+?S6`d!B&&Aa%m<+d={BS{NhJdTWbY5AC^NSrq$4H@XT|e^x|Lgx1dC6Gf z>_f1`riTaB2v$h5JfQxSu1L#AhPB8r6P|642@K#%Fa-~I^&^*u7EwMeuvuUgUl0*% z4?7#i%SyteIwZE4@e*A@=}Q288lmG$hKfEE0z9pp555Et`NEju-a^qQGPCz#1$V%1 zG!NLuOJoHxJ|U3t68XXcl#Me)UY7nUUn0|z=q7+CFl2nme3)GZVx_8}f(cANFuw#7 zvcNSBTnixj0G>7zg^U+4RRBCyWZ)t4Fi?cPH>~tI5c$#qOgvsI-WW1eUV>Fc=?PgC zfL2+rl@M!+frl9XGHt<10-EGuCp=!TU{}F-IbHk*);KG$77tZGp3s#WvjVMOqD%Bt z#V^$-FklKmBqxNc$0C7M1Y<%M-m}=4V2QB5FrT&rfhY8?6ipHNCHes7idpckdSe+~ zArls?2;jB2h(;;0MQr*U@H$m%990=BCwzE<-cuH-IJlO>(8TC5RbCd&xTd$rQWRrC zUOM6W^%FXDl@VGP0c1V|x)vg)%sga7kdhlp7lDbNf1qtLzFdn~CFmXybu@)S_;j8y z=nM;WS7=JcJuy~AB?ms1`ti%z)FYE@EjH|F6J9~Tp>Nwl9>_qlX^{|P()3mprHSAw z%6Oj`Q$^hU{uFsEeM#rA?XYrCQ%9Xf+m;g>T;-pbEymMrH!lEQU};$8HjCsBM5u~7 z;d$Y`IQ(p$4O|cZ88*aeLFW0@dSrTGCyPur=`{nnRh)av3d=X-K1}p<Xv62DA`;*- zm*<2$R3o%_ps>e<EaQhO(M9kNM1Us}?=u_r7~y$MEIS2QEGFtoZ{gZ6>)=>C>IH!; z`=dNv|98U;#Pd@gcF(Her&Fx}z{8s=dycV8!51KqN3rCqKEU#<=o=64zcYCxMOF8` zr@J-n=<cC!B0l0T63o}%!;S9)y8@hlvYH*Aa#CE%J(dmaS{ZVz-QyG~{Ve^5rd<^H z`U^XlQEw2S>1pi>FHo2!)a&i7dKoPQV<Z3@^zx(szr8bCk{m~_s9!Kr-DX<;|65f- zxE_23z{spt$!zp+kM;C)W=4?2N_Y5{51jq5DG%-Gw$XXKY;WBrLN7mTX2x1gD8HMo zlaEq>+jUl3QJi0+OaEPc`aCF){nLbJ>>l!cZjALSrSZlm^}IzHfRRFZUUsyec^Z_5 zChU4+MXUAN;VX;h#L^IKgA%Ja4_W%>&!+X>i-?uw=G&^@pUWE3`ullM_J%AU-Uj6? z9jwP!_L;DzjYu!QM@?IL{LwKeXG1==W$6RRIw;36gk;llo}5lbTVU$<gYxN-KCP7g z@yG3J+3_Nxuxr2Ppk&-ie|<dm9*#lDC)wtNcW7H{A1=Fm{^$Vlh*SIgV*cIEmG&dW zPnCO|U;i=}=)e9e&cE#R*EHd93fHSvDJDE`Nf^qIVK6Op(9;_CHPD^ov*KS($Edi| zO%pA_i9bMyr+%HQL<)EQY$hg%;9YJ}faQf2jr1X=;fR`T5`MHgfm_l$9|L+pEptwI zT54Fl-FNUERtL+Eba@&c6&cgqj8*fn)1S@)k|Dq_qw$5P6a=I<ruhK77as&x@&x#T z<WyFXTixcB25@sr_G5^+@hjX2!@DL&*0Z732)b?``mLI*znC>7<HmDDAeNCUO+zM> zgg2&rXxw3Cot`Jfj}krlTKz?@$W>!;4i%4J;;bcOQ)%UzFl++ckt9X|mHG0yZQV8Q z=(iTN1vT+{&KP&R5XS#F4!`{1)Aulodew-5zDk6(yi?nILM?fK+l@VElDtHRj+}5~ znn8VJ0^#X)8x@h444bUOrFq}7tcrT~qG^HXxXR+~i{)zDYi2|b*H%}4@~@8(CMxJj z*UjZM96ItY%XRK}wk=6m&sx;qYO?Mshy#L1Z0?rT(OzrQZIv<s__&LB_M_1qP%F^b zz9so^dI9dxVaLyqE$H{okBXoac<Dk$E~4nz=k99f{m<PM_jQXULgLT<dFZZ|63;Vo zMVS2+uUE57%`$;OM8CpqVF04?u4DpD42nEt@fWdWA{AVxuZr46<`-xUS;oCDlWlhO z*M}XPm3$dPGrT;XZ{a%Z%pwA0U>lSlV9z?sMg+3@Cp~F)esL@0h2}14pZGoo`0MY# zn<HXqxw<NcSX{@O0^B5z@X;+@8u@v9-<`3$i$lBY(s8%7W)iGy)~JMJm4TxTM41zx z^t~FsRUu5VRnnOFc-g1qU}a+R&0$1)n+|LzWt+}<#-X*FE~d+|He_?duBSydFog;^ z+L9j*TTh&*M^KCB9cZ&-ksX1QYDzyFF&nxq2+LS622$&=^*8%4ZDQ+(hV-loT|C|< zYQ9Npl(n7sWcPNLhma!VyzDv(*jo3f5ASaIXp3dw@UG9Xt?Ow07J1Elu(d6VRd&|~ z*9ExF!*x*hrMeHw`moD~vHk7021WECZdUg}Iqvdw-(yfR8mo<IbKb7&oEJP+ef@sc z?Uq5w@V(v;d~V1&yZWG<R^Q)QDd&gJhV)j?zK(zogJQdeKC1EO@;u_smbPeZKQ%Po zmi9(*rQ9~C+^+UJcXxWb)l!%$e6w|nwdwok?lIDT{O^CA3v`&#?Vs@avD0POPuyW3 zJxOdAnC3zn8G63lFE_(}%IzzPp(Eds=FA*N2*BcQR5iylwkwQ*%_KkUOtj4J>5e5a z9qy>pW6zw|oHC}>;whQj*V--kH_22x<*zus2h5w>51Xb8mAfR#HUm;j&K5?^Zk-}i zMhWQAV^`GOSQ;XhQZ*(PL?Q*T`a*)JS~ljZUJpGTS57$$bVuuQM`<1@4<Qyd+oy}2 zmBz(Aouam_D>j;*=jpEnh$>7)QB|4YIe)3#5xc7Hy>0I38bYrp%8qjifncaut}-)3 zXaoSqBAl^jsilq%ue^-(mCOpA^5BG-bJac7)io_F-6hlKoSV42U>u$;=_Vu|g&XTd zWy~0(_7c?*PHXqjmwKM?^m1v=X5sP}F5mfj7@?LxWU97|begH=wuZD<tR?-@?4!Q# z&-IJRZ0Bxm*Q?E=U+1im&|P7pnRQdd;+f%^D}ETaTqk{2bE>IsbKad|^9APaDvB9- z!lUd~|5oz|(%u%|Y3AA^-5YIsRE57DdJi;3+7Hn#s}rU_bl0dw8RHez!c!cyPu%X( z>~Sc=5~8Ty-hVngS%crSXD;l6qUa;CD2=+@)W6<GGv9R92W^p6$L2Y=zXfDxN{+jo z4=zTe8CkE&dbvM9?@xFIBW+KvUfL}O#bV3V>%d9QLw^m*(iuO1{{ML-BvE6`-)@<T z?eUV@{{1W?B0bU%!M<%v<~fq?>v^TtMLL@MT>8^)nn|`i+cN#TNVWEeiOaUs@b&q& z_0QRge#fmSOZ-LqJe>7Bx#j+F*{%k}K8X**j6UD+&_(qh+xPoTBb}jQ--o3ueilpB zW%TD~s()(+ZscqI@nNJ|u{hRk4apnphd+fsi$>=!e@$0{m?!Od@`S7v?A;n7AyI5I z<lDA1y)=>|<n+M9{HdF!Q@0$iym*h49QZh0pDwHMmFGb@ud@xxsRDhTV6qJg9=7Eg zlq_4QpC-vsuxel*l>XQ!eNg_%N~!<&aZpCt=XLw~M!T$L1jqdCm9kCa^UCMfw`ShW zt)m57X;Ta<Da`LRB%9+7ar3tZ1sMUi_UF=p-)vtN&Sp`gPz_}um8_4ih96hW|DHcn zfXD6L0A@%upWD<_)hr&?0nOALMMKT0EM9&Z&TK7`(BDJ1R4DAw#k??UH&9i)>b%_o zkMRnv&0Yz2s2cbBhMVj1iTW<?*!<4V0Yh~l%BjXH|H^X>a~qb$IZE7fVa&=Xsv`5H zc?(g<9aViqqe`d!LWar=i}MgDRBw@qVfBP3AUf42j6In<8@j_rI2*rx?RY1CHT#)4 zA-^IGl_`4fc!j7$T~Ywelw<?_<?kdBor+en)l9p7SOA5;^IqY2JVf3enW-Xr`v+a= zeM`I?tt79NJ%S|<M`ouH)i2kZRiLmiNZdmOI?R}FE}Aw8f0;EvRb>p3J1d-oaB0G~ zjl1=~HS~&r$Q0SkGG-lfiTUkMTe508Lj^W?mMxX}6`_6BN$)t#vC(_Qr1H#MmG<1u zCfs}t9d}&V^yOcuDeH~^k<0Q9H-(tqen{#kAj938eTqxQBm?M%+{L<>{;nC6@{XCV z{jW7oJOaPHMRZ*zewX+1lYBM*J&khT#?`)xczIta@1W@_-!^IC*NInk9ej#F#@l03 zJdxF_;zH~5@JIv^E45|LDO&GcSsqnYZ2}|8HRIM&cimhZ4w{<2{Y?^@aV(qD$-4_k zha$9iX=w$!&hE+-30G{P0~U<nmhCw;rmWs=%k{TL9?xy#6@|flLTko!XnF_QDZs6( z{$>-{dq7pN&Y$HjV;Og!)|W_Zurcl`DmqtV(c^XOYcoTDRV}kaXnuBtr|>$`eztq7 zPJc;ZQQ=w!=NkV9E9GZ0q1fu~I1YJEKG;t}bl%yFdrxX!&0uSN7r46_P1<!(e|Z+s zaok$gE98@Je|<D+ZP(0P9*-^ci=1x2Ym1&9>0?8-4s5^4`S9G3Z`+awC?9XyPyN;* zSd_i*RfTrh2V<`sKOSwtHx22R^(|M^)vAUp3Wle-LQ>K=Te1Imtfte9cJxnm{`#?_ zE$zy--gA;XHZx8)_CUpK(Kmy#Up54@o>Fm!?@7PH*$}BWY0qz_QkzMLln)KD!sT`D za~wz^#W}ZIJsc1{(DQpQolptD_8zd5lRvK%mGkIioe5?4TKh;tzLm#8`L-d_jx)B) zma^0T^216|{WK`4J*HEAn#%LdTj_q*$?(vY_Gq=%`oZq{#eITB4xm{w#;46zzuCT? z^z7%2>tjRyZ}~F?Sl<;#q<K;m&S|FYxaoYT2!`s^w5CVPLmbyQEV0BWbxJ*Bu*Dr3 zrbZ2tma{<=`ttb90Vq62m5Y7hSO)d{Ktp8afl7-4*BRlF;f(GgR2YphWSU{5JKGG4 zhK(QXOl3-x_Y|3;cjQ^I?_E_*R8{@MHrke8Cf@4miG>wI!ni4-qVG5_xI!|HdP1pb z_&PT|^7a7qIw?GpSd4nXxO<>0v|buWZ%B-YbQ3`Y^_dswu;n^jQWPCNX0B~F5BYrT z33=H*f-uX6E%hpkaP-)~Fadw03<OoV{G8Fu!+NQNH#a<Gi(*X4nDexdEA%BYeNz}S zG)*4^(U*HgMnc!<w=$}W)xs6=Dpr1udFSj^DAdk<?igPU4|%Jw)dD|C@2iw-aicpA zB*aaN%_wJ?#$<ZtV$8@8W(QWODtLC=m}V`Fjf&t7fiCCCwk^Ke@BM@_hq$E$YMWX) zYeXSy-E6|Uby52SmhP+HtT)n*$=#_tzi$)ry?!wQUtQa}x`$7s6ORM<SSIM&tq#Pn zi9j(!Ym!U~Wky}klQX^SnH_+JH5E;=vB=CSO6((2GEW}xZ{1}Ht~DZ)UKa5Y(G7jP zu3D$zAmecj@urz>qc*>Wm)6Mk-irzEhdZ%O{V31sc-hO^*S;lt_gx8^hC;2UQZ!p) znAW>NyUz;OKbP64Vm>>5+@Vw50a;Z>E6BaQ@9i$L4*9B}z@;f4=PEHrl^N#lp=zn= zbXs_Y$Ze{AcRAJFWAh`q<G25QlnGLf42O~Kb}b?HE?<pA*4xJ<7wjibyp3JWNQeFX zk9GY=6>I$s`saO=n#|wa$95%l(Y4OMLPi^n8hs%BAU-_LgS7Uj|7TQJymosUuo79f z+*jLW&%1u^y=Q^2Ye!qh_F1%RHX@rV!8S}!H`8Ohj;CGbnuNlVB3y|mPYu~+>-Iy; z3G8<;0qJ~_{)A7qQ;qU4dm84HN*8xFS?=0~<{N!YJ{+ak`(x8;TI;m*7OZ>uqsAWA zjQZo_aZhhc*MH(jSI=oFi>iP0;I}{S+eQ9&q*16k^VJnKDBEQpSIYT;{!;j4F#m9l z@X(OfbuH}U&~~3Dm~KhzY7ML!={mvMO+D7Hl*LeX;B`JfPk4E{tgNr{)NHpmR5Yab z|AR7rZpHnVTlbFKZ=)DT-|!z_b4w%i_YPhD5r0?)=|8L4&2JW#Z&EKeCwlo<jRL%{ zHk>xgrw0+a4s0>HLuF#9hh_mHciB&U@vQY2Jn7T~;5k|(&y&L9krjq5rKd-VUXpI2 zm`&V?=NUsZ{2?KpzR04#q^r=gPGvmb&n0-NCDXF{naDu)>@Vw|D<)xP(=nCu6@jYm zE$q>=r3q)uo{2aYtiaOp))#N4B0OFrN0&#*X3dpcFcVQ$HzY+fbl;+vMbkk<#WRZ8 zxWhl0tI4%BK)p(kV>OB=($7>>Z~-sXVcDdnHOgQTl4}3}7luhhK~#cTUC1*hXVogN z<#me0R8~^}G#^G4!@aL{xWBij3LB6q)6;#~*#Xi^vxJ5b%GC79nRYYjTVA+c)$3|R zmY~}M4DF84mj2E9_Co%*=byYqMd8sM$W(z@2RqYT=*yC6L8jp4tHYErnbvxN${eK= z`n0sfLV$eb))vz&3M{!d#qeBK9$ne4qiuh$z^yJQ-0}M!=~`(#UE%jY$Cr4>>s9jv zefwTBRUiW#?qdRH8(Z*+r%k%TC9;b8tP+;_07Q(rX+(Hqs0wtxtaO{1F<pNS#U7Rt z*^bZLxhRFIICi$9_QzNqv~17SUFqwXi*ZyW@RBOo7R2<$I0O&fmBmZ*=+kPoU2(XZ z(&-f%o$YB6Zk}(!%wE>U3o%jM3j-HI3u$|iEh~g;dUn@2?tSQ6BB<;fWGXw`9<96X z7T9Jxh&edeY2$GnYlV07uwy<96Nsm8gZhfKom00KqixHc?k+R@#pgEh<cApGzy9_m zpYNXv(<}L7H}*zeh4wm*4@w^9`p@mr`v1pC<F0!|oY(Tp<?me^SqlE-ebGOi=}*tr zmyYDK27P^A$7P@7THlVkVKd~go;bHZ{m17yFDvV1RgO-OKJ}JtCVBH-qia<vfRY3s zdap~s4}-Gy{Aa5Ec8c?7isRPy{i1#DwasU{>@r1{2aFeA?}`tD@}U7CLoa%DG~|0J z`OzesPf}{$I?GqFKG&LGY)zuOfAPDAX&JpVe&hcWkF^Q?WG{~Wr0@BEbi+(91&_99 z@^o!eDfMYkwtjf*;nqvrl*T6ur?hA2D<w;nZ`OrP-C84Auuar{pl}Y#_wE?UHl-y> zC4X8epEPPc24yviFN4w}r`q;qXRqtg$4}3{4NC75mDP^FDZohk^R^VUpMd9P+dsM9 zZrQ%3zmdN?4u05*f$y67Co#Z(qyWp`|BiY=Uh7Z|OW*_yc%fRfjRmpRRpgd&$;@-0 z7slH!WSK+}%AY$1=UvRBQbXr_dFdXB+P`rtSeEdxw7HA9DY|eM?sm5G)y80WQfo6S zxlUrTU}V0un?O8Ybh@v~S7eZe%o(Y##Eb5Dx@IdfbcqZZR;9vn9f!e0V>?7nAh)`Q ztITE2fw4w40-Q6;j#j(MFUvF^WQG{qXDh{v$#BE|^b&bzA&<!E6<ci>a#dx(l3K?w zTlHNJ?v={90tFOud(96I&As61#M2{q`1;Zd7G>uZ3clhUg#k>w(hb3Dyh_%Ko34L` z$sIEME~1zw9LE`(rR4GIJAi)0%hji)z;pNaLqHLUY@+7AJ_cSGcXL~6a-3cj$1AX` z-8RM5iWTdSF)CMpf6nc(l3S7v=#b0qtEk7aNomfs_S_>9Df_Mp{c6GXqwnUx1ST|O z*|cP$2SFhg_{;PC#IjwMzrH@aMDtuG-Y5FP_!Xj9x2{CK_hr40_Twv(a+Otny~}zX zOIp6PBCb;`4FNJSQYLs<y35XS%%yoCj}o@-ia>xmXC3QqdBr~`mh9bfab-h(#f7)- zy4)088?u-35KYZ|sc|l~x!xsKda0GnJ(h1``@iTPzsSpTle;_2%S+;&d5Lf%P6+_( zkT=i|$Ulwy(Oog_kFzTx7T~Hc-ti{d#@#hx^{jhQZ5xr3Pp+_U`g=V$VfDm*_W2hi zvtgH0MyWUv7~_62KPbR|tsa2z%#o`Ed7Rc~8mjK6Cw@eWP~DNKH8$~Ho6x^VqEfHL zwV!KeIG?AvATE+(bM|RM-*MTxwRe8Ki$7f!b^Rr+>-w2R6k8ke{5<W$510ME6S}O~ zu7;9jMbd?Bd0IR-Gask7cj-NR*On%pK4>F7?drxpD90B4c-c*@nyXTjGY!Y*`%OQI z`0&$kq!7PpHIGKWN2RDgK=TJg1rx6y3!~-JBYkejr?&L0_;t3`guOC)9kWZ1hCB_* zuI6PtMQ_L_KZxyts~XdjEe<u-+YlgU=F_0mGxUX@*Bo`(W2G#;vH$vUlzZ=e8Wb$O zxBY#o!2I+W|6rwb<#QR7xX$Al$Hvjy4{b>|u0Gb^zf;l?Y)#PuEQ7M_ifgxEY2ezB zM|JkQtr(x%|Az|jAGtt#J2b1pruIMLmF&HfmT!@Ykck9H6AFb)jSL@Q!4rW8zE*OB z%gsube8&XeIb~d!6@Dlt)p?c_WJ$V6FB4;6A$y2fq6%E9ka2kcvxI*yqKq&iGjVuk zruU$Td3vjR)mCj0_n;030Q0UKs&_4E4Cst_oFP`CG=o#UvQ6Yjm9SEpSxTf*k6JqG znO@MN#l=ZCZ;B^mO7X0xT(|#)>$Qlts{#$PxM*(Hb}6gSJ6oAXcRxea#FhA4G(|1( z5@f)0Vwto2Fl%qLH7sb$F`sH~E9%Z5YHu&NPb#eToq0Hpp@7VR3{w>g0~Yrqwd7>t z**1ONYS<IB$-sUvgNTyMIRI5ay-27lk~%z+R>d`W(UOb1X9vQj8m~ZL$b^h3I#sih zt*NpaVU=OW&MaN7SLe<&B8=0zG5q9_8Q_|eGqOmX<q%H2v2Ui3I>3r$f=o7JCs4Co z9hMyI`QHl7dVt&UWO_A^mJK+=ZsQ7ZR$7Bnl1U~*iYmwcm%dHsy2!hDv1nLIGvAKN zVJY2q5Ys2$9PaUt$h)TXN>dC(ZF3b3%W&p+7tw)8LA5-XPmkC>J#YEeT{&}P_4afz zF+LTECEA0vZoHS|3pMV3tW$XeG@MY}<HTo<wcb~Dda}7%6)*hE3ufnzI72YvskZ5) zmswWT7ttmY^zQ28o<8Imc9PwjllI+wg0Ik)2P{uSt<tG7BW*Q+*%J66_EF0!FnqwU zi-|v)8{$(HJ7LqSWe7hGl~D6=krNcnJ*r#AW(-J{{$4^DM51JO9`m2!wa~WG9}5xh zkr8$5;zuoyLUzi9V{J=IsJZ-Ohm}2QAloQw8;5jr$8z)9QIEFdFPkfVT{bEmemd!s zenb^}T2z8qgk9fqvop75w!*)Q=h4>deNZ+(?Nhv-G0M68d!8QbSJqzgH1k%r67I-( zYj2`;P!PL;?XIFVD9_6xJ+00`$<59iqS6<8=9qkJOADXY7!-3Q)f}}@3u|hvcg_}7 z-mERF^EwSY%;#}XQXj}Z%(-E{W4U#m8h2{`=b$u2OQRk{B~EK~r?VS%gz%iT@y?cH zl)<KQw?WAs?sKLhhkh88I31p%P#N)V%_%f%rS#z5Wl+XCD4$kJPWZ<`*)EGV)_2K! zrx*5b4oZLdO8QskpoFSlDF%BcHeFvU+e&#Hlz6ZlYdc%1jC!B8uYOJ2_h$RCzfiWU zV14_NFdd~v-Agg|LHWFWX$uDU-8boP@rPxQ{zGJH6zcGjwzc2|DOS40PsB$&{hX~B z#U;2QH{2pRvgwea0@1f%$_OWNcdaykW;LZnqy<LWSLGJ3#u?*hzPL7nm$YnV!04j( z9R(pxl87>@vQ+(vDSkyV;bAQePqR@I$!>}}qL+a&;6;ox*UDQgqwbhK)sXEn$L4{N z;^_>L_wwWkBeR#^;ks#sTW9FR2;Wz$<#NZN1ib8rbi<uR*-Zf5|0d20=31b|YJ_H{ z_B;HyBPG~SQH$+PA89~d?#E~Wl~KOVT)5#Wj?*Fu!3~XCvc6#Kf^Wz~q^=d2l0{ZT zMP6Q&+9G2Sg8|4$Uw|14PTiQ}eS3%W>9TT*x0zw*bSGXn35trmAfwzi#wBu#<;$_2 zjF}d8q}w$LE2`vsZ&Uzwi(Eukx+XB(l$HvlUUpdxKUT#%vhv2Xl=P9FDl)`s??!jI zo^k<q2$9<sktq;Uf=NgHbV#moKMwj{QPtKaNft5MoPo!Boych<DGBs=zh1X#hPBXd z*B<XdwABdy^i<f{Wb}&GzAcotlY19Ze3>5Cs-u<d_2^cW>E3!8%LJB7FTHjb8*DsI zub&a)j?{v-?#kt6zrS<l`H$6Cr>^*lFOD)qpryo5cj8KcX6BcP>R2n=W+K$P88J*- zeMM#J=q_=i<=T+z+v$YxUC%kNDZs6}mg|h>_nY}kx>6VILQFg_=`bTcEzWv$pi;ZN zB$5%N7KEkct+(>EtvY|G1N>JUiy;q6!t79%5bw-7UKmLKlsxG14`qk9m~b8Ia)?jv z|2&@J_nw3+xAJIis>xD1?c&_tPh_y(Vl$Yez?9h{mR_n0#u~~xACI=7cB2$A*P1Tq zmW_wYO7^p_-*l$g%szdR=d9Z<+gqKlq5M+okbcu|21OrxZ~2PmWf6g(I6Y>&1l;SC zbRk}kyKIA!48aH=y-zd^P_Pe58^Fw@vP_uNUD2I@@>201y#@@{LBX`ctJdn2d}@bo zUEOQmZo0>@QkI6KIIQ)P$#_`^!za{o^uD+HVNmj1V}@f?9)~SE^Lm{pC9t<ew?SDS zvh=-nM}#wGja^ST9P&u5l#nyS3Tl~dqwYY{%6cy1>eQ{D<IyyeGKM9i1ek4tt!EI+ zP^P6swVtp&K`CgDgR*QaO`FS2yC0ctlOJ*GPm#k9gA%{*lMTKGYo7^;H<wgB&*)vG zs#tc08LM8}aP&dRKb?cJOq{mRJ`769BsO7eOGl2upVR^V!!k%dFX8q?bq6_2Xh>bi zY#uO`ZNOqR?-E#bii!*i_xu&LD<v`lMnHTBsX8wgP^Ji`W%SiP|4K5p$4C!Dc<LkT z<u=Jxvk3bTQI*TQeId76idTEO2^ryxn^lbPhE*hX9nK!$7QM>9I$sq!eX~%B*yGGx zrEVsj8Ul?Syj?Jr7!fLIlVhmryF44sc<E`=JwFO6^!zRIN{17j7LM3cY9R_Kr?c6B z+@g06^Ha?}j6hI{{K+<axd?OUJ#k#ftay6>wrj)yRK_j$$OSlYVcu@pgn61qttQtq zXJt9|h*?`BQ*?-B$wnk<a{1L{M>~NS>ZO)vdsA8>sG+8as(6-H&&nW?7BY@P<ZaIC zUNXsNtrszh7whFa@KDT@`Cc}etiut?ftjT3G{Y4ziK3%k{ngFkf?u95+P<2po8v0t zA+PR3i?D`=c70h!F3S;x#h#PBG3z4BA$K0=T86odD85S6t{Kp6EN|7UQ=Qh@`*1?m z?K+k&PQ;Q3ptUhIAM-}ec^;X@{UeshZM(~Cn}auSs=^hFIp_4@^J9zByQbVr$}zRS zTYjrFHHW(gRAhSgU>O$TuATzDwNb<M!_$6dLoSJpAdaq=hNw$9{pIxXq<V1@BGSf7 zawA0zO;tg&?z%;;mZ&3Nc=b|(zI>OnT_LR{FcUE>Niuxg!#y8)uD1sL*28ph;abKt zt9+OElFjVh)yMsuU9r!XJogpn=(jn=OtlOJ8Q!dZnggBs7QwKu*#4+DbPB#;r|c7! ze9w~=tSM!+etO1}f=d3o7rJ=RH0(97WPQtdVOG9fDJ@B*CE05UCPT1@gW8;&=M_Rs zNl|7AGm8&zb<Q-4yYxK=>%TXRI!i^=E-C0wQX!O07~K@7Ra&h#@~QKOV1q7So|mn| z6iByuZddM|m|B^xPt_h^@58f7+#~CVcz5)~fq5Q_6hFeX$?}h6O33Wn)RWg%FP6gx zQ{mIoqCLPj_R>S;-UbD^$!BG<(N5^H+EAL-Gf*Gv#alyMUTsG+>v=_vR~!<I_Itl( z>IO%MX15Zj>SGxPW^?(8p3z9{TViDQ-5BfV+wAIt(!$6!JsjP22xu#1^*#HOL5W@} z4JumX`8dN?DON*%payQ+G2*DM#Xm=?KS7qm5XnR+*2%g*ZEuJ#fi{_!L0Pu1y-#WZ zs&9)k-t3WX^OFG<kC$Di$kGYhG5sQR9d75}4@wUWh)Ps>SxAI#WvbPQ>JUWbsu8Vj z{x4c3Y9(vFif=4hYU#OsWvw+I4Ya)_a)O@c7jA^_x6OCXr`_=P`Q|9@H-T@UrYwo* z9I8;6s<3RnDnqB0o4p3C_ak2jS|)BCq65A=FUQGoB<5~}u+S!dgJ5dpd56dtZd{ZZ z6+!Oi<avp{{Ek>|5r-?6xZTf^bq$rs{iAUfs1^GQ8GyN)-XS7KdM)iI)|p>4-%rq? zuGmPv)Cb~})a|zlh(g0JCB;Wv>Y1E?p|A|HmG<2%q40+25V>+6gztkRB9^n}o~deg zcxI|7bfyTXZZUNq@V@e`i>?p|d;r_aafD4Lu4dLG_sbnJhgFmHK2}d(tac!%5WyU` z%9wJw12N1szztEUU8q{@vHf9sky;FqOWpbE7EBq_?J6Zm4Z*E(_7Pn*02wkM7yMu^ zj?7(>dq-c{cZT^s`jt^fhC@equfDCqur5nDj$l<~j@YR$QOjdIO)~dMs3Uxqy6>5v zjYSON6df`zoucXNF194y&076quh6WlO7VIQ=hb@Va>nH2?x~f1eriAM+cxyr{^VZ& zl)gQy&rClx-0iygitjtVP0?4(<diZIO4P$$d`u-xi`RgiGMGVUM7)$))>4<a1_Wb5 z6o@2VI)+>rva0T}*!`zF4n%61?5{3!tkvFKr7FZ?EQ6kVKrFrCi!l?4#KzT<OSkUA zSi4JyRkc#RMRm@!9*bAn76@*5>gn|7jJKw{ig*!U40tYOdACE#w7|@GwOaw|?OlHR zjxAo%C_JvWhKT5;KJGnk`MZ=U{mAUyi4~O_?<%z1y7XA(=}Vz)Htq*zthF)=Nj^R; zy43BD_m7k9o8G;CuKsrWvhDT`YE!e!R$E!vKUuqU=BwE!_2ztCIqCDUM@#MP?-_X} zZ@)P|@v^Z!XS(vYUBT|JwpV1GEBbkSc`om*-An&=e4TDF?P1;K_S45gY<TvZj@_1i zW6HgN(30v~p$m`xOi*8~abx!TUALEI_M2MgzS$mo>dx$#e3O%xUY1T@7yJDB^?T7( zKLX3{&f(~Dyy!2y=D(WS4NLj$?{z1yx*Jlw@U1`l_u@NJi%wpgc6{B2|G-(%gmwFZ z<l5za``?^a8&GuF;`jgg{HM$ef8C$&{#Igoo!Px`$2iZ@S6}wlegA!rZK;d)*QB@m zclvCpdA9wT&6+8t96>S~@^Q5iDKG2PYnQHh{CjtE(G&B`+?&6bmp*M5bo~9h;n~9H zjOVJ4e(YK;rC8W@rgN|2&f2ZjzpMfym*xGdcqjKW?AW*S<$ByL0!|!?qr_+!&^aA^ c`rq`QQA#Z?E2HvCBLfh4y85}Sb4q9e0B7jgB>(^b literal 0 HcmV?d00001 diff --git a/public/images/sites/templates/gallery-for-lynx-light.png b/public/images/sites/templates/gallery-for-lynx-light.png new file mode 100644 index 0000000000000000000000000000000000000000..9dfd278985684287e5ea1651d69930f0540001c3 GIT binary patch literal 613188 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∨^^ZfnTCx2f=Du}VlH5iQU{;;e zGozW&O1pOK+F}2&9bv!!qu71|U&5F5O4?P=^r^}u{DTDW0VK1k`y4r(A@y`uW-<v9 z0C7hrlhCTJHH#~n>22}$B>rMsuC3!dE1pPe`KWDUL@9+ubqh@=R*v6sAdtziBooIj zbiE$nz+aJx?K|}LR5Iz6VBIy!Of0f7UBK|U5fM|ZZQZ#JX_>vZmbgveSkDJROJri! zdc|r$OARgSfQVEPVXoZT5!FkVK}%bIhL4)aRZMV^UMholOQl&8nH)1RDNcPo`{Sa; z%@j#ElL--vbaynD@_<Z8i0{CJH{_OmO;C;ZQn9!xiQWa~LyAjUFq4cOk&bx~9b`tX zF5ky9)z`$;df!ST6IJ4jOl*rA=g(wPf|*0z#a*$t&P<$hrygBd0vIdb*bh-6^ib_+ zhw7Kb_N(~_HzAlg%+N6AbeMg?9IB=~bAH%qbF8Tgo)9tgh~rZ#`HRzK2V^3FNqjO@ zHpa)S3YP^6;RQ0N$)*#1gMG#HVUQFnl=)fhrc9uWBl_!;iq^Wwz3?n5E#tT@<AO9h zA_-!bZP3HroMBh~gf52mOOG$Ke?bIX7%I^(BFQ)(cI?9BWX7_(5_Z8~lz>Dqb?Nm? z%uZxZY<wEc@s`(y0a*iCG0wynlLgDp+av+I0tg&8{b|P23u+9eYKHxBaIk7=9%z<L zY8UdZXku^`?u6vokw3Gq^oc@V%?^DbUDaqun23No0fi7GdBhD|E<2J=79s9tA4#ne zNL&Gyh<T&^nGIpU<LxQF3zF~oEEHuq)ybQCJbER&(j+#kk?)=GuJo97&%&<*GP|X_ zer2fCd#{fQfwnV1%cXig8yfymE9+>-r0ONveh|{3s;p}G#o9T6-tzW)fgC|p_8544 zcqk%|Oym#~p#;Ar<SFurr6y)Hpb481r6yBsSlY?K8OSEa=;KnfWi!G+){K53{9+Ol z8Hxf8?0`+Y5SG#`0wh%!>U+oCFdH1^Kv;#;3GiV)X#uTWL5k`1#f2?U6)qehtn1g3 zggeo9KFfM)%IL$lbdazqV(Zio#)w4?e=XA^)NC^{5w?eI=B)Y*S1*vDrFS}L+>2+0 zYH5VZq)<2u;yOFUX+^~F<U=xXxj#m$YI3_N>UpQ8n>(_6sD|w!$IcJz-CjYgWB(A5 zDB|0~G@B0sLQ^tfUx7j%vL4SH5FH%78BX`UKOs+MsG8GmY1Ubk!@@Hh_c|@?SC9#A zdrW-I7pNAV-Xd`~l2AC2T_&|d;(XwH*b5{-&{HmrYVzBOpBo2oQ&b2;K=IEjY^5|U z2?fzS2*ON$ARF;?4OdqZkx}c24)%#aJdI4oGYDlbv(1kI8YT-C;q?5dqe3lTF~xFJ z-V#y`@wyHs5B(j_0YMY<RI*GH;NIR-{L{?nXoWb>oOO(w(y%1;sWupe!}&GtreR}+ z`}RsI-V2htXVamhFEy3v|C8|1u^V}!g>*cOvt8{b2(^A+{Xba26m^xr8(EdhwyHX% zY`XGIiAbV_73VC=!L&><n-JTu{R+noEHVj|-hZK;HsKX-PS}(yJyv7KzEA*Jn5y)- zPqAwnALPp}VHx8h^b*81>`1_HJ95(LFvG5ns`euWAxgjm+>}I#lPW4x*)?q$2wJXi zwiV;5K|l&P_K^~GGqPIbedR@3Lf>Z6l$}%3%MOL<#UibeVL?bG4#<h=ndh@h(G8HE zjyoYkb3epQ@v=&ZOt3I}v;Bp#hhfV&C@DM`xg=EY7bUqw^5&D%Bg2t47VYaCN!g<r z5&C$VW{9u=?;7~P$6W7kgVc*?PZ|`V8O*oP*MhwHr~YOO$FWIZ2#+xp1*-3a!F{;+ zm*HZ|5oa|?S}u+05=3%{6r$3_UqK|mR?%j;H11?*iu1%%N_(!jsskEUhJ`8f5fJe$ z)G*J-zN-Qpr%sXqefydSp0$AJqIyLSQ)jButG!FYb=6q1{1;p?S|G+44F^DcJ~*tV z@-k+*BtY6MJtzQlAx}&d$ODlef0*1l*UC6@#8k?%cdqdl3rVWsH0UQGi^IHX?VwV$ zlxTw>TLfEgcyWye!;avTu<km;oq<eT8$oPG9r&C~0Mf5TOEQUS0)p=J;PbKA;I7$> z^Wm?V&xq}M;Q5Kwtv)ItSxj1`R&cmU&kI0^R<$1u93+#}mm-o$t{H><12rVcUo=*1 zd>E-9qGd*d1kBTb1nf#BTL*0SP3Z(1WX*(rn8lsK0yCMUktcJ7DIMWw|3uQhzV@1G zh9>`wLO+U${%(&?Neu-ws)D^1OUw>%#lwJwvV1{o6<zkxz+H8zM_5cpO0{+p8%J!3 zV7kW`Ljj||g-u9}!Uk%yg0m&HgERpS8|gioPnbMGVqv4M?G#MW=pGCOw75a=TcYDv zFfBIVL&OC3hdoTsIzHN&i<@$yqVNJU;ZKkL4L-?OJ0BGu21AlL12_T_LtFbbW~&Yk zrF<7f#6n&@p5msM`DTS(OojU{d%gg0PBPE4m4?*<6RtXfm4pOR4-z1wLo9-cVTL$= z<$J2GSaV%N3^UNQUb#nfHl%1|XfB1?uLmy0IvV~mautf~E1|@QU4($BDr-Ctg0nQm zy6eCp0Sb0Rht=NiLbP$K=72W+Y}(KrHh)ihJ-V;^I(NHF31FI?rb&8!uxgF{W~xB6 zXMo)m3ez*0Tm!dQ1IzmWt3;O&7TCqwg<97Ld}-EhrjVDPt19jwA2#*{21JTgll(9( zI0u!}HbJCC&4_|U%q`LFxesy_zuyDw@di4lj)^LJk>{W~*X|LC&{D^j-t&Py!BW6B zkV*^K?xD;Cm!$L0Z@{`=$U7)PL3tJus!}_v;>}B5yEKeal;xypsAPv2b2;!-_Amxi zIlOxN00>hEy@2LAM)?J5z~FogWb8*5z4wHL1Ug9wSxC0p9mpgMJ?Kqx#W4rC;*NCf zdA=#Ed26|0JsQ>Ge8{-2W=%libW_t6sjS$T_N>Fx+&4%K46}?NEuV(r$3(%eRhwO# zWP^eqz7ztiu%SK&NR3QpXxXb4s}2*;5|5}U8bJATo9!8y7<Ns`#IW7CRl)>zGI=Lj zYNH<RP3=O~3h<x8ghqXUg<BN*_A&FBqh){ID*ARGW6K_wsvB*IWT~&1O*S2VX;Vfr ziQ$n*CaQ}^CaDmG-84jka?11!TCVzA5Rt{8o-^U=Y(6PIcG3^CmpC^1Gcf{1{H{5h z*BVz~g$Cng$8#OpzXuh9X-wAthRe<f6(e}KD^OD{-^D-en2tz0zrbr0I98kw>q#`t zE}O!FRcBViJ_OUVVUfTGn}utS6Za-_k<OG&_QeG6q}HC!XIys4KBGC96Be}krVy=W zl!mo(1{MO-<A0LK*f~#MgpmQU!!idG7eQ^ii3Lq3OQS!)E;D`sv4@&i$Zr`wV=FM- zlr*fp0uC54&5D&wX4n;&sNh&QHUqPjp3zn#3tC;MtxfHT+|Q=vyG`w}7$vkPj$c6l zrx*yoSQ4+f5W?N*eDKBTE%Jp;cU|GJtWm9|sZtqxuCKj{2BR=1C~0DhC|OkdTb*hI zQD2vR1XH`N%;Gp<H@mC0kXK4FQ{y~5Pr*4E78*A&R>CvMe6{bZg7BCG5s64fKAc)x zvpqKnW0ui69FeD!%mHLFN-Q6Ly-NZ1xMc=;Ls?a?B|AZGi#?+mUstWb1Kd-;A`|iJ z@Z!i9Q0tiWfn*Jg5%cac446XZlqA6M3M?sG=!vi#%M_3OFPNS<JQ)Bf%rm<nhBr^= zqwwY`i}U%6<BM{Z)CvN69c3Nw6c!?lt%%=hk)>!m&ymvRf^NlrGA$eR$}oY>)vN~9 z$%UJODA6WhjV>(6M26jOs3k7IyB&lyYFUXzgt=NfmbiL$42)8W4Cgw&wL$}UwCBO# z##L+^D54#hd_DVoz=yy+2EMb%vHkA}nS2Xcu6wJRKTt;wuZ#8Rm6rOlTAvorFM-LZ zRHNG_87tJ(9qe%$o6g$Du-NpQHF{;rR4s%}rVckrt%rW%`0BMiH4%3qJL7;>#|WLT zZG0IxXF|(|7b4^+W?7A8oYLsPH_>^8?F>{;_#9ho^L%cP$pjPzo<QIasp&*M%tTFu z4vi^wH2>sOur469VVxw^^Oq)z7`i!~k2EU)<_om*bW9#jvt6l|&w!a=>GHuso@@6p zR27G40!I7s4mz-|0P}()kxC$AMLNYskCa(~iO(zUd9cPx8h*4XJuBW~*;uO~%=@Sn zi~SZYX_l|;Yc>UBm=HYjRe%_h+y@<4G?gld=U)8f0WDxm@)XPj%M!bct*gR0H3Qjk zf2bAGNMn}NFrV$ovQPI5Gk1{W)8{~mB3ged4Xdfwf~Miog*z;Qtd{*8Oyne9u*xlz z_Frbk0-*~-Ot-G}gZm&p)Rblc2>li2k%60xGzEm?Ak#&_L$ktwCrt;<$9qchUJe>- zP(Rv~$GCR_CJ#tuloEtkm37RgJv|!C>a<6zM0<C|NI&3urw3Sd`W6x5V2dUl5@uZJ zg{ps-OYmJaUY3dTkXC0yo5pI}h=@vA8xnf>?%Y99$|lkS<Vr!5GLzVR&<t#N@nov? z^Z_=Dz)TG|;bLck8%%imV#Cp{4pB>nVb?T#rzb7fPiRR7=4DTw10vi*e+LJeST&}+ zn<ChmS#2JUc-vZtQn?lsjBbFA>E*K*N#qzgk%DY7PBIjl&u)Qu_v991NcK1-=FP&= z^rP8w!OXRW&=kf94yK5Ht-<of)Uuk=I;0HtafzNr%Sk)-@IXxI8O1N{69(t;tUW-B zgq+N$_r;beel~R4NGvlDv8$-Zq9<*)tML=`7__0l@-k;2U6UsSgkqI&aH0;c+f2rB zRjMm91JDF5$3-~Rw;#T{x|Qdd9&m?{Bj-x$viY3os2vby*hCK`H$FFzr25;|BY(}c z6n*gS>S8b*s^BG%vUT=V3u)N~+Y6dI+cPJamS&rTr|GcM7Y8d?2zfa9q&y-7`>#gA z^P~PTVN>RAmgWA3)q}!;C(#rA!m7M6p&%oP04(Q7{>-vJvnf{H;A=N!=skf*!iHT> zNWkZ`5SD%VV%!w5Vyn-<vhtlm&0$869}b&pUyZQXy#e<G0eNCa*xaFbqOEj4D+f)p z<8^wC5$p&^N;1NK8E$AlGqK{Sb8&(hN|VwAdm&{5<;>@lt8ZpsWX2JVULoz&_+b6k zB%g*26&ap^#q7m1*aZ?v!tc1GR$}uREJ!3j$g4gqq(3}9r#|5NAO(1d5UYaW5_fm@ z?l-&`9y_su04uamYLWG@JfvHU-&&ZoWhKQzoX^(*(t<xRv{<=P6K);=vN+Y;%sC|q zJ{9RqcRk+}<4U845ZIh@xRdn};nQV1nU9?iGiH&Bk)Dk&aq;mL5DOa1c0X+n)EAGz zE2BjNGDB8mvH}Db;UOSs!4-(QfsiUvGag_U+FX0F=p~MfM{Jz#nXvV>WHPmGx)RP7 z1+Zi?r%FY4Rxj+?OM0Iy!a_{OT2_Ta*f1)tx-8~)9z{E`=!}zvJrA;4T_?Mlp78`f zAq-e3&I&{UIpJL=*nWmxtbm^E$O(2O0<`4n8pc3j;_Re&;tHkR(o9&({1SPs;Z|q9 z2c>Hpw<PPM#FlPljszc+g{<e}gtV~~80Ga;`)p&SpRq>^_(L*BO?P36dQz~P5%pd) z7fNsc=|;wGu4oB{MZJ0L90W_??7K;X$omCl2xPnq!>){{>rEjU*LJo_eID_#$&27S z{Yo%-tWY&*n2cv-0<hVWMnE|JX|)Wd5;FvUrTIu5hGh>4_m^0gWdJ07P^aA!zj}ID z>ju(Vi5KxyZL+eu%~b$PJHm1jWiUz?X|qmVTxqj{fKV!{Mk^Ja!*`iyU!Gb4AWLq^ z*;0wY6(C0PVATT-qrYLZRSpk##{hFH@7LSNXZ|mO?IK8RplDf;^t{V3lL|fwmb5jf ziVthZi{JCGTE{d;n=cLMj|ZF}o+d>~VHPy#!#dc0Cr@D)Ag2T`{$sHFU}f2NovQ2W z{cVtlXln3gZ6+a^<Oz#{j#67xS)YH=WDzewt!6wiOtL<KZ4fhMVZFx;2uoS|(;g(f zoSJ0#r1jYdNaLZcp~_K6gLXti_^b-f$*{BefIzT(vG?8Km83YW$<YQi;ynB;w4f%B z7%a*`pl!ezAY-Lazq4lj?U!Xe9`+syqhncLXLKWDVvoVX@FWQLecBX}H}6RJC?A6? z`xGEV!k(ftrA=L^o)ha;!LSuT<mtF6y5GrVEenN;PaFN6kjeRrb23o}j#0D;BGls5 zi-&T}4UL6_Kvje9wa{oUoD=qv&1ek*6To7fitJ3q<PIkjNYJSsKqI}@g=n=;-Gc+8 zY?!&$dCcdqwkNy`I>%0SbN!;JnxSK%8oXP55i#2kaY(d2W5TD{uGH7hWDda;p4>jZ zc*<lt9RPNP1_vheSnHHRlWgs;y)fwpe;j5W><gUUWk^Ya(T3erwJ}To#N0b)a2z4M zdBUAcwL=YAENzNOqOcgNV;}`(N*ve6YGGKd6!f8u$C-s#2-t~=jufAFluq-(6$2Q9 z!gjKoG6f`jD0H2`BBLk6S`b#+nv)kvRS5?(q_@}vGMM%*I6}rOv&l*_+*(J#dV!*e zSl^OL>|JEVB3VD=z*xFJ*=#05LYaMMLCgYM1MFWd!nS9YcFN!bOn@xbYEJUg$7FG9 zLGorRz$4yE)1gsj9L+LvpCNgCH{(ydwE`2LU&$5t9*5JIL(7;Du*NXqla==GLP-4d zIWQzS8d|eSibYZ;*gjo~Ca3XYBT)Io_-c544%IZV7E`hMeo4410BFXyWkjkuco_S8 zV?!2uUEMIcHQ5<-7FYA_*ZUOUY_l2UNP?~BlNZywn8}@9JhzAd1^UsBbyH#_jOShl z2faR^N{iO(ntd^OIU+1x`ej6Vd@(^ZB%PXHS3~?KrFwg;%NX&6S#g-D1=H>58(!29 zbn23Q6JA0E8l7PlTa(NL|8zhoT9}}^j0X^op=%M4$*Q*JkN6_T0me-+F<tOj8xwyf zGjUAAXP79K<33^ZV$#3;jteMxSU<O>*d=h@k8-U)qJ!I}VA-Tz9wsgTHrnwDD=<Th zbXsBibUvt}jAwa@92?05Y>1Ie;9IONDCio(kLEM@_BCqV%8%uoZ3f<@{0kSstrAXL z490j}tB}gdD&9#y)VUX~DQdFu(;*)leV(`}HsNV#Xu_^zAZOdn%$MVW>wg6pvQ$uJ zq)R8cCD@D!3uIVL$s~kwHA&PK);J_kYuJ(1X#$VwX%h1R1p@qH7|y#c^Ym)>ENqA% z#&R1jRnbMXY%7Hu+pd`5cm^HmdRic#R|Zl9^@5yQx``m~@kCWHR^Jj_y~}GFb_HhJ z$dq%q+A+0Cc=~QtKCB_BEWH*$cV}o-eD57F+Y!Q2v`8TKS+tVGl)@#LC!5lS#n>Dz zJ7=Qy3P~Ppin+LPwvct@U`iM*fXR?AU7y_)lfJz4mx*CCte%PWC)maQby!$S*8z(* zRyfnOWfT;j#4g=>LDp0iK(Dg|`$DjZ!??zv7y}!NFRwdq%zvPU^}x<+cY9j?<il8W z(M2XAH?@r2#oLpHU9%H&I=YJn&{{>{lxM3}rQE=<j#YH`==W6-hlE`wLu%P=AJ(em z)L}c)scDL_3Aa$tw|&chZ``*6R|HY2ebFF&5L9m%g$HOM%kFe2)OO#i{hvhm#}`Qp z*2?VeWLUNTGKTPg261wrNK{Xp<VO}{nd%xtw{)a`@byjwm?)40N=T(QIOAD!1qV-$ zZxXl_Mbo6E5FA(bKq$dV@GW#gVkUYtNA)An<0zmhR>Ou_yq241Ojc(6XlxRSSrCv; zDS)`Bf#4FGq)3HZAzao8(4fp9?1Ze-*V<rjS}s!&i~b^&IkZ0k!#2Ybq)ow4B9vW% zZOj+Htxv8xh9a}Tcaj#-5^&LM0dpV*Z*%)Km1v*pW*t9;G2DI75?$3-J}vO|kbZ-- z;1N&|e@C6CxTqJ`Q@m%I{un#cdh|YrbC+<zaYshg#X3c?QV0`odce1gSu+ZxT}Voc zbcAmQx!BRI?sQO$hwdo}ky2uX5!8xIBtPS_Y<I{vS(i!cb@M1yAvf6iUW+*j*w@pe zD6x!L|EPq09OH6}g75pHP6JO9V%D<88a(Dg84T77vE_u3Hobn_vSLx-MS@H?aT{zr zXvN+{$+#*yFR&{(9upHLGON51MPQybhlE|?VtQW*uzmDm?@2r|IXhwzQ)I%4g}MR4 zS0e$U@Amk{k$1gc`?cx0f@H#do6;UaPC`8u>S_4>MJtZdY=UzsT&OaYM3Ul?@fcL4 z<yfue5H4PZ<xu|Sjr4#?+G^JbrnOVjpdr&?xZ*tfYz4a$6|kycYeRsTl=M26D7lnt zUZkR>j35SHaK)f=QU<fmb~A0t^vK@gmKBmZdorz_>ZKB&^?zWi>Js#m4yMf(E1V&i zcBrYDj0f*R0HhLK;@tv0K2m^~4XZ&YGF3_umb?O`YlD58DX3v3g2@2ph+T-*16v@C zzw5>dwnIVLW>rlr)P9TN9el;wq6R9nC`GGuZHlf+K@8l0&33uKE@#oHSD8f)x6l|^ zd9kG5lQLt9?F=C~ZY8m*$JU|8bS>+5rM#l4l-~4fomdoVMA`mYl~dp|Jrq=%v)by7 zqcSmV)Jy$aV@_KNv)9MtiE({Qeo$_}y1(SiAzG`^vWA*`!VoJQW4&_7!?h+W6kjy{ z!?Ay%8-r}v2&QR9WDPG-z)PIp<V>6pvUf~nEg&|i9qRvu@=NbkfVpip%Jf7UUQ#<? zEX*w!02-0?Y@BGA5$*m|kh&!Pg?ryi=Rx9R<6)oED4-2C4Ct^Q|5y{#<=5W5rm+Ji zm6;3>>>7e~n2Sm(<|e|y&9b{_qR0fqj1pL9xFVYQMP^5l-cOh|gIHX3H;q?U-Y3J_ z_Uj_lt9o)P+#izu1;o9iYq`p#=RK>qV9CSA8V0dA7*MQPr6^TX{8p8&5eSH7*lU+b zHukV~Q&$R!CVotYRZ^5<=RK$Su<r;&)9B!A^0aDK#wL0$K>lL4Q?rR97F|;MT1gRO z6P*pUWo-6|Lq+f=$Qk~SF9>1dK?B54u8?&sCKCavH^cO>+Es7Qq^XwHERLu)^H;|W zv3Pael)fcfZz9F0|D+vZpr$9t1kuUkJ5({~RWvFyabSHzZ_j=(cP`J4;l#XYlw(IQ zsmN6jyVCk>-JHZ|nN~>@$;66*_x|&BW)HO^WJC2%lXLXy*ilIiSV`kuz_{F+WA!AJ z4BAws=kc;^D%D{PPmDvxW%oasvRB3Y001BWNkl<Zh`DxU+DW*ouyqCON@ze_KnHU{ zu+zI*k&#Um=?d_j%pT&Di&5M-RdM0ZZyAn>j#I^BRgzLs;gt`$G+A9h?N{>wchrpq zY1qWvX@hYY9&V4s$UrhaFwV!M^JdV|!VPQXA82wkRhZqRW<RjMRf#rFB1j+v&M?@{ z+=*mHuT}vbdg1bb1NlnJXzEG{n}WB{Pw23Yr3cPyzabze`J&MAo1mJ;L{Ul5X)aPQ z@nGp=)PVsI3Kbj|^H1MR+GD!V-9&cM#ajzN7+0XiuM|!5K^=Ipn{(^{aX^m0n!<t_ zG86S?5B^%$e@sJ0iFCRtFdnwIN!aD8!r{7>zYC7;K0t<LaAQc^kug}(z#({GT*eU- z;+kh`qxI*S#M(i}BXmx3czv>l*q3Xz$c+Hme5#`f7-5-tGKPr;SSE;?41c<qT~>jY zkbC&o+YjS+?NBg1BH{DuN^F*gyVhT`pp!t;*wHo}-<p35qu<A4k^RJUSfZ!UpZtql z@5}+l%TG<B<dh$Av9L!Ae9f@VS)QpiVunL@^59i<ek5R^4M_*jNGcXnaUOGmHdK(A zcpAPx1BA?er9?F^MKFF;g~;abwd7BedzvsVBh9a_#Qw&PYNxQ6?w*gOX8<vgt4ye| z6B>xo4`NQju=>j5`3(6I*0^hsFXvyxTHjbee~Mj`s)pRFZirc%hx*&83-?1<K(Qo@ z?L4^>8jO7x@FSMp@fRi&HW9Ef)<UsnhlQ97AC0|6DM%_Us1`~w>GXnxk)Zx&GC{sC z6jY!*?;$?0#J_W|`7vX{&oM4iOcSEb!vT0qhFrs9raIHd9u$i@CzJ8vbc^9XZsr%? zEIdshz%S1nXXtr@;>C?V+){0hDM;j&0w`UGHj;~mdA1)dlezXE1z$ArB9&cjjysZG z66WZ>m$urnY2ZfNuVz}c03w-`Myz0gD&mH%MseLhxhWG+*Q-@VZT&oawV@iETfLDJ zqWpS@5Yfh5rMCiVlOU3fxu``_-xYxfjv7P#+ZRzJu*ukbQ0^36u8aP&Il*>tmkF71 zGhlu)?TIdenU?Nx?~;I694DnJ^3VXt6qbZtwkez5Y&MjGix5|_cu1qI;EEVGrBbtY zHRmTEzIysmCaY#S99}eVX$%6QhFx`-PjA{JzA3g`ZBq`|5sber$_er8GZO&z_N&AP zZi;kOttMvYfRy-?T4Qtr)M{)ZaogywH+F6*qCRA^n7d=PW2RK?W8B37LsXN6x@nIs zdYpw2p9THl5J97SJ6fxg+Kld&iVG{vyUQ)Egw?@oMu($FA+$k=tw8B^S2x{O!!GKT z7ofg|TV~M>4$*VUw7F34b0LXL*ul!t!ir8TOdH8XJcL+}wqA*_szFw<-9^fAQ^ZN0 z!Tc(Pgt~d1tBPr67XW+W#9oKNSrw=r=cA+{1$@Y6%dSOC+k(nCdWf(%r9kR?WhRYx zIEZ(E7t&H_O7f$?nJf_>e%gMd0<2dk`E6Din|dWG+)r_{qr1WC!LV$es2b>#PE^6v zEe(**5MnNhVdjQbbo4EOvygQ@{=ihCYL{W&0f0O+A88#~Az9awf<#B2UYJKjnq%uG zNs-!$WOjFVGZZk^i=Qs84SUaG<s8KkkUc(@(xO(4DC~<H)E%zS^rtbiX7}wZUTh{T zG7qlMVR`Q?m52GvtZ+n{X*0&ITSSMfw2Ljw*SsiXS|S5>QFM%)@B$OLQUsJ?$Z9^y zxb09O*5*A=kcnAO7~_i|@>@{GN@OyH#n5m6dNMKWQfh6ra*5V&0UEfZrEz-b=;-m) zg@{C>O+~E?v!O>a8SNSa480Pi2W&fuG47_|E98YDHgf&6i9(y?Wrs9%L4uv57Bh>- z(_*a6GaWuG4i*oB<mH%NmNn$d4yCpe6ISO5!}6;4Jl3=`SvGa`NGiRGece#lx@c)E zy_m7w9)47K?D5qkDvo60^9DkQ%BPS97a)t{^&;!<P1ek@0Nb!9s@$^EAZjE!T4!il zkxYD>dir`g=n;$1l$jzvC~k@=J@^c!G3P1(jD}bHacUlw^iks>5>U=REx=XMlGtv_ z<oEf$5SjeSrny;m94>|%Lls3eKElUI-zB0kzYdK}T}~K{$~<3zDWZ-hIpbr}XEntx z<Ubr2CvS?9;~YuSreNnbOSPNsCc!gln@|K5EzV!^mkDry7ir#X;9&WK=}HQ76=5MB zMrl8c9*f5$&-jce$)|j-^i~TaVq9vhhg4&Qq7)_GShtBrwkd$FLa-FJ<m0ADh8If@ zh7^4aZ=M{@W|8tKy9^2Q_YbO^!+qhca))>8upfmZcU(G_7*~K$Mc4RK86UMZtTa6( z0%%hVw=pZ=Fm7NAXehmw#$-bWLmLTa6jQ)B`Ux2Svn2V*n?GLlZP$k?z=8`j1{jzl zM)L9I<i9$QIIa{5ZD~Q%<#BO(E~cn36p!N9r5H*|rccFGGl+AE0(To>hA5s6r_v0g zk8VOI-kh_AL{^i8%>FcgQ2}x6_ft*0bX$*b#N0eDz_?gf92V;VoC2a#uu#UT7DrUf z9suGQq@^#QR1jO4dh-|$35y>e!NFvG53H^E#dxV^2nVEDNpmBO@rnt<)*22qqKsW( zC?Szr6*o8!%LI#@79q^X>Ys^Qpxrbsu24OLT^d=GzQ|BOAz-`J?mt-{d7e!A^Hjs8 zD0U$rbL&c~Bq3=3LVi`qH^pm94sD!=VQo_~womzcClf0b1zJi7p=_l`BS`F+(|K*t zJ}`+pQ8f3!jN--2(gL$BFp{3>`RQl5ZjE)G2#fugOxVPcSPpGUCVBi(u0rdK2?0XO z`RJ1&dBnKo>_gvpso5ogN#H05nN%Uu-jmHJp_T=<V3T=pt&65C1(1i5$o<ZG<=) zq5-Ic?5kTXW4WU=XDj56rR*)%Mh0tO5~p-7+)Z**j7C5LF!q;VS++K$<9saPaGa02 z0VbP*yP1?0+|B9gO}E1`pEHyI$SIPr)(oSn`K%}=wG|juP36+d-893Z(f&-6`G!rA znhzAmuF+(Sgm17&e9_2c)E{hmD-s(4QG0aU6cw!0{a80A6N$qz3K+@$tF|7u2@ad$ z!L9>#A!>n2J75=X0K06U;-r4Ihnz4&{w=DM3~}9zw(JHFE9@yk%1&@`B+r{-`4<(W z)^%XBL>jam@dLWuDKKr)4*`;R<|?e1fB<IAy#+sKFM@^6;yZ+$x$z_HBB&BKUKnX* zHM+ulU`oE`7SF<3{l{2wifF5vcEqzy(L~YQi{#;^OiBKvUB!E^_bI@FRu;QlUetgw z=n$2YMi_pyRT_td<HQAysev3s7$b(T1%eWAdq#CX7|2CvR57xB4t^O;EDM1c0SR8^ z1niK!!K}GC&VHf|d-1t$D4nd8K+7|>%9-Bd3!xqnH(JNNlGzdv>49gSc&e;(x(LHZ zz1N@1s{`ytuEvS%*SX>o0SSSfq3COlB}VH51^mi`pEvrG)s9EF{Fe6LjpAxUB$e+~ zeoh{(w5K*8P-q!gQeLI;N1o0TzI8?>YwRLx&^cSb>7tn=r~g#6L={m4tLC7R&lC*X zoOJ+Ah_#lsS@S$u9}c)UJT~k;CY1%W3>%v8P0>IFCU#9Gm)x*r%8Y7mQf@p%3>Fb% zo6vK}#GPT6-A)Idn{b^3uz-Nqc9;>9Gls`4;ndMgA4C4In6r%xwawT9N$gWgKK~7u zN_7Ig<=ka72(>)WpqOC-Glwy8SD_2p+FC5CovOjX5v5(XAdGly0&5d3uyPfJVcl1g z=7WpCVLo13FQp3O-o>aH?D02V0%$Oai%De{h)@IcgmTO$n$Cx2n?n9kls?05u2*k* z$*S!z=uvWA%ttpaAPL~Vt(9oO3!jgAs;9eYJd9149)0^yZc1BuEI+nF+O{btNHQg{ zZ{E$RRf76g21u=CS2z|0?TJR(t!kr%1I*m-GMdhHQ@r%9%?UJTzl&b+#pTAVv?*#d zXEVV-G32loXeF`g7`hjvwmDxCBzddKp#!?6Fra}Smm?I2T@V?H>rEmS(KZ@87=o6i zID27)MLKE;g%=UE!ZC%LqPr>h;%ZY6MH8G>^LZn~Sf3BWe3HEtu*(f<cJvdVu0Rt| z+cNSUA&LzAnN5-Lp3~Y)Xn5!KP7m-HBI~v^M-BixHtXnBWd;#y92ObzO3+NA8>>dA zdlqs?NV3-3rXg_BTUC7t9|@NXf5BU2b^sfsk*kIWQf#Dh*^Wyds2TlEHXs}WWF`hk zSmLD15hJS4FXP(jM<U|IzKkJ-4!fwCd4}0MXyE!^HXUMW<ZEv`M-V^_t#oZCO_Zs7 z)O2hN%WOIYy9}N-vFDnqF=etoQHI2Ef)9DHm>}Zi{Q@`j3<-s23)`_v;(oD}Wn%6{ zvw3`-hdC!O>*DS?nIvV#{u2GMv-yap*~FP-Tg(J4Z6mxcj-i42kPQj7XKz=0Nu)PS zo)F7GChU~nu|4aeBbgXQB7Loxo)LIA?X`GpZI{$Uh}n*K`s;Y1RU+&iLuG$>ve%22 z$wYN8wBM$;#}s@foB;!w=s)M}=;k7V?QFNtu}3od;7i8kO0OB4n3#JFaN#qn)_X2{ zJ&lihp+apgcZToM@UBHag*j?wd-P_5>@ye-kP^oj{%R%1#m+b`l;a~zCLVKzFrs9r zUtom~$LJoP*o^Qc|1d1tXiBppb3A+A21Hn9h}5s-Ahiue6(zmM!;6#4*V)5vlgS4S z<trp<mm>+pwiqvB6;5Vb`3<`{*%a8p$!4W;@x!pDk}r|ugv7piH&>Ur?vtGq`xJ)x z2<mwKG0kTlz9^=m7=y|uX%!7I;0dpg`KC;+zA3Ykc(!O5vfJf^3CZ&`;EMpjg(*rr znPvREfnYe>ew_Ho>_Y+yu*#H>%eE$Yf)k3-EZCnHL6dp}gj{)^VVB8Q$!4*-j2@?a zGC5A?fRN`=j`J}Iv*_`g1UWYkHJJ#csWLkqRxqXX;Dk03*F<leSOcHF-X8)D5k9O% zv_l5YG)vpUch>{wVJ+HWJp0FYE$whx7%;e<wGE6ddu5iMeBV{{sgtS=b|%^P0YZ6R zw6La%J2NnZdnry6q(f`z8Q_s6De7Q8VL0BpgIfr;V}`P@KK&o&h;ZB68jxND#eTs` zm9rPk4uUL+lR=jZgzzqFYG$(`cAtaUv{C~Y20Ipeb3!-_d$Jg7bc>j}Xt}8x&KIIv z^8&QFd3Dyls!7d2K-RYep8<`FwL_psO^^Psh5)LSwNMtf`lo!h;iD@wz$~vhASbY_ z$mA4B?0whvr={R0hjv#+arF!h(vs#k1zJO44|j#d)~7{Zdgu|7$#igW>>{f=ULTQ3 zyD0&ssi-I0qAjL+qohp@!v;2j{U@!f$8>?rSP5d52l#;xcOo7r8aSC)5z%iVlMI?h z)SIhn-89uqwHgA(02+o&zf<E)*U6!Na_f8!=PyFmfMbgywx?9s8w{x^$NJMyq$9f} z>zV}4CwwmPbi*-oiSi#J^vY(j9+_qCxFFPHSMxcMU*Gd$iJvy;w6^H<Ln~k9<N2IF z@XaqyG$k<x$gPRSOi5@4ZYw2~^&&Z2ytBQ2h+T_u`)_4|57vEp`tE4@^!apscs?(U zO&x548nIa9L4e`(TFbiA%a1=9{)g9lNdDx-hr78X`MDq>sZhnqu#4NvnlBmzL5j3- z(^hEk=y<W+oTCs?)c}^0*B8GtPE3XezF||&uQDU~cFi~C{W|bF6=3t02nh5lxlW9Z z_QOK(@?oKFN|%o<DqveJhX&AV&l1M6v{)agC(fmpJG%79LvyN3YVg9fs%eIR`>>F; zQgrcG9vEl?sJ1D^%GQXb&M*LN^N_K|QP3G@>%EaiHzvZO?V!XQ5$CPptZGZ@TvdA^ zG-sXDOS><!H9kpYlZwJ;C#VQpABBu(Tv#W(6TG2pW-=c~Vz)k&=t0%ethD0SXsEOF zB+F(z!LCs4bGTCLJh0~xLrKzcOAbw&RL;n%{R$JGpyde~SWMA5nXH`B-$W)z?>>%c z@>l|N{G>LLVeH9nw&6LMv=Ve`Ekh%5`zD50HNOe84zogwb6ph4#6~tt*-E-fXrRDK z6-T)h{$SPL>9E>z)~U}z-P$k5@Q!_S13-*SDA5-x!P-qqBAHko(Ft}vLnc~uG#pZA zr-?|fBwRRk|3ch&CJXwjE>q^?l-K~7g2|^ZQY4V^_Dp8Ya&ni{*~`n1L+M6)eE4cU zqqlba>ae!H2+J2ezVu9TgesD0F$LI&Ti(BYKKkd^?&itr+5Z(%u~@T89_fH?VF6#_ z$)<$)1Ot_v?<R!NrrVrXZy1(T%5OOp9Q@&|3Z$Wy1&D&dRCHvm<nqj>Om}ldDf8Wo zaf=2?1*xpSy2WOeW)oxx^d09Ea$n=>l}Y6q_R8$VGISTPoNIbGB`y3*W+3ac()!h; zUc|Z{mI0jfJ2Z2i+)Tv+5+EmWX9*U9=L=NDvk({x*8J&wsIBq3++(bZG5BWOhc^(C zjGu%0b|d<g=_`FSQTAo+i02ph6f=y%0Tu?InI>G!j$<a=l;K`JP;ehd&d@ZT)#3F4 z*E<zpS^ORA#bMrpTGJVKafEFgR{NEkT;&NH_(qaSo0M-Es`~rH`ZE>T4dIgPp5mqg zmc*eXKB<dixipjx35i4b-(^fvlT^uYyev2d`HQ85^%AyLh;Uez6NEFzvUef{z107d zxF(WzCtFAWPw;oPS9^Sc@N})xQm3H4=}9p1lyMw<!}1~;)2vz)o*8_CP^Nn}L21QB zs$yl;WX}=1=oGu~LNbxoOIF#3Js@!$`&<baZcERwjLVM-ygrf%9=BL1_#q&Q2?AnS zs0c#wF9w%N>A30hcr&|eDj8~M#&8DgVs$c1MoW{4!wS+n4~Ik=s%7SwPdGiY+7wVP z8C!kW-Nc<%3@2SE4KRdnp)A#ibh^l~s9yiY;suc0rqe?~2a)y!ki-zoZ8Va+9TUi( zgj$|}5HmLg*plQWeZp&me8{CXg;9U=WYp>BQX<y#F9MRx4-;$|Z4n>XmI)-(UUIyZ zls~?8J|~M{9~xggT?7{!G{nPV#N1OI`}%mQ-d|uoU$dJrA;_w}X(t%QnFzqb{=6$E z-?k|y3wyo@XeOI(iapl!DDB`y%6397kL4>yO36rDXu*g6V%TM;k71XUlMHqWU^teF z<*CTI7=zHM`>sO7X^^ZmYoiC%42NDi6w)Htp$VrpBiq!y=$GZJt_^}RHS`2nR?`_I znWtYQ6Cse~71=b9vURWQJr^u=j@L-*kxdil4QqE!MZowvHbY8Sd+rqU`e9ZQOzQ~x zL0=$z3^Rlmp~!hY`QGV#RN7bGWVWoZCUZVaaG+oj1S5Iu)&ZOH7r5T300WkU`Uk1h z0i?)F+v?&;DeV`qjWMr>bvDgC3DApbSnsj|EqqexQFoGPHK~mWH#?O&v?^yQTu_U) zdF4#dUc^O1F~_xle%Q>h4Q9-IQ^~v6o9Q`*MMXz<;Yyef*?gqUxsO~x-0KbQ*x+I* zUQ?=oor$J^1O>()tuo0B0h^q#ben~?qikTZ^pbg!B2M*$V5-ihH#Yu7ZRxBTTK5Ze zMbv6z04&xZSDgb`q*MiCZ#_SV;QDEiji^XxIu>YUom6Uv%WLxX`LKm#w=`qRE$n-J zX}#kFy9dceMC|(oM~<Iu(Bn>$WS{tsnE-7Qi*HJ|Sa)E>2WjEs4I3{yi8&gq$%LOF z6QI5bNKP4&a96x28qm8CRS9Nw(W3~A(9VBKq;~>Xv>LWGvKtk-kVhKgL8Kb0x1GAg zT|v_|wqay|MFm`IoY<+LI3NKHdVsPPNLLSMqq|-oi$$zZ5T0-r@@lCEBwC+SnUqz# zLGQMr7Bb;%REF-O>|O#P=GI745|gpsuoi%AZWA5Qy9?@+Y)3*Qxpg;funXAyu&68= zUxbJXZ%QdvqeW{dlG2oS#l&uhAt>?d!nCrmf-4MZa_(X^4w0;Q6vwd;k1<cdR&|;= zjA|7H;hrrIE^$s4D#Ne{2zk5=9^WqJjuKnkTx320oMa~+Z7Vp9sq-zFX?Qjt6kbc5 zPn^I!z;(7M36T6^F*!4pZvepCiKJv6;nmu8<9v9IT@<5sA7EG9l&QMqE+d$;{xhU$ zbe|P3HpL=}aZ?hB@p4n1!Y-({6gFi_n^WvEMhCeP{(we=sa7K>LTLlvzV6i`8uFrX z+)X{X?VmQ_*h4;f5vQwx?j>!vfzNm%7@pTqy(y2G&U(B?%PGDa$s}=_AZ&~mW@4(y z*2QCmf?3zfG<nhFjxjPBlbEKA-NFy;dDHq}5qwDGUC~iDz1WsZt44<xO~|pHENNI+ z6M?m5%9zkg0FL$T2|lEWR;I)B^I(Nt<LZrNs1yDaIPX6GdY=N!lfU^dE?Ej>3Y=h7 z8teq(k@JRoIpLoY&UGAR*DNE467<Tp)7rYOTb&oMN-nRF@$~~nC>^?nky>UZ5*Hil zBf-ds`pyxUo7g8JwPh4Cs3^>Uj>~df<1z*>iukO&W(sgRhCXHx!EF)`o`C%qCjbGS zXg!-?Eto>OW`Rtzh?jG8GLlt;*~0r_Y($lS;ml?mqKzX`wHgG2L5>DAX#Ihx2&0ZF zs%0UEN^48xj?Kg|R|ZihI`)4#zz~#S@QD_D+L$~9Tt`DqwOyEMjy}>S$Yi=cXMmVM z6GI97P!xDLGj2{_%=DgZRb8DsBNLAQMR5%sq@&C<W$j7g8OS88KtKakOU-g`m1D#? z<)lCwL){J^7VMJgs74m+FvCJ8mX4bOrVYUlS@C)E{JZ=Lu^i@INh0-hCAo|L%p#?0 zY+5EqD3Cw`2P*?o$cTws=?91{;MZup%S+aOkINiH7IeZ)89QsDFNY_?iH73RaD;)$ zNvK%Tc9?pgf+-+?35Lw!QxVT)fTCYRtlb2+p_N*{6mtX^W5@*<XHLT}690sM+H6Cy z3B>IY9C0gT`-yQ=)Yw3V!D$dUTZu`EFf5w#_F-F-B+3~OWO~6Rm^LM$S<1fFr3h2# z`jVHTP}pFo6vk|Es#92W-3QaBZi)diU{^x<z?>7g0d_HN3U;8vpc12+uu3TAwCFJ? z`{x+t@r_=PuPuVs!GTlTHY{3rS-LoxQlrsI2unA`F7_xSmSWBZmD0q{Q-NIyN2=<C zl9vneCeq@EqX*}cOqQw&B5JXXGoq_|lVH6^vC72Jh?pd-<$*wE18J2_=LC|^;EZgr zZ4i*Wm9XSkL`gW96usIJ!|REJ@jn<NreDsoA23E%FvY02+Y9XTl*N)<-qJ+v_@P7^ zO7h{K36?<?e0Kqk59|YMU>c(-kn3m+ef1tXlx9br8)>Eop;1xF2ZJ#~>oYV(oJh3b zBV{v=o=C1pev9>SKOVf}e1B`b)RaSr7EMKFoqCk50BOBX+8M*8yJfKb;K@mU0!Uc) zU~a}+?gG*^$2$IsBtYC@KC`bP!Dv{l5wH{aRGoMP$Rssoxa)ld%w(u8HP-ILJ!?@| z7|NjIoB$1)xvchb<^7Z*kjbVJ*fZEQU_$&$jaIjTOmeSU(oVkVyD+S%Sos(&zY37m zT@dUnJ-}7Xw)D;UiH4yk=$(}6JsbI)<ewsw*^9=|>@=N)1Lb~?6<pAdoJ;;9Hkq8v zR_ms)2B(~_&k{@~LZ_&fg*F~xho->7uFf#{qNs%ICVZ5n(}e;(ju!1llX@pnY-KEz zolg^{O?q?b8lx1ZnDG3C5sx;#jvL%fe&BZY>H{3Y1SqC-avg?se>;1^w%f3nE5v)J zY%yPaVGHdsQ%etuVMbUgd^br~h6YgcVg)9L&VLq{u1{V-Yclco=pkSMkSXrjy8?im zZc3Y8UUtii=~B4#u&e+kmk5YpB1w-v(C~Y+VO1fMKa-mm)B`q1HI#!7A|cs0_;Yae z7(m8lHy1apz$C69h$iKPDPxzft!Trlrc_kW3#p5Y#fq+Z?*^_U%&;j|%P>?|*4dh! z9=3iBW}uXmU%CbCl87Xpskp&1pw4Cw81=Pc6PvI_NOg*k9&f@Bw$^G6Tck<pC~aU; zKZyJG0M3e=Q`Imk*6X44=9E;Ww6Zc#MbepJ<Bg*6es;^rS-AA>c!?jfc=bTBN+_EO z8%41Tqcveu_@Fdk*pvd93#`1W_1dh!uh1IUr-Dtn)W2ef!Uo5McReK2;>{k!g<DaW z=FF&_b3)K!3+P+%Vg0chAQskCoo#YFL;C=#%LKQasm)Ds#Ul1-i*HaAU2{WGjcg^A ze^{J<+E=(z<eh3i$GAMLo#D*9y#)u8lL?A6$iR)nK3@C%SOqu%6C!G~moA3~)60zT zkHfArp)K8o59I*J3V~ch>oYrsSN*ACs#|E@g@s9{s{pZl^I_4LD%6d8%)C*L4|mBM zymMemoc1V-fIt-lZehbr6bu3O;#9IH)Jq42M1W8y5@`>wC9a_zU%%SaEr&(N=X2wN zojo>2(NLnL4>!{M3=qWC$)$kwz=0${7;m*zt*u|P**F&=kOg+Lt0>$8*i6=+!-D7W zc;AA<$6E|s7|-m1Of1#PwG@$g*PnATG3=TG@*J6rulpwMAuKI_x5s{IuL3!p4-6}I z$i)nq$AFxZ$(qUV;l{g=?gAC;Z9WztumU7)inuvLWJT}Z^hAdp0Rb|Za0^8|u5Pmv z_w#}b%GkzMq&VH@%i`5xHAJ6wGC8*sanzLhK_E=j%Up%`9CqG`QmaEze$3SSW%mqH zAvvATH(zKau}Ez1)Ie>RS^xkb07*naR284(#jW#UQNuq^s7nld@Q*$IqBYUM6ylNV zo`5+%nRL0a6VC}O0wd7V?}B>iylYbTMXI$8TXY8qV`9<!(N1v=hz%lfH_v6nWFf+H zaKtXekn>GRAANQ{p;4JToS)oHG<nztP4VXh%qbvPuc5;0Cs#77nQ3EPJSl$^u?xv0 zxx^F6>xq{uW2a$foAMONugr@xkqrXQ0KIv(fF`^pDe>Vdk%I6r#~5cGv*lMf#_%^o zOG$(PN#m~mjI~<NK|s;@NmxkdU>1-9`1#C7(<!hhrWIjXw~C(b{W|wJU&*NPv1jPn z^`Qzd*^;3WpSlp8Tmp88bWLme*%$E^hINgPp-c(ieK0Jv!+L6CEFJD-*y%WyXPB^I zgvFi@<6w1b`%CG@Hsz0B1&E~}o&YjYS8?^Ma^tl1*;ma6?0NJ&<5RQo*|00*<N+2a z0I+=Q;gue4x#%?p#xDSwWX2*O%C9G!%D@zG!A*}MltH@!v4CuJM0_lnOmB~-^l3js zo5qvf4yS1F40b(3COp<m_FEoTH9a$8N507e(>de5*h=P(lmj4P0<l_tD&#%|#JIxr zBtv1Sk{y)U3_J`Qbd`tt!1&Sr4F#uJYIvb`L(S(#Ci4m$=T@^1xpaDF;NxV&HKAXR z+A!M{`NUz_DupK1YpS!gLNefsqp3}B!Rp0C4l|b7cTFm7h_nJT4r;E>4&@zcbhT@7 zM)b9@{Cs2V$rdoBXq5&HpRML<IGc)AuPm+9yvUh|ug%!o>jx}87Aikcq-*>Wor<EM zjZ1*3iBk)v+tAlwo(x;Ho=}_*%}e_-V}5T1GyoW9MQdq-UG`$iH#q_GeAt~>;_1H@ z@fqt2jM%l>&0$mAO;;QXs9RP9NZw=SC(xu}4<va@E|U>STs5;2Wl6Pj`{ryBb*agY zW1&z+6l@C8;eumys+!uSv;c=g4JQ?F65J#SmQ3<!Tmb9&cnL!)KGZPtbHs|vXf<gj z!1JjD(uUG5Djsl@NN;grm`q4G7hU!RcG==+NMp}e6+ATzXA0n3a^1~_6(xDW$h%SK zg;xbg9-ET-OrEp|eD(D{1=x}wb8&_sbF^bD_E27Jt?j{7;0~EEr`Hr|qIK446%o%2 zW;oR9$T<aMIgNHXAJod&kRTXTN|BIr_dvT~-r|JWgNV*vv;xs9SWW<u-2DtCT8@zP zNp?;hr14xbZ_)Zi&H(AvN2N@PAA)!uzDmgwHr_p_z;m-@T?2w_PNuO#i`Z;q3R7A@ zgChLMW0nYv==8e;1OmUwrB9QG!9^T5y1na%8LOD1Ii}}ivZ8kl?&XxfXS=pidM84U z2qx`(GnvfRHk6uMagvi2Fq?&sjJ%Y2#SpUo1D(&U??`&sYEAL%__QZaxuvJGjrIsH z8_@oYe0L@v`09=3g9cvJQ=<&;YcN~F*v2N>=|m-%#)9~DjtMIYlBGZU8?K~i8K>%z z@D`d#@fP|eX3;c0Y=iM|8>LIb>toczM>VP~RBBzUn?w*u8#0@zE|@}AVCIYUlu_%U zg|6u2mxnvXU^lO04QS7qf@XlAm}tL+L|;wOu)3);MZr>JyE=08>?cAQm%<mrge*>y z$P)Ils4&}2LF<5-rEF77n>q(`92VAxwZ3kc&rD0RlxbEb!eepDXRs^Lf-Sq9n=3F+ zhh^0?a6wi`lCg`FOaKm=Z3=$Th)mg3v`8i}HH~E%&xh-iNnRH8rLY*AwTz5p!C!UD zwn(?)G0BpSW)QKgs+I;_F9^^A#O_@ejm4s6B{(ryC4>fEVeh7M6NNxkcP$|<ND_)m zTmtXq#rg_Lo}m7*!!mmhNnZMQ^QNrj3W-9m420GrneA{aYuvyKt<}nh9gvlO2oDrR zEi`hSX=m@f-su5OIm#UdXJn_mg`6yHFxvwha1}k0!VY`Qr<n|bcr>$Whn*YKFTIw1 z@}FqewLWbRIhHaH_ct9Ni2eFe4BMU*^GJaBd|0noB2p*d?mL0conJ;CDW4N{{xXPI zV!|kVuEbN8OcE6@Nvbo1Z9}wxy({qi6p$ojs4gVdP;{)N0U45ho&g4S&cB&#F{B^F zqb@C_A9a>YQsC|aEt|nDW0!_}ds!fc0xDDaKohhS4TNIQayV8)2cUJ9g(zHIw2L)7 zGK~xc#tXBMl)>Yj$z=Gbh1L`z;hsWfMivgw`YY$yZfqo(=bt1KI}VYm;oXVz+-3z} zx|w|Zg!q4KlZOZ5`Xp)<)6iNnO0Bim+Uv%(W`6^7xQZWMd@k7I=iH$GT>@%3h!V*v zL*h&42`plwgMUu--IA5~W>^uP?p@1IWA0tZh6G@pw8_Ntbcw`W#eZ{{VzrsCQimt| zOYx@x)o~h&mor;n!t+HdkU_QBmAFPDO<~e0eqa>D#}jQTrz3z1oec?H;9=LGR;YEd zZgwcdXS|wjf(4JoLA(nNz@CPIXPPkzuslXfN8cGZ98Xq3@!1m@NJs>5&khllkAea= zM)5>gCn}$Vxfbyt_Jn1y#q=VO@yDU0!bAs9<uFecp_ma;wy>m2>!Qt(7A1!%q)XEE z2PR}<s>|$^9$+W>4`3#YNR9#00L>C<;fWk6wpy9=YF;MmG%y>@1HII>#c>)ES2*Is z1iRv<j4#<N=U8dlBiji#K7=1-CXg{0W~HcTw2;Gv9x;DUaUWPyAl{iZACIs`HCgRn z>72=Uu}V3d95kS1%pR734TdqMd^m{&rV5>(6d!ZFUjf!?BCL`<gAC1jEafFLqeW`% z0B9{5A=wuVOc6=>>4sZk-b}`l!2R1R%UCt;_-CPvSeyH_kCtzqHF+X8t$D^B2E(W| z#Y!uAQ?iyo-}IA3|F-~$9(M{X_o`G;_VvuwS@K?n1$1vsY6Tu0m))%rwqK!PFNH`a zj#y5z4oilOx8z$@|M<i!NL_>#(Na}yVN7q-YE>S8tLYP&pSQajOD5CEE1WOJSuG{| z5O@=XB%1iF)h#JzMzusx{R(S47O}mq<Yk;DXwd7REIHl@wlhQ34fi7UXV-xe4p=i( zTS^H5c0EBReKd@y{|Yj}87Y&+^|3Nhbs`7Hmjkc29KRKr80L82g0^2+itMc4BeD5g z2J8|*15&-(P-|8_qR)%1$5nAFm6r)@#)Ts;JM=4=gUKY@n#o`VqcO*L+!PFAwC<g0 zBajJ05NXfIwZ!jU*h#2s@~(@B(z_otYK*`lP~)b+d_q#f3GO_;QaoM~8j`F4k7TC` zzAfAu8JKE;0d61(fw|3rakr8~m&E<?yD4^kytSZB#`RZa1q*I_5K7WrRhIz04%I)c zBL%?PN!^R<t^lFg$|JWAw{W&%{qMjE*6X3DIv{y8*7D;Vf5iFB3cSgfpeHe~j9FSm zuDQhotBXy<aeO`>ZiYA({(%z)H7{INCnFBmY;r8lh%#VUzB}k2M3bPQV1py^0R9Q? zrD5?^EAug;N(}WBi%Kv<Br0r?g@vH1MDp#gVnTxXIh>3mI>U5i#z|5z>Y$o1(k2S+ z#eH;jn4wQJo%J)W#ZwRUXc+Zran}#0oW$xiOx#5Q72OhLWg1q=MBsbXm1cFc$JxfI zbZo{F_$SAJhRb=Tw5EGxYd!;EvWtF!<i|Ss6HX4lV_wN}hB`ndCCJsE4qMa;FtvD& z*k$T&vap}P@?qEebASQAU3O8~i-}r=w6oU@k1ZYp0A>xI@iQJmRsA4t|Jk^=SCzrC zlk&^+`m$l3m5g`s%gYZSr)Q2nTLZ_d&M-_>69&j?y#^7%+~(}H{$>?`2<v0n(bb7b z{C8X*F;y1o4BJB6Qi~oom?u*?Bw%+H*S(QpJ(FjEV7~$&x@y+c8+chp4`o9x8);oQ zp&7w+cIlo0TXQ0!!p7xUUC?5Aq`D)<ZT+JN$PA$|2xoRXFkcqOYHek#2xcRQmc}3X zh^59!e=d({*f>RlqO~%*yaE(D`e4HusTmDbzgs0Yq~+no*mkHzr-S69Lclqhw6~!u zZ(DHjN~iIfkO|y6U!Q55GtXXEGU>b`21;1bHMS=81b6MDq<}0;RBZLDrq~4&OY4)F zo<1kt$jV)rDb56XIGG9w0T2vN;sFqH3^XK96OE`8v2FmQ|EwgBc9}thSGaIf#?><6 z%#5VQcA(HGgLR2ai;fe-s)Q#=1K)g!nh`t7;DW0YW%ioR?POSU*jhMZV;ZM`c<d<o zF)dI6YUSldLy5=Lqs*`dWO>(y)uM3%$B>vn94=t1pq%4L-R&<c5|glcIc561Lf$k6 z#CV9r_0fnkDeL)+noQpp&?gs}CH;UAEx1_VR6W5iBY_j_vQ0soyY`UNsm6c^6rVs& zkR+<jq9`mJgvZr;KX!e?rr6kqT@4kXNaxv$Bgyw0%a@$8mZQ!|-p5~0>5SwjNkHHn zhvjt!o+5_w$H2_G0>t1osSN1-j0HvavRENvG?k8*k-WiT$Y8?Z6qdD<Nle*;Q<c^E zC#cM?;8$r`)G86m^3Nm$)Q_xWgDF#Im2sYlfQ!SLzV<A3C8?u0$$wlH(fRdG1sK=J z<Ze(}S`|>PVARBYO0sf_<)iS=X-vQU7}Vex*N}uOe~UdRj;c^0ZOH~3lOpBZD9CJ) zz1WEtFx9_3TQ(R_-4W*cP6HCT)u$h9rm36W-dx|(MHyRF0r$H{sjw|lh?@55WyZZi zz=P`7?Ekc^&ZZWpP#k3*rk;BiVqZknQ~UFnN9S{Pn;Pt*Yb<zLpdxK^C@wvV3eRDS z1a1+2F<uE>K@1OVZ~KQPHp{R+jIwq^a&~J`o3?m}86n5T2yg*a!hs9Z_QF4k(_O)6 z2vK9c9}eakU3Wa2K7cs^otuekCtcP-NQ>({qJVp@LOdP&>0`K|V`952U+y?_Tfp$M zqM%vRPu9l`c}dX)OY=NaRC>RY&i#5(hz_p+o^W)j;biPr8GcR^cUF_O%x;1!RXJC! zL`0?Z@+X7uOCknnE?)nOD0w)?&iug{&`2g~B({<SDSHAT3#4Sub6=4@b91VjI`3Y! zW?w6sOX-*jfZP6RTQc})#x6mO!%{0offx_$EAy47xjEi_@1kF8Y6>~v^^;*COu%K+ zi(>xxmKmK>rf8ebrcjTUO%i((n%;QCXYe{PUD?PI*T<%GG9P=p0P$LRq4PQpC#z@E zm@PXWz(o<jBrv4f#qIAWu(VgO!3kCy)tWlvbo$|5*#kzfg5b%rpVy}~n>!9`zn=qQ zlc)IihuB35Ci*#(4m{5G8SKJg(aQf!v5zF&+Kaq?x4kkUc{V#mu#DUF9+E%b6j_t} z$s!owsgO!l0P(T$i>tdc34v_EPv(P;jhMbmR(k3L7Ujb(#t2~ebgCFYcfz|cW6lbF z^C^-5ESY_s_+9YeNDLFJ&8<j&&DjF)io?<>b;yRbiQz|64gCK{*ZUM;w;vQHVrxjK z0kI+?bdc0i3iC#SP2ntbF#1efs*BC34A(6!+t`iDB_fqI_D@8Jt~OECzC0hb^;Bd& zdJU%@McfjJVOUY)nFY;;Pq#To=MUFjXD|E$l2!nOnVVa(sI18FErKOA`q?aVK!iyS z>P-b}m&Dkz+xz(H=#!p)S=9AMMTn&`5f#1=6Z54zpQSeCOQ>?I7UQCBkt!sG%cjyI z6_4R`wV_h=IA<p2(%Z*37F4aBowkGX27RWJWaXBbg|wSow>OLSrYl00zgj@K(j^r= z9R*vf6-7&H`3<nBu&!+zO&jk;eZ<1QCE>H80T@%+rIs#>cws$m?IJBCm5X|X6}?qu z?=3oE1sYm%A=#Q)fpfeA2FZ9mArYxnHwSC33JM~XsB$5a>P|B)BjjY#4T@EJbvDb6 zI-FVK45b$?5~|EQ5pm0{R%C6PE`1UDvU}o?AA(xIHjxRL0__PlOx!yw(w*plS`oAL z5$z#qs4Jy6f%JeS><Od|4E->}@&p~bgzi3b;oc=xRALCW*mPhc9v1BlZo6+FZw`^@ zE6l)1iKLWLdT&6nAViQbbO$|xT1?X`+8t2>Cqy*xz#qFXH&_c!k_8we728bk95E(r znJEnr0bcE88oXm_qdwQVQ_1m-$y)fD21o%7_y7d3O;@&$`zu0nu<{~eO+`7A>P{|! zKb77^87g5hAq<YNSEe#e%A-rgqR`MY24JTL#Od8W(T!r$;BNy*;ETw9Dg4P1_6Z=v z;9k6{;LrN3ZY^5U+;kpO;GD;v?wTja$UwQ#Xu_!R_L$x-83?`wa)O^DHh0X7l@5&9 z{4L$AsHT)6v<*oN@<{TMf-IupkFqIk*pw7+hnq6E3d3{CsQbSQAVyrqP)Z}|2o{`T z^-3)DBb(!W?|hWC%*_<Z#2RiRlGvssOh$16?0xhQyKMEEuTEGxmr6c;aag{V<U#k4 z1PH~UGRec#1K@%$n%w0EUqv>rFIDhkGtM^Ij6RP0m`0LE8j%4{EI<j03{RN!iixE} ztupMp6|#;bKLNx-0xhnJ!@6d3BqrJ`cDaO;D&x#RU>H`kuP@uCEJ$8f*oDJN|BDQ! zqGd%1)Zwj29+nEn75J*t^XsmUZG#k7N?K3UGP8gui&VPVP{b;UpImb*h1H(b`J@gX z>z*ive0Xe-Rj3>1lPsg-He&^*$z@3$GfRI0vn@+%MmIATq3lH6H76vkK(tVmDnzx` zCNFMHmpf`@+C*-|g*DcDD@8<lK6B^%m6)4#QnZFn1F~sog|#>qN%p0Rv|j3J`x2$> zyeb(k4F+x{_qh9N`U)_-!9*ghG+zZRPLD<NQ(A&|WZtt&(qqc9Nx!aszhsab{Bv=8 zL_OfhDC38uc42AkASH^HJXWq=gD^YnA;ZLiW+CXyaH#jGZe}erOIw{TW-i`W9XOw^ z1y&$Sti33@IFUl8(+ZFg<aBrJ*|<7f)B5O%A~Yl0leU(zlQ5@y=|DcOEP(Sd@_*P( zbR1S0SCIVhD=Yi%MszeYIXBZ)?TeF%A#<mb`N%1kn=S$Z(wueE0QHd%8<i=lNS#e@ z{HSp+Lt(sSgQMtaW$oW@z}^Q&gGuQHASLAt7B&X&#DIA=79l_yEhCys4~laIu?I?M zV;<~lC=q;ciS!*-<&7678Yh<p$P6K=9&`z>`PV{MkTmLI*n|Tl)VjR53fgb=0V@lH z@7i}k3?y#mJP3efg%@H*^k6b`=ggEKTuFou#j3)l<yZk&bV_r8r5oddveBymumja} zX<Mt(?9m3DR-jUKtJ%22=KAgn72%{zq9R*$(@G$*9G}%fB>)h&_9C7bQiZtLPL1Zc za~m9l);Jm@2@wCc()6(4A7l0SK5TBK5luybOgO?~0!jt!vXEE%;sm9Yzf{d5>W2Qf z7eoWe2g|shhE*Xz=`mr~Dap55YkgiCq-B()Rv027vAmMXjRS=`uT6APo`z@>^f8=X z%yi`{Icr0LZ9)w5J2)b>+nQO}d%1aJ5Lhc<^<2rVUF>n}l1{(U8l4eumbc|tODgBG zA%mA_A+bXwZ3;*cJ<&``IN-Xq+TsnN9du8*0s&M&Nj9&HmtV1r!v1b2d6(cORwNN* zfDNL9L$+7uU0QPlTjfnj9vts}E<8NGzxw)61-OIb9$F6Y8`9{3G4H`;6=ev@(nK=I z-xUn0%CRC`;dQJ!19(5c;4g{>OIYzC20mydZO96s8`)IX<URXB(bx4}sKLu}7AV5V z88v9WTY@c$H77o^pUqOG93n!pm2$ma%T{Wo!dr7j9rbqX-49oVj(U)YP!Xw(c?ngL zDpcucRb(1ZZfu2tu{W@*)`EcZ&m)|hP~(Qpo>t7*-3MgP9tzwXn?~MUEM{w7;>&2n zqPwq>8G9TuX0r&HDmTHd#)_iN(j{P&hM^T3Pg}9U-jJmgVS8bpk1B*km%z#)pe*%F zKSKj#f?bwC9u90HleU;#i0V*rmsEdl#Sa_3m%iLW+BeTOLZ{tooJddFZ_oBVM7_+1 z$4d(dw`_asTNdek4JMF@E>@Qzrk*N$QO!NNn~^P~^>JL)BZpBvMy5B5gk?}>&H#a2 z$6SJFb{R*K;`5O-pYHkx3018R!iwz&w{3+ZZJsI`09o;_HMd-m2?C<o)Jz)AqYQ_F ztvXsdumpgA?jf1P2Rig92pX|l*8^R=_Z-vF-~uXb>Pvx;&UBJE24{o;GYvuaHD(T; zNr{OB@OQ5zgI<xS0Ql_3Kz(#M;@n0k{FDU#7GphpkSSrqXYsF|7neL0s9>{+qMB`l z@|-wvIV>iovxX+wH-iuvy<?CR!4{x2T<RU|>YB^1q_7k}n^<db`KJX25<hBt4=LM} zr~{K7wUY^f1aFFg2|2A2^<o=%l)h|*BnW<-<N?fvFvZ5k6wjG=%tT{*0wm~K`i*2q zvuTWABpRgnB9y<*&O?*d%&W?Msycobd0Gt!QY(YI+s{aTC}tVV5N8Z<1tUuYRJ4Q& zTksB(lcctIaO`4V6N>9_9%l<ygG}$^M%Z7C64PA?+v);*RQo5TKpO`Z=L60gRG+tC zC7%PHL?%M&ws(2%Xe@euuxj&$Jej;Hz|#l|G=LJ@K5asj@!@6~=ES}d&e&)5Z%w=F zjMEikSplLX4{<{55nD*|oVNIpWc!ZmV?DsI2O1*9$gRAPsmWeY^3hq4No*hj@TB&- ze$?=6L(yFCq5_P4)zeW5AmFf8x<jm$pBW@<d@Um^lvp!)O)S_y&Pg52fC`gYA()_R zwfYKOMbYGB?DDDhqbi3Gak>2FH$VLJ^N&CN_?y?)>-F_zzwOM0OA)F2{^jj$Z!xRK zaqP#Td4I=#mwm4y$8qc;$5D?KA6=`|TKBq3)$B@X{?ICPkO)&LVx=KP7Z^mJt|paO znpl$mPkKtI^x8dAG;cms^HWE6YT07j0Wr_orkn|hn>o_1dQL0>68+U4?8=T^BgdU; z)fTH+dM_WDFkJ6!NwJNjpOjYBK+$H&DAMWch}Y0blY7G#1?p&%u;u%D7puk*3o(gQ zr*jG#vZ96V0JHegH~Q+q`2>3u3tNUpO-LqXpkMr-X?g{E@XR(OuTOz$8TOJ*z;+~= z9!$H|jE3$Qv`;F2OC0Kq-c6T=`sbh+%>Xe4$wHlx7Cec+|H()!teX~Gnj)c8+F(M+ zOn5P$$b>VuoWf!eVl8647h+`)2m*G6umx}?2n|daW|slckESaav)!B;omvF@`$3l* z`^;Vzjb-ENxo|dKyaL|dbU}wLM0Rj_ky<XK%;d${M+GJ5hD4QIxiu+jsxw8&bv`Uk z!L}Z?bS=McBlqYii||TiEXK8+>fzSC(<V5qEjw~3l;g;w)E+<DZSjD9xJ0gsn9aR{ z>1zC(otf03IE_||*C?doR9EQ75lq|>_-KerS5_>@W>4401xSU(H)YEC?bf$q*Q6Xt zdXm*tjcdEYF0?`+$;Sm8zcUueSPdKAW|VuRR~Q{5r`mOnB)Eod%GVbKw$dJ6P>QVj zN<;=V-b(BX3#zew*kdt>$6Xsv1tVG7v}UBaf7K?%Yp$QYfN6co0u%5r2U#UxSEJNB zD(r4HFDrXa^5_B9vlu1r2Y{qujpR=mrWx#HJWbgD4A^yYRDHnpE(O?a6AfpraB(wy zs_-$@0MvA`64+VCobuU3zC`9o8s^xhq^POsE+pyr@%r*8XJeT)BQAmYSPq7)!~M_X z)KMUAwvdq|z<JW6DFd{srL<17U6l~&1+_}y*Y7_4@blmN%YXH+|Mp+}?T<hHxbL^? z%T+|Kmn(CrbwBF;e&3}s5!YJx<B%%bwvp7^{n+nSs2<0@?{}$nKaOMHkK?GvvDc&4 zdb{03q;R?2Zuk9G>t5?ll}au9eh^WuwM|guAeQ6UkK^bHbER5k<0Acms!_JwQdBka z_UN|W%F;__332NOi`08)dSPKIhG%UJMMN`NL&g_3Qw8+^5p@WAU`ef7soT;^<>*zr zP0E)Zsci~7v3S!9RqL8Bz0bVeuwu_b+H6gLHpWtr4^eC6M6t#)ih(Usz|47Oryw$Q zx7N^f8pcFLZaOy|RU7X?H#z6>+|?~X%{d&|K_Qlo>pCS@$XUGgvHEu0Mc@-VSs#2X zt+{DdQ(1icJ1zp)^VqBj0w>luAJDkO1_`7OK>_e0X>9_BB@eELcNdgr{%O|I)84JL zRSg_Yda$EUPI{XUd^xP%N^wGd7?w0<*qU~c4okBKt;j@BS@lo|L!QZ+2%&vi74HEL zhu6MQB}R1-GAgB-0coLW0RG6LTUak?>yhCw$!>-g+Buwqwk((|P~8THy|RYs*syvP z<&auj7ZX%{N^RtwK&Y4vJCLMH-b`{(IdZD7gMhjgocOC<3k2H`26FG0dKwb7Rsjer zj}e&TWnk`*_Ke)jdWxp%P3Qg->#;ZNW((F^VHZJwhQ>q!8^LlIBOvX6`_Rq7)<Nt2 z^iT`rDoZ^Bb|FRHoxEr=fPnV}Zw|r9;jYzv*ddaueRIr;GAlpZSva4LZ;Eb&n(Ut< z`AleW*tjVzz{+q~<c)})B6&2;FWD^j$`Pb}Zj5(z#9VBO8w;i+Z-CU{mfbyc=2c}7 zOEf^EK$_1iK~hXa@gP$z;#`TC3xn%-D!NNw3cMk<J}W*`y0mX3-$MY9T^OpUON>m~ zTv)Ok&&{{TU}in7Y43)fag~fgjhB7#P{T3Qn+Sz_74YEH`TtS@b`hBfH3z*$gE2@d zbAn-bab#G@TF{BN6mz>Ttb-=(`8fDkVHS3dWT#g*54(t&CBMXmQrhtOsbfb)lABS| z9Vsl6-~a$107*naRBvh6u*+=h&M|3Gs?xl5R5oHRrChI<?|=C8yWjur@Ba0_`M3Z6 zKm6|ZzuWJ(fB3`yVd9t9*Pnj+X)EP+zinF~lKoz5OXn3iYW@DZ?}+)>D-my(LLzVX zw{6>w{n(G4iOa^d9whwhufGb>^>Y2?^XJ?Bji?^S{n!t=)BSdDy2^1J$FURDvhmxO zU%$NF>QQTz`+dLP_v_^<QuqDXkNr4~TK8j@dK@jPu-4<)Z+qQqJ){<rQma%ssz7M2 z2(_BV?WnMBQo5o-Qu&}(1s5udbI;`!RZghY_yR>xgr#t4HifQ*2$jx!dStH%G<a+c zS$p1f->yE*Dvg(VP<Kxu(VE#TwT4m|C}BS!6E%J;I8;C_P$WWE#@aOVY$S@`Vb4|& z3VKm!y=Z=8MF7k|Gr!orJ^oD96v}aYPf=FI+jYW2q;(?`RYtTx6uD`R#xe6E_`>=6 zkVR?Rr&S9qeJy$o?I|H6?ES9=!k=*2K_MLHgJR!_mN+m9H(`w0roOf0hlpK*+OMwZ z)XHnz>0~|umWW-UV$E!QW~T`ex#=k7j@sjb|45TY1B-_i`l?I+0>Urm$DUr`;7Iu> z->w5k(KDoqom?0SF)G050~z&3?&?fQWtPW5P9xZ-Ukr!i)cY~K=>f*0;5CLrPw$e7 z%cwUdK)wMMMBUTS`Y?ypg@G7psHk%L>WveF9G{7uZUqQ`<!)k@=~R$A*_7m6tizA( zjunPIU$k-90_*dnH~S=n;Uuv?Vb`j%L)?_dNRl>XU9%=%Nb)OR^y<RrpCtK*up|zT zwbP%3<pjG{rXpmR75?G}x`?IbEleAe3!}CDh-5CBf1ZvT1Y|wF&?z7oDU;|l!TUUR z#oC|GZe_d9%grP+)(DH8s^-Z{&puD=A9H;~2y_p;iS=VhtvGX{LkgdaNR$GKrk93T z&zB4n+fs?`@uO%^u>mzXb16is{bmJ7aEUwsWPLmvd5leTf|}7X3YtH*@a0mr-~8~y zk3aqR^Upv2_|p%spI-j<U;f=szy0yP-#-8H=bwN3+qc{8e!B_NL2}#oA6|c`NB!=H z7ZIto3ej;KpT7I9*82JLFZ*$Sp_j7p%l5i$+kPAud3kwxd3}BT$AA38_4@jopMN@z zTC4p0yWhQjdj0h2g{ap1e%z1aesI|?+vW4;&u?#EUS3~bUteywU*F#DU%tH6TCdla z>*cy#HmP#E-|qLjNENBK+rE{JOOYz~`~7x%d%OMm_V$H&V=8ZNZ*OmJU*5jl-fp-1 zt(5X|eYt)4^7)rPZ`&qS_WOPu$8j7&wBPUdx7%JTZH1XjDXam$&4E+vVV=oag<2`F z=F%<1h3e6)hozJrSz0zGs!WGy3I+4V%=M@uQcBq_8xc|6rP5L5IBGrWQL9kx&9|!1 z!6a0xNUgOMChN5Y_)@rRtXYLQX2H?>k@N^ixMH&B2j|JKMkX>;Q%?`4BH?)RgubRz z?H@IbTFjB&#=%~Hv=YLm!vc?<+8y0&$EeaU5tkBUP$qs-SQ*O{9nYST8z3OhtPdRO zXX##Re(12H*+tht&bd?i1kQ&~neYfp>e+C@gwfBFZmyYdsOOc)Bt4IE(s-JDn0>m| zK%}KuMVX?;ptX-Z|ERYZ?11^w12n&fvR5+F<1-0waXyPo`>@XXwAfpXz!Dc?r6w6& z#Ccd5VHw1)+~qDgY|-A)-dstC*am6z`dX3psl4F^7icBdZkAZm20>^JsA36I(P~&= zZQ0A1g-^@?$>p8Wg!Oz&>t>!Xw(fn=%G1u*vifLo*NLnRd6Oy0`T-^?t;+x^{~=^) z+!TgkhjwfFXWOdjX^Ry}$C{pKRGY%Wr%0>2#tFerNuGw72*wIe0lT_^)5G6jH8TI# zJQEFHiVJIo%Vf80NUJrvIg{9ufA$k#O7dv0Sw|UIXm>JGP{OwX;bqDdL-8=%R|knj zs7h<c%^K&$6OM;-V3i)%aUWLjf)fp@<g>!AlWUySun6OiZ2Q~Axmg|uw!BJ1T7AT@ ze2O`V#XJefyRLUCz!k7i&r6fY84J}!U_z8gx=ss0xqz~1;Ejfll6BPBLhl^5OqdhH zIk0|Fj%Kkp4#;?+QFgjMGy&fQ)86n#ku6!sF!m4TLl@*4jeQ;aAtZd|?|=OM=bwM~ z+rRq#>+5&TId|0kkN@=f-~HX+y?+1tkAMDC`|v;h`OmMPUiW(Z;ZJ{jeSO`w%jaL- zn7PIIaw$Z#*JD5Sx7(YPdbw<sj$eMcefRx$QtMuidQ>6eZQJX<zqNSdjj8N)|NQ0G z%T|8);rr`#JLHfe$FaZNcPZQJ55Kuww#&;!HoksWUf%A<v2R-up;Gwu_0#=+yWj6+ zD_rV+JFeGHm&*$Y?fZV;Z`-91)t8r-<}QAFyH}|_e5aJl<swyXw;KsHZ*#4+6|&y< z{dT)mlI>Ee)csy>x0{e$E|<&YN<#a7zrJjjZQBpI-;S4;PcPT&e%$xt-kR|o$1XxI z*H48n$5E@)%VlGxZR6uOZnwSG%1otf`+hH_eEROY*VoryfBp41Zd=*7T$oBd<aWQ` zZePCt{=04C`|a)a_C{5{e7U`SdAr~5x7+RW=Rbe>^7iZJ&wu=fKm6&Be|-D$MWk+* zM5;oxFR{x_Le?h+i!-Tm)$=NQVy;R6_}GL@m@op+(6SQmD*cq9oY<3OLMf^l^gxb) zRHDLMJvyVCVT%fT!n~~y*OT>W5!5}^x!IM}7u{xf(Z}HU?~>rL^kxugsql@YbQ4EN zew)t6S{<IR9yD(wjyb)@YCeznVfE7~T|NJz%(#;^h1x>!A)|Tp<f8&;Nfe5lpLC9G z8N!RYL2D-5>lM(7Of1$bg~(DkO*qNo?^lM^AjOFPcJR$)DMnEOL{EmlyF}|jfGTn1 zyHFV(`@`o?qLe(jX@HP9Z|%a*r3*DEQ$F!?Xs}DTJqObPkyQ;OietK9r=##Nto}2U z@>*PBQ>N_Nrma!?p*EqZXHg&~rYwVE(UT5Hw8WjPUX5D@Z+Q9+5k^fk;?w*qr$JG9 zJq(3PxcymRaqyE^5bm6&1W$qXl~sr^d3|8`kSk{KNt@v~NLW1{{yxAmrIgIn6LvK+ z1b0YC0(wC5YS_{ZwXisQ-!@Z}pZm~L&lMu%ARcf6B(@r&qT3`ix2E}Cc-WJSByU&M zTwDhe;)ZNx!lr~yQX<PuiPpLJm+{Zp3hBQYzB~+TdtI503PzULpz1Ml7D{K5zs6)e zjP*dIwI|Pc*B}5$U|(7@(eP)=%oD?$@Gf9bt6G?+kiFx2XCGi^%Sf6mT3K7ub7ug= zOa`EOqGKWGw3na^l|2)xbi@%o160v7OXvQez0jZMcxQaeOsC;V-0w8|#W$Ui6^M3- z;tN)kY)RJC+=fTlw%`2x<Ig|;{QXbgzkdI^ZC8=9??($QzTLjmy6^k`_kaJtx9jE8 zr|(~0UiSU?;fEjo>aTux9Q(fSx8ru%UN4ueW$JRRM0D9UF6DmP585x+3v(%#a=YCw zmuqV$bku`Le*f2hbHDGm+g=YM;{Cqw`%y~SkJ>C&mzQgi^6M{OTD_#b9&|8qxm;d8 zZP)w#cE8`s#$VpvXe-P_TREg|%zW8|MOezVZRJ{7-rl}ku3IJ9Wv^BEQa0LZt(Wc6 z+^v^Vw#)U{dv-1{m%>tezV9K&e%#Aen96ZfF6DZ;GIMjjGD|5;RQA0UI4s+xFjKAj zeZSxDUoMwx;p?_tO1ZR}hPCd@)Lh@C6p?xyJ2PJ{mu=ga`KRChmS|_@TIo21gfExN zeZLpxQkdj8?zdVi2}`BD<yhbE^*D}t{P~an^uPYc|NQU&?Z5rk|N3A4^rt^wE^2in z?e99rE}@>99Egf~9UzuobuhfxlX!YtW4OndpVmfCM#zSWMdVQ3Kx(B@I6Py_f=|e# zA7d_jX6Ha86O+5#f*6EIsFFGwJMm#1ht-?i(#pLsIJ1>0=U&`i;KR5BtVT4}70{;J z?Z1`W$|hdEB2N#heP$*zY`dDm`oFRGd_Jn-h|X3>2@k|{=or%;=h;p^Q5|^Bgaup> zD>U#gIEu~JC%px%p2!zUXxR7sBHUK?DrgEBHpPW(04;pyT@GRG#cg@H7?l80>0BVN z!k)S>Eu&SejIq^O6t`J~bsLLQmgO!HwrruSiHXsa1tXvtI=namgkoa6W0wtUxxuMm zk9KAEG<XAZTcez1qYZZri@c1MVu)02$Gw8YxDYt3JfN|QznZG8;%S(JnnDE1cS)Hq z8zrQjC}W`4o8PY}&ejLm<?^ffEu}ZP>BKQ=3m9QkRel37`=(4qqZ2@AKCD`=!11>d zx>6Wz@#IevUo$NbK#jOp6_C|r?fDS|<MxQO>>0KXH)TrlKHCK?xMHO}*quzu=@)C< zngosq(TL5wB@#X+`Dj=aEdFdbg3K0D+@;qZ(!umwe#T7!IhhY`ilIT2ShBiHAZfLx zYgPbLvCFfB6lsl<1VsrfOoA1vDSfi_$8heEinzK6q&@1%%4lI7{*`W`B=6Q?t$*f{ zmDTC64m(qlFFFmhj-71EUrgnV*E>DH)`Ddh{iim1k}efdfu5_zJIs6z8xYz6;+A84 zCJU9`-G`aYnABxrj6s+5331Z3&>#(-bS$jB^^({etVsHpO(Y5$3YvOg6Zkza*|b^0 zIC@}M9LYjs8_}6-so^e&*IExMeEoF&@yFl(_|wmyzW>e3%gc6Q;^Xb@*SEK~`+Yx- zdK|~GAJ^;4%gf6zzx*o1$BmBHDnwNIx?S(L+i~pMb|I;SsT2~a`>~VI>+5$ce7#&R zeAzCAd3(8jy1m_BUtUFIKkh`e9(StOYq=hD)VdQfOMSguw{oFMbr)heq+YL=*Vk(c z06z9zWN%fZODUz)%Y{nex3`0-UM??0e81mcF0XWv`+cv+t(41U+eG;7O_+)ZA4lDf zy6^S7Pv1$Ed#g<?$K`T4b~=uID}1?Z+of#Vw(o~jX5NZ0OJ&}!mzT>$n78J|J?ehD zy&Xpt+O~}^*NupN`TXk(U9Z>c<?^y^O{Klu?>jMV7iOm8I4;+697oy8_2qKCZ2NKF zce-qst^1;nmzS&b&dZg!ZkO$HE!*|Ady-@;rIfN=E>{vhj#_Ig^i`SZ{?GQ`|IJ_j z{-6Ez@BjJl|MP$PkN@<?KeS%W)Q!Uyrih`OO@C|N#ips*d97)yc2qRqfO4^JV(H1y zhmuG$v{<FVrd=PZ=>-kV)y1G;dfjy~O2K2hYl?j|c73e<Wm6rpnX-(gij^M|sjZ5% z^8Y@9_yLBsD2qF|*gD{8Q7$Q(v&|YJ5A9ESUlZw6>}K`m2PwqN&=#T-Z(HFCadZS8 z1CQzicGoyS=$rxEQb2m^ps2VYFf5yJ1{y*(!}lc;J1li%?LMW)DjTCqC$Y{@v>1M1 z!YV0tZi(7m;+Cd+YXp#$xHPjMGGVOin=ZqyUPNaoo}^7vg-Xxr#ad$aMYk-N4Mis} zKyJM=dF%P&#~-A`XZ3J(v2B^l5D?jGrHSB;xEINF)62^vY{XTZ7BIjbPBCjhC{}bw z@&`>xP)vrn4}m!OV=}CFHl7(W$b<w74kVUwWpsTQT|Fo>P-i}Z;rBBq17maPNdUI5 z4<}7kpzutBV%!&7cIu`ywGL=U8Cy@Yd4cXEt(rZ7L23bucye_tnAcvcJ+oe{omGL| zoVxxD@R0B&L@Y(6sUxZ=3}{e@cF-k|Y)?X1&7ztX7VV*R9F{q33fM;Vb@j4GTOo3Z z3fN_OW5T^Q1w2`-9%{nt(7HU@YDtevnh(okNYN7{A2tv&1OqGxrcA&z)1H4>pbh)5 zs{V@(E8yzS<sn8gne#6A#Y{yEIt8vI>W#==R-3Xikwj6S!TA(4?XZb)mGm635?mew z1$vO#9hfriv6iOqPS%2Jn1Vi3#+b%=nZ-GFxMVw*Y017U)XP!A`buI4wd(l87|@Yu zGp;S<y#VzOO`FJ{n(fqkuXicHECu$`)@9QODu|OLqeD1F?8VfBtCyH#Xlf@!2eF7) z1K6sr81fYtHIXL4G0=$;Fc%lF{Q3HSiF?-{TXG~nEFNU$sk-;}V|r$HRx4Q&Bv=9@ z%K~Hw_W%FEA0%TfScYW4mSk&Zc4udHXQuDHRVOpa2!9|M3^MancdJKG;&ye_$&*Yz zg28zH!VxzQf+kQ06GnqUxA-(^jMWXK+FC4%tejmkD!>MaZAg09BMr=EW8W-ur#USA z{NdeKKl%D6-+Z&)p0_Q%zHZ0;p402L-S_=2lIzK&xGwSC^YhEg>$dG63_>9;FP~l| z>$cyCF|0w7s-(EAs;H7gfe<yz)A|Hd0Jac`A<z<51!01mkNfMZ9vWgqQ34Rj1iIc9 z$pA@&5D5-B7-<P1Q^rG*fTTl22#GNe0x|;Xx-cUICIW=4OIUM0k{${f6qy+UKi{6P zXgUM|c)!1*5>pV(l5^SQBC4PQl0gwzvu4qB2w*N6l4KE5R1%P+%8Vi@9b3*20umBH zCL#bi(ykyeEX=&bm53yZsz^Qn^f*$CoKpgzKwQo-X5@f`kW_O@2aswm#sX$UfRr{+ zWL~N+#|%JH)F%Rwtf0#p5tKN7#k@Y>zWm9T&+l*l$DjS#Z+`vP>BtCNuv3jJ6$VT! z1yp3{drt>_6|p$*Tc}tMgJ}{|ky*8&PBp%x1XvV5X_`@q;cpr&OaYU&p$vW92^L*3 zGxs22jr%HEP}wg<0d_7LzfHPstVmQta*9SLwQ^s@erz5{1VkVt^D9bAkR&aew_%(C z005b1uzkM`WQc~XA_WfY!ZgFe<=E}wwqD(0N`@^tS^=Pml`g`trcQW!pP6_IN8*}T zfg^gbYo}Lb>=A?Lf`MBWJQ(_ymIV23r@tJ?LniE1dgGQ@Yc&CYa`UI@$b^k~P6HX` zR6kvnv9}0+^hm#U*qTyg5bNp&;?cGIIpURJ^MI*#D<>g}5s@90r=)-fm-=%P+9Y7L z(4h6)X8RoI3+|WZH^Ex%$0U*h2w2liU5=mCBWU@?Q?p}isndg?Cx?&L4L|KRC#V-+ zYisV1<G_wvMZd};QGvSC^J-2ngsNHN>dQ5hT%1JqmK@l}-9Rhr-Zk%N+qW~)o4sL> z3SB=(gn9Kt_Q3@uCWX`r?V543gFw2WwSIP$1WYrriS*nC#}14_vRdAvDQZ`ny*D~^ zy*W9pYOxpn?XXg~Sf#6v`il72AD_*NZbU8>R^76mIi$VLYjML;8c*|XHyVfUdp)(F zr%(LNaSvQ=dG&)G3~V&6#Wa=^RaX^j8m8;m#VSnnX!PH6#eE2KMN6JZYuc6lOdqCq z?!=kK&fPLC6o(1vEAHrgAcJ#OrlB5oo0QIPH_qUqO?$Id(x@kbnk}iEr_?4w)n|ii z^9cJ*+1hV^mK<X@wAt|C{%BhsVcaHt?HnYb+A#{lqzy|my-NVu-KiqOcxZy*q@Zux zH+#9|-Ff=G49Va7`q3WXUfS!709K=*wFJrZC2FKOKWI-WT%i1qU($*VgadW>YZ8?J z!KzDXGr8LFL`_JgX5zBWv<R6A7akfjRhKq4EkAnG8XC;*m4kmG^Km5RKx<k{Sk|w9 z^5xI|_-9{#^EDv-&ENd?cfb3XQZBk<&N&^D(#}joECSoUF_B2xw>u%N>xu}!|K0ER zeG3ay2ssO6lngm501z=VAyQ5`Mn=*kl0{K6BBrzx5fSAK$8p@^)3NW%vOF(KI#QM# zLdckN&H#!)pqf%iSOw;w3X+96+}5WUqsVdJ?wV7K5fmh6016@GBX7r{3J54!g%km9 z>uui;l}yYba9qNX_JV1JB_5gy0gDq`MRJn+{Uyd*%9)TkaEWD2$H5!`AZ1mcoD&fP zKnNj(kaHH1r>9%arGQfs&CCP<%d(WaM2slukdh@TqLLK=Bx{DOR88;uzB7}GA`ua* zs^laB02~7`vw)^U_U-kyJ`tg+WXT~ugJu9+Ru<9l^7_yI$A6AF|C>MiH^2JTuN8!l z`W`_a5r^s%U5xQyEnw3(N52T1pn@gH!eo(wRBPO~npo;zg2OhM6o3+Sfi*{Ws@^ed z6TfG#Bm^C{Njv*3rlSk)9Yk6YL;;7koP!kmKux6e!5xnEYxA3-pEN%Y{z0cO6jx)h zLbQlzx8-pxF6G5CbC4Q$8mGNiiIfxba60pF3tJLzd4sgEm_k!DWGS_vt+lqMczVlO zTd+}h{in=;=a!xf#!{KX+>X}k`J(3Or4tjL$+CCmEoJFa;xhs;1BWjT|A&d%Y8#Y> zl)^G^<ZK7EhtzuFW#7q9Rm_4783=75K$V(V$R=d4k+rjLoB{AtHyXUuEZQ;-!TZ*{ zUe;VXy&cl3(qWsAIuJ7BNbQxa5jhK#xDTf{UY2T`4qb~HfIii}6k@lDoA86pR5!&V z5VQ(>?w<kxl9yS<jivez-15QrcvB@x#T_6-^S-u!lC`qhW+3zNx?qYQ*5R~fomf20 z61UZHE+(oAt>DK#>RJH3!2zD#J4L3;6O5&<G@pm}QVcyD=civj)Ws}fJ-EOxN?nK! z7dOqnqb>x*00S1_Wyu+@dcoL~jbe(Qr_(mEzFltltGZ3-;S%I(ARcHJEvU+wC*Iid zCik|VeWyr?6Z6#7lS(S<_8um`p-lFkU;^BiCscwC&ENooG`MN^Au7<jF)%AXpN5TM zC5zmoscTj;U<)1ZR#Zbl@@N-E|5C#)r0^4IQK$rf+M<zgFeUStG?Xgofm0l%y{PUl z!XkP#u2SM;wFgpJ?navgoTy9tgw)!iBhg|b+8U*0?8}&Nkwqu(dY?Uu0mLEu=4|lw zPE$|(f8guKE5I@i(rt<Au9P0&;oTSW<7J^+Nf`CHJ=$5JV{k*R;IPThowV4@!p&O@ zSdm@Oun1d7n8|`Yeo|VPknzVUer$vg7}5?KLU1+PSv8mQ_4YtYu&c%x|KxA|{OfPN z=D@%Go8Nx={CT_Yd(jmU5h0~*+cv2l&}t~kIf>+LzbnA)>Bfn3&OpM6X`>M1!t1gw z-+udP-|s~D{QMl_O*HTOw%h`us^+KX51{br(?>)kCII~K;ft@o`1<qb&mw||PtQ*| z=MVxSAZkka^>y2}jhXj-k1-MvA%(D3tG<FNN|v03ncuy8SJ0{u10XMPB?eVV>3Ds8 z1)%ruBL}Lbc2(ZLf4<-MbR3AxA(Uvw7#1YNV@qkzSyYKRAW{r51QtC+;N|5Gpv-{~ zMRLwsLc~QjTdI^25fUMQipX(f5xL!NMcXE#7-C8}givsy5jAJr^7i@j%d)Ju+tacx z_t$$$${d#^5M#<m7GVnezU7pd2`E25y*mzxfn!|O+j76ZrXy|J>(lLvckiEXPfvvS z@BiJu{pbJFzr4ThA3uKj^!amxxG>MEX-|Z1r;X%u8EH0blTp6+q}WO&_hbRvK?a-I z<Uf?oF*{LPr9pR++5UnStk@6QH)_iDZE|G}Bx-6~E!bS}zO_AzCKB~+ThPC2z(h5N zTYtI~+g>(ScZ3%D>!XaovBVlu+rhL{t+tRI6=&vtDw^uEo&d)4$wMVsD6$JuMQ^)3 z9qQ_a<8vKr#-qizlg>K-c~Pz^1kN9h5q(`N!>j(7)zaqHGhsMQf@i{y$nuiG!uX=g zyB?9-!}8m^9;9l2zssbO^NkVi5l#b9_j7KsO~^n4%_(eTZA1mOU5D=I+&+S5DcHX@ z%&vdFE9$j)+>kwFmoN1+X;$dQ;;mr#;Eizg`y(5Nxw2t4MqM=PHE?aBi^;D>f!eJ$ z2=iE~RN5jwE-W+iScbKlOUXL<!A&;W(mO4uwb7lx2t35Z_HUX^&;lmg{CCpxL^w%< zRqQFj_#LwcC%3X6g<lRoDW30L&rkc%B7s{hL&@*aX$c$xg0WNd!x_Ud>a_b4#e~~w z6sD+5OY6q`=0dl>JW%3^cXdmOv1psKi!Faz7q@DTmL_Ot-<$SjAA8c9ykZ%~7FuQ3 zIYRq9aTa!lmZkWRHM-e!s-YLWtt)3_G#^;uWb%>s^-|=+&TUya1L5~Z5XX7zi{dgL zO*EPs@7=4voXH(ZTu&WUS4<E`D}?&;uARfV_L}prM@;z1nR;?jI-v(Q=`aJQ)f(r} zID`7HPJ4gaiS5xD*zdpmI+q9h0T;#R-b=KFx5^47QIIZ95a2FJ;Ay@v&vWN_Mk59y zYE*Ar`>IG_-#-_o`eH!E-kGa&Z#Ie9RaS-Dch6LsJ?Zp9t8H(eTJzwm)7=6VjUmLZ zzxif)dP*tX@Av!t{_^?ru^-G-ve|M<+kH>zU?dSy5d>uBKl%C3f#}<BzrAmFW-ghr z0Hro>M#Ob_r>ZfAWm$_-7i0YJ;R6u^m8!rwrTp^pavaC9E+K@JlBy6=!I3IzVM=M= z?>Qe?5;MPh_u-2#z5sxAU27gKFU1d>QmNS_q8ei;E?EEwAqI}ek)NJ!ps??IN(qrv zHH46k%n{c$647xSZ7gZucK~>Pej;3oBe!TZ>$<M%`u_d<oMqqdh*F*kF#urB84<qx z^2<^esg^lnPAT1Px8pcU;bH&{VF3VU27sKih%#{qQA9;RM7M2IRb~z$-fmB~+l`sm zb^Y-Es}h+_NFfAbzTIxO+YOOaBm@j0rgR)B<(yR^1ZL(CLP{zEF@$AZ@2{_)K7IPh zPkyrR+h6>}FSXR4^TaxwS~FaJvoGp-3qV&Pupukf2FHR%h}G6;U+`$p=%`!One_kw zAOJ~3K~()r*d6V2tf^2~hm1gZ6Kfk!ON2MJNwKOTP!|Reul5_2$m-VOFw6$#-1)C( z7|m$d=jk*M`+PV8TS*&m9NhbV+JRso*n_XB4}Lrt9H!#AKi$J{c{Tsf%=FA8-`lmX zSk>k68qk$4N+amhTR#^2g~wagpK?8@tN_lRb3H$AkmcovVtWLq`)-@~vqnc?Fg#hG z{DjE9Js1c80I%;ZKDC6geolewNn2~2M${z>gy7b?I1-vI<7`B#Up(=OzELdc;EWn& zFC91B_#gn+$wl98lXWaT&rNXarE~4J1RwYKcbb(iZ>gWF_U4{_JlJdcuw1hP8}y1m zBibJPrDg{k#Fd^Zb!Hvs-a^%y2ZArZb_DxzywmJWlU8^RJMus%)&B}^B5HRaqep@* zf-i#sbb%k574ReD8&f6rGx&1NvGh5~^PEo{`#eAH3j>jqkJG7H<8_2poSRm&TY>v_ zo=EyK00dhG5S|74ei}G3n3{z*wtPvZt56Mqo%5ivQ#S)=GPYT(2`-)W;o~h2J-@@I zq7kHCt>%RLGf>WH%j5J^{jIBHYJ16g=ykKx>|Jp-Kai1II);h#@Ie^2{BTmYE$;{7 zI0*t*fRN7qECl-0**eg!H@YyfVwq_E>N;c}MW$`CuVf_KV(OHaAzRbI827O|5?1b$ zF!5o$G;2*}wUNd=AMTsNDa?-1onqzS*zOlE{C?MuRDhpc7wcR%_TDy9$=94$!MS?; zBGoz6KC=yV)u3nzE%L{e3aF2qhtpbA-_PMVY#KYd&&J>SR=Ltkq3)N`Str7_fi%IT z<}8oqwXwm{Lv^u9)(1pD=J@pdygn@onsQ2MKlbg|ww#iRsEFj8j+9fXS&&(XI530A zmtTJQ#g|`x{`_*^wh%&y3o{+*NI9pRa~5i7Cpo1oCG=N_NF<90AQa`cOn%X3k#LDi zU{2{^W+K*-c?p8WxvMG}j$?m)eN8FloQpQD3IN1hBYqK~=$wei%tWNBITtUPs0uN~ z7?)*<F#>={&MF8XqFzr^)fi*WIps`5F@~bAmY+vXfVeJ;sxpUVS&A<=#<;GlsuD9H z5m9^9vaWGmOVOo>5SS^pi--v+rMzvsh!i)qSz$|vc;FD1n6uRIU&3Ws(vgb(lXC_T zB1|c(7M_dc**Xs#OUcJ9DMtFmFaG@NpL~q~zxnlVK7IPOe67I2^*9EAE<!lhj$*^U zqGIXq#P9YaA|m;ah;Gg-b4;cVp%(?}<xiA>dR1%QOxqt?YE9dN%~d<^FV(XwXkop+ zNLb${svu1Y8ZfcY&xikUHVaFUE{V7tgg77DZI%ayU{C@*#K_nbBB9eyv|TNgn_BIt zJ`fk3H5pAWMO%N@4F$b8I6Z~qBy?RALD6AHo!#uG4;tgblF&bYeGnr1TwNUcSN&-c z(nBU}Imwsv^N=iEe@00Nr&=lYjX4TwI@BLb&T#4RgA`z`L#Prq_c0>W;5W2kdg)<s zfS_4z3ODePmKV#bP$P9sdLHjK`KkKWaD3xz+PHYIpgy>PnEj$~&pg^P)QP0jd}97B zk7m5h-fSAMyQXV7xweV5?)#@KEi`n&OWMOW5BaS5G?N^T19=oWan;+#gNJ!;D^irA zYg6OJzdj<uV3`>87vzcpFr?*Mf2>({D>yAmmsuN%zF!(TsZ8D^kxxAB>=V9RO=__c zmqc=I*5p^}zK}t_@825bZ%5K+B7rf)9o=FL&dG^@%a=`O=Ki&5%bNn+&AgriIJh!w zOcMPkLvI@zh+HvzKTHK*2dj&?mkO}<b(!t0wo~xJ*wKki8?!RmxH+xPYuIP6Z<EtN zZ0DNFJ?w%ytcw}=o?AXOvhj3hl*DL61l}BcQ68=Dlx7g@5o9nBd^3Dt3(Qd0#%!=| zbW%R$kskce+?Jm<kSV~k*&X4MxI7=$%SEw&;z#a!+~t8ktOEQaL!eDZpXRttrGlHI ze((HX=ZmT?j2`-j?W6HzYI{jfQODC85w338D2D#bh4oJTv6j&m9o;S+?ir%hbRb>2 zxez*c@ut~!L@~w~6mm)lKt*yoj&vNQ9Fl6)f>i`Sv*f}&0<(zx{`bHC`Jevnb-jK5 z{F<{K$3aAUIuH?=a+XMe83l4Fx3lj%5s65QF)RU8k0Yg&pPrsYB&AaJ7DZIKyt-C1 z6A{TOngA402%$hRmw|}nlo63aU=AVYl#T;QV~in$q7)U~fCDm<Xbv&hlrnSXoD+f~ zQ2;oWWdT5<RMcif%K0ef0z?v#`~AMI>v0@Nv@Q#xmNHJvA%tG&m557bPf9uGv@B~$ z^krrRfs}I(jMH*-w~|E#Jv%JxB9ak_8A}Z$Q2_ywoKnh?%6u|&c_}j&$jW`+V_aG{ zsQ9i$L_rjg2t$b9{PbtHr~i~v`svSp`Vao$KlrP^`ju9UDmoF9hdKb`>xIFzO5|E= zxT(dYRngcP6i>9?fRde5=QoiD!9UY>JvjZ|s-~jyzKdw)DHqN)H7mwrZ&eixA@7RA z*ui{_LgEgoNl1E|ji~SE-1InhED;SwP;)@j=d_N;Y!)tf*XjNx@0ywLH212H9(3n# z2TW?S)P>FmO!#C5K8@vv4&*yqew!>W5lt-*a2g0+y<(=WAAMa~MOAAaZ&8HD)FB&9 zml3D!;8Oojbu#ecjeb7ybhmqoT3IhTJH6XC=Yfp51LeBZ9Q1PYf{%y1$Qrnsz3zZI z?RK9fh||g2>A{H~p2D49>$*Q3Y#(&o4qcqFU(WP%nmu$G4V88Ku1-rfyy;5h@ZV7n zxIN{bjIcywu;?HfH?)*~nXkKuNWPr4h3{S+B_1Qq63|?;S0i<+ISAPg@&-}i9Lmyl zt*b58-soWwpn{>!!RYN&ZCXlWnU7atdXW!leAJ)zWz?(ny<Sbn(?+?xVjb!gC+jC> z+4c>+$sJdE$w{iOwHmV3_|Hkhtcu$er2jCSOLp`?r_!^%vQyW%h_l##im<iBvSwa+ zwB>!sbT<=to!=+Uw7Bid6Hg64d@!#VP9b2)yDnA%Xn9p<lkPMeOJJtQvubNM2{ty$ zAH=(+fn3=ah7<f8Pw@u(`cc=9RDgZ;yz$ZsJ?ZLaP7mVsgWw|GokJDI1qEN*16#^R z6{r1FR`?U__6#_2vG0=}IrpIV75l+Bl^k%<(bvy*!Lk13@`^hNxx8plg`7nS*kexl z*!PqYBLbq7WY$t17*s{e{|S+pKYsfWltNgT7baHKl#+@fo109sB+O70;1U|0QetLM z6sZdE?WTyh@4JYE5Qr#XM8uqu3WTr#6z6SCghZlsS&ww6=4vQZK|&@Z0#zmMir=<v zQfng-fGle`j?SB!nvKkXLkJ=6TOwiv%$Q3fM1)koo01&IAtJ|d0Kn7J6LU!EK;&X6 zsA{T6nYx^hq7dekGv$3hLgWxwRrY<COo*5fik42qq8SlFWM+zyLk#!(T|t?dm_$Xh z0ss@|e28QKJ`M;WsFr}(N)|aN5$BwVv_y1Q`bdWYgt$K4RtEgzKmOxi|LRvC-oO9v z|M5TixBvG4{Pgh?0ym@JKv?w{SBo*LF_eJRBo1HCaKvpwxn?)|Bese6v0NxA*wOQ^ zPhZ<6#hB%?J^eNrEQM0CWAL>5nt%IYY%l_s)B4&E2*do0N6Q?P=<%*v$a+V%a8S=4 zP{jP#(v&y3=9Be3Zv;6HewfqEH&zqhWO{XQgB*Z{p5PldCTw82kLl+RKwUrZL4e-F zGFQEdrWLU?^HKS_Pfs;H?P@fG!R7m3ljz`qR(n7@A`S^{*B(wkYAc}S+`{M$I_(Ua zyP(6Z_M`{7yONllkk=oava(NGviG9DakTf-Tl6!SGu%~K!j-O7gHp8m{m`p(e)jy| zCCSc$Qy$`UmJTB-jCIk*+3+g2@79%qH;4q(8Ox~1v^hte$2*ll#@-Z4<1&WUJN4FZ z7U?uaJ}v)zb*6{?lk(-<IzR0cq&~x!t)gpZnjf#ITwDm+ae(G*4qqi}wh~o|*6Djq zgRyse%Z^1swv)>pLq1)i{;ydwRNCa!W@JP?^j*5P-MVIbRfx;6xXp&G6Qi5&v~v|a z2dYjTTQwcc?(Job^V?4g4z>Qh#lL-E)TkFtXWzh}E)mwz4S$TRzF@gdT<O6C2H2@> zPCDtfj1q#2WMe=i)%mct*{eAR&bp@si`NcK)KNAnJKX%cK6PT$R4*B(n%Diigoo?h zcWL9c`@ODX-_%AU*odS}aFbul-#u($GAKRn=a0I6oC1snHwWV{YSUNo3Z`Y45A4aN z*kMAwA*F^GYpe5NEm(Se=Zqd`vGRAUsl{ky?WXvgQrNnru0O*nR0?QA<Y61si(5Lh zCl}XA5GdJMMfz6*EHxsl#g?#cp`3G4QA7~Yl+uxQ$RdCxo|sT`seM{X=!xc(B}<I) z^QVvL$e_#|VvNk3v&1!)SmfolEK5*LB3Q}-mk8l^@7~226##*6D}BzN3YL|s9><}o zx7%$$_P{|zMG|vdmNlgmLM#<iVvHfi*Zb$3)3U_4EC_fULIm6PvhQ~Qig9^;eKGx^ zD8rvVeO%XA0H{I;x7$<B`StY`5t$<br6U8tu^%ELDg|`<c3X)w=e+MqL?Q6g(^vQV z-8|%=q@p<=Ic-=0u2fa;_j}IAvczS%3E^?%eNQD?J01BrGE)G6oD(y|*m8_xaj*!I z5&<HllnE(|s7feV%_wo9oGV{TDHSN`5{Vtc62fw%qv+~ICogf}A+o3t0U_@D_R~N5 z*<bwfFBITU|IXj}NB{UA|EvG?UlUo(+9WWkNp%kW*wkRGjI|SCF(Fo%zA6*8v!c<f zI>++7O<J51;w*d^|0`jQbT)cv3xreqz_tlCJgS<+I5OWJ0$ssKTap&ohYEz?bCvBC zg?D-F$oR}qbI<K`;}yPYpFaku)xzyFP<eua%h@jC;1sk{8cZ!xsF{k99&jgn?^Gz# z-Le8g6Cj5pk_&OR_Hbf)19dg=&q>k-3R3@N=&lcoYdSjs{Xj1J^9B=sV<5)8?M(Fp zadMDXB-JDyat*eDfYum7H9HYJn7sy*GZ}Dy@YRe90HD&qO)iZ@-p})fp8uUanNV;a z0ozJHvmU<j{2(~n!7%BkFF*43fB%8l(umW>FZ<&+*Q3?!u4tzwJt%l{(T7I^c_ScV z66ZYz-ZU0+zsPsZ-nmx|=<Yi%`rd1OewY7gy4l-KOYcnnp48>FzPBSy9yj|ayt;f= z)fKHU6QHBc?7r9+#csVZdyRb!{%6C<e}l%pPyGM)*z)zd9?NiR0Arf{czE%k+w$(P zyFwj!d&|GQpuQa(cfn=v2tYb&(RUKqfJ0V}fYbTz!8^WVt>0J_A8|wOWIwB^eqD@g zF5Wo4$<DPAru1Qd-ezClpAUQXH5sj1spKI-=MAd<17AN<0X89H5?O2*RziB3DGP9- z@sV=N7gHY0P^Wn@ihmI6g09%csXga`(UGiA5*S<_-bKMztKMa4z%}VbE;al|*W2t& z6cmY=;W&;g2>?NW5R+=kIjS<Vf{JEhB85^8H>G3Swh%aHO(_*T<omWAIW0?ke*OXx zw|zghJx3NHEfseGh-g`E$FbjTt0IX25kEgYGjj-h>^mXG7*Rn)_I%{5Dj)(WWg^a5 zj<kztN|Mr{szjV6%XUYgoP`Kd+L3TsmKc_omzSL7{kwP6N;&QOe!t&|xPV}V5DL&# z2uuw7vF-cz{PeUg>+9<a6D=_oHMrnfA!_X*A`>0^o=W<EsalkB&B{cGA;cJ8UteoD zO36r7B_PczsLb)*b4*D@a>^1y2r(imvq60zsP5ag-S5N<fH82187_YG<2XvXvWZ+N zWg-LsLM}gxcY53IWv~E{G-Z+d%j+wDCW5Ei?aQye*!Jx`y!)5`%m4hZ|J9#4;_~|2 zITfShWXycBZi?;)a2r}pc~;A5hc~u~XI@U}s;=0QiLcm<M&;|;T?3bl;vzMsi3o2P zZrjgcKbb~t{0C-zZ2IzP+q$yJmfX|OUoH%mqek!g+d?7cyb0HU#e-$XozBd`dnPZ> z-LrH!KKtFPd40~E{TL58uo)s7P4+<3tFeq8_0#VcO!&=#Opl)iGC1D-eY*HQYX5#m zuAb@S$Av?eb@V0Zt5aIRtVkD;%*{q{8C2y{?5?K0(vJh4(5CaD74demi<Np-XLh-K zulkZR+8pcx(2UV|S}(Qq#YdXqIf&ZNo@LILt2tykwmCc6HuJ{}x-q`7MVw(PV4>za zJ)6?}#ZHGgH=A?_qi`3R_j9aqr4w{^2^KRG4}I6{dEVtp`xK)&x{5Lv{k_@|L$ePy zHK==?3+VMmSZ!#ujXAnkJ(@kgnyp#2$;l6h1pPoxkyF|bPsxYAyO$aW_OKTmWSXnx z)5}mbyAocGNZkB@Z?+A@@2^pj8=9TEDvux3x*7dm=)o^<ZFw}t*mf?~3X9nGyBVep zOp&mb0(zv|d?(RfrH1<1o1&f7@@8!yt=m@aw3^)?1tnSdl?4YmE9&g|^Vd|UZ#t(Q zPJ-45R$q*xiDcEd?6y3ZA)bn?iU#yPyS}AuDmGhcD>?aw3-dgX@p|h)pQ$k_XjWoY zJx|c;!mI>o?fn-Uj(@=Q;}qbQmvshzYOdOLb-$3!h0}Puo2bTRmhWRxU$s=YVgz<V zpqcv0N#Q3N94qWBScQi0eYE0lGWKV%IjI*lDk=GaU?IUl?!i_owG@W#v}^Q@+OZ8z zTSBc++axJw1rXiyk+PKfrKHLtIja&%)+{2b2vRV76jcP|Nc)k4WZCYYZ|nN*X}NEA zLJExg{pH9>LD%&L!0Y-104e2t--$2;&KYAQ#2})glJl{?e+tY?U`AZRf<PRW`~5Y9 zur4bx7ei?}kZA!uL^E+jjUvKCF-9W%{Q1+q-$S@DGXkXpn4cx@$05Y^5c=@p%The4 zKuYDD_kBYYX1?8)bzNRxQB_oAUE+PaOFC}1_4c%)0uk-oE+SzKs*;a`Q4um|W@J@i zR-zgp5Sbvum+!wijty!>QHg<;5Qqo~iI|80?#puf^!ej)NC>(t;pOEcA`l@{2owYI zhv(%;IqioWIYvg*{r<|!ipVkYvMeF+x8MF=1c)>Q4uKRhBE=XuJncJ+WFq?T;c46U zs39E*6rP`+L<Ir9`R1Gd{OAAqZ+`dNzyJ6C?%(>;pZ(@HzY$681VaEqDQr#!J=IDx zT^7YFcV_C1Ii*+yu=aqb)-(#D;0!wDLM>`p1T+=X%A9B|U(GeswQz<m{nQX2Y`_&N zzO0;2oS)2X2p}zpt#J0nWNP<|)0nEBiNjqOU`t2tG&A3+1VwP0Qq>-;Z}0#c1+svU ziyWL=*r*9-w!!Nos;KItK8;(F(}--^+vzx5(tpl*Zj&j!Gd=a(vH-fE0SjvlrUxp1 z_yS?(-qi-G<O~E&Uhmq!<*g8S&A%5^oS3jfmY(&!H%^mrm}VQgV8Y&mmq#JqB#gE| zY87rwRi-BAwfdG&OFrtjO@5dkc*wMDA882-6|FSPeFC~j-Co)=#JuJAWLN5Qb$T7N zW{~h=TFULg+ENwFYiNM+z2;!|I5(}Yjb0~RYqF0|5r(5_!|wJ(DtoVUVRg*`!8_kB zWZKEH=7Pw<S0uhN>!?ZX^LG>~Z*0-UXTIuqUFBdFd-5o<@hn@<gaQbs*=saRxlP68 zBs{c*xsCSVQCAKf=7MCtdo6bd^t7W-jSi~`jl;V*k%vTL4AXRA(-8-$bb4)5^QeKU zQbP(X5^q}_^sg(y+->$Qm;ky78urwv_FSr4r)Gyu{I)^xJUM27nCu{Z%OHTu5NT89 z064Ww&1es-jbDQU+bp#iyBOt(hNr&I3r$t;y)I~M9HCn=Ot84<7}z|I6@%K|EHR5E zJYH3?9)ja>)s2Z}L%GC9FcxSl>)aBq`WJSxv3s^c4`#T}l`&yC$yDx<t|(pdw~;{& z?>ad>`zXjsQ&Xu(Z|pM;f4%O1K+X8ap+GM;!wUopWCuf~tJrkd9a09BHf55u<t%rR zizw{IZFtZwou-oII2-8yho^u2ZtI&xb<+5?sRiGa-XOYxpk4hz>gOL?0s}b~?2aWL zJ8JGF0DxMGR#k~9hNu9Nv#KI86Q!I~h1l1v#)9Fj^>Jbj`+j`*@a30Zegyz8FE6DS zkEp5&a|j`(B&F{at{ExDxbGVgmCRyhLV)f5TEcg8l6^}67-LUrRTX9`B60{}St7OU zp%U>M;{pKNwk^xT%#sxVmSuf@ddG~2m?ewk20=+V7b&4aQpXsVWktjSK$TNUDK!{> zIgaCg-$0SuRkDJgo}LIvL~|Au41q-?#GoqaNGgCpOI+{UYk3PIE=wsIoQvMhfj+%_ zQqa;LL?Ysp^0F)@t{`Fv@wTo-&tc|ujUg}~F$Zc_S)EdPiinxRx-Mk`mt|oNh){lE zWJZc1l(&e;db|DZcfb4e>GPldtv`Kzz5n9R|MQXdl95MccPLk|9PAqs`v1#6!I8k+ zUK;UodJEd5IT}B=Bcvq!H(OW}E<3VQLvDA)hOHg0iFMc*D|SmK67=4K19(IjQ+&s5 zYmM9JTu%W3@HCM5pH0d1ore!rNKUX98I%?wo?X`CG3oeNL%Bb5E%!-JvgPrcBgdP8 zIlr4R*0sT6R92@(wd%pDQ;)FWcvVw5!o&UywWe(#lfn3+KLZV158(m#M(Rg+*U-2T zkahr7qYbx$ZY(~*8%GV$<lQq^?&uIk(6`GVEzfS~Jr~qATUnFQ6y?(&oKk^KP3=hy zILH}2&fnDnZ0A{BpH7N8{xi8&o58y4V52VPCze_~3OeTuHCvL_|FG3r?eu%z3+G8V z%N2%CIi2R}XIP6V5Xb7By|72w#w~%Zi7IVQS`w^UB5`dQ2l3roqf9<DLBea8E+o6^ zVGYvH^XEascM!hN4d~kR^Tx!zHA>xhO=9&#ViW7HDHxT;Sk22tnI$Ob`v`{DIWX9o zJ3YV7t@}h>GuwGYB(`cc38s@+k4v5o=>W|DjhRrj^bj_aiPht5a%^jSgr2cZs_P!Q zEjCq4@~GO}$I?o_VlO!77_uYU_6WIs;a7x4CBzOq&%sP#(u>(EyB-{%ac{}K&?ub1 zW^dSrU6ndJV|{M<qb)xj8J)-)^J_rU=sIS5>YBisg4!N&_E$SiY*xwa`iP|-OnIj` z`vrD>+DBo+iw<M#-G)xm#YbQh)JCBo4oFncOK`@!s&eA@{^bEpj@sQ?qc7HI#<-DJ zbgNvQTb*Cg*QE^#+ODx^4hzz@(dpDklOfSFru5$q1$w%?d@$K^8oAH@ig9)-@J!iD z;_o7~AfGd>50)N$@Jn+tpvPl<w13=;!^I27_Rq%kcB>`?ntN(sD_2c+%JTq^YRasl zingdoY$jx-BCKKyQ)$3XP!m@`6;<%tZ@>N9e}~rFO(YksGNnvJ2&{^w5N^qpMWmAc znlo(o!~xfZ0+L92ecf_a=9sgjBO}5StfeOKaU7)pZ_XK1LL_EB4lK}C08ok;sRB_T z429z(0e~FGod~mN(Laf5rPiFQJyJwMSO|%bOWuVQ6Dm2wAw<bJi;$JLtOa}V`FVYj z*JIB_Op#TQkON0T0!St0Rx~d$mTFH$7tJ|u+m>?<fsjHe)MWiB27=q|Y2WsocGawi z`?0OKhQNTLDmhaKv2d~yn_a3LH#=z$mnyeP@VSV-zHGPK3eBq0YAkb%%k%U5Z@>NY zo8SD+Km8~F!~g!j{p;7)*JgtCC*0fAbw$a|1gn^#Dr^%S;u-4lf~0MuSHB%2sCo#L zYDY)+P|c@mennT_Y}$LRk50tD?vHl(2OrthjLq|ow$9+tlK)N5x6Timz%(T_y<xIc zk7eP;?te->hjfxkFHZf_FXy}0>}<S?6`8EQ9ZcNUrq~Zp)~s>W3ufqlk)G8&L{$FJ z-hS_4YFmo|qpP0Q?a)@s<7!ankJih3Dhfls^kqGo;qP;CJF0T=D*%*;XhQ7)L`8aQ z`Szk9Rr~B<o95}VdG?}biMmWfzFdjh>Sw8=0jDdr)(XU>wh$^W6c!DkrPor4H$g<Q zxJoD45Exs*+>QULK-!Hd>QO%sOxv_j2-Mk!FzFI7rtEh7KLtyB8C)onz+H!_;Nw$D zAf*<wpj2Z~i6z!rJ-3B`b-hA;Js9dl)%lgQ_yXG?4wy<ksBam2?%%A^aMOn?{nx6? z($$Pc?R`-!Nv{QHV2dTLzE*P?HJZ^$k7_Xy*a9NzqHynRUlelGZs9rBei3&p+P1JD z{}x+5sbQa3X2!~W`5vB$M66lQtE(#3B0DM&QH|JFKr5!*Xb=IkdV@RF)aYUxS7ndm z-t=XkTWDx0BVR+NxlydQM-&ch%Wbsb7Nz|h>+p<PYguu3A`d%j+9{RxN+?hZRvJ{h z8ctksp{eRiRWYkOx11R?N)cM?gsBo4-?L}}Y7uJQJ7vb58l9xQlC4L%D<U_w1G5dp zNkJ$ARY<6%vs;*z=OOJy+Id$G{OSEsfLw)|nh`0g<yow&si+D_o_G13BC5`I*6oRA z&R{2lRJb}RuP}NB(P9E4asf(~WGk%z7`c(^&>t7aG;R~y@{P%>UnX>G*F$&=>WXTr zsMCJ2k)9EAv&3QB*A2r@tjxH#PQD>g{h;d)qX0XkFLaQAr_}A9?s5qnUCksFSXrm! z??-aUXpp|R@430<I!*<wE*owZ7;^J&f@(8_;6>Q|X!-7jj@|$OAOJ~3K~%7K1N&qS z;<AA>akIOC0NQB)fFgLLEO2O57*J~oVyZ^-22|L6aS9@!g3R&b$4^;=xndyi`;JIJ zSOPCg>05)LBBJ9sa?%{M05gFiLcx)arPvQq(UZlT-&~3dAs`BK4Fo6w%(X^q7Euix z0T@7-5dijMyWh9ldMgmh%mv(uia)lg@ml$c03b5+vQ)=u2w{m!2tgHdPDeUyv5I<p zzi;WtB0z)yl#axK0gxyx3m5cg$$7o4hF;TVPgF%UBS@*GR9Y@2mzWrVO0mRJfUy*! zB1Q&ENw#fU*Ci~gsFuP}1>>rebS9*t7;oEFH2gYCqOaS=96_^+6rX&>+*1AU;fvq@ z?&B|i@t6PdU;K-o{`8N2``h0aFMVTn-D~i8o18R<?ynKIbIU3;&eht#e9&TF>&e+D zwtB8kx_5U>m;IpXSb4jD9W`oMa1#>Mu=@}J;7~L+;#H=r{oYmaD_rG111B!zAFPRc zrsFjibPqH-k42l!>cqQDt}60$4;_44Z|sxc&Xx162jJ5E#6{!hrl8muPM~51QB~pE z#Ock(?aaOotolI%aqIPPAWm&SAI<B29U4BnXr?zB8640tv3xx3o7Z=q+iJ*Xm-H|7 zgw+#pk(C&^hBud{A@l&&Kq<dHdfkCetLJ!Tvs-yKLQRf5+dj<FaSll}f|~ZGcYZb% zrHjk90cn2Y^=RH0X<NrKQuQxAb<{+8G;Hw3QF|RuMI3SCwJEDgfa0v_W=eBL`H?}L zdfbucPg~C<O6P`EOYs;Mv6Y%{+UbDu>ijTW_Hc4t*ZHPh<2A9dZ+f{SoHhdIu{cYj z1r(mBr;XH%P-h}B)8|Aa9%GeGl2~_a_VA(y`?{EGUHpg}hV9=Pn~K;Xr3YtPA2mJb zkDo5;#d|u=ZYzL-1XC{tgQ;ukAq&#JU^p#`ICcHIwtUwry;9xuNu`0b>_KmD9qu%; zG!sl;jT6$9Erj~7`P(kCSA9b4C3Uqp>T~RNN9Y(a!<!kcZx-~FX?)Myf3Lx->gU%^ z3pb@o{YB=&9Xf1BNh`H@-nq3uu7~wk?5D;M@T^^jnogq2(b!qv#D}?iJvyeT>uN9o zKgOE;-Pex{fnEW|5HBFa=03VeQ*ri{i*fa!g61Te!9^4X2YS0&T>cOsVQ*{<l!gN6 zL$Kn7Slo?g6&q>TBwgQVOwi)My`de!y|A8b-Ar{B{wn@bpTj}|C2CAjM6)PR>Mo0h z16&jHN>~$BEw1WCiXlWI-nQ+JfBy4jSw4RJRsmErE^9ephyo%!JwKTP78LgF*!Q%q zw{^XhI=wN*bzO@xwk*rLckh<C9LKJz%v`{wRaGRFDnBWu<H%1>PvsG2D(@u<0Hl}{ zv{V&Nsk%Umo@@$md2bn@WC>v@?1!j=b;WiOg;J~OIQD|lT(rs<<GyV%t|3I#S}bab zF-y)_RBLsm@_kdAbIzqY5`YjFSmvmpx7)4ME0!z(xbH{K%7n}as>^a)*R{$=s{4K* z0ura3b4~!Tu8S(9luHn`sP6l&DpvZ4keCAiBC_UO$}`>X_o8yELJZ5kAHVqJFaOy; z{U?9<7r*@VuYdjW@<K$-KwhJ9^zk;q7W^~f7*%pr%q>I_$IY#eQRwOxb8cR!%nYls zc{ovf6?nhJaJb)p@7tt-q-YZ^<^bPe-(fM7_6OZ&yp(F_v}doHHQ9Z5u=LAidtA)b zu-{9+u<qCr@ISs0n~fR26G7zBK+bl?(I@cM-RTSdt2(iLw7^Ax2FY{TtN?wVqD|)q zFHaNaW1nXlTa^o2&B7$z5$@qCy2HZ7VV+JCY)(G~08H-fmowS=GL{C=<LwaW_b{As z{=_s(d>u0OX|cFaZ`gGKghO7Rv*Yy0k*VO2`HRjq8-3%gleK|9W9pNYDmU@#JA`-H z6X3*0w1<X;IA=xrt#P?Q&S)CbK&Yl|_cywx9QzsPu>2}mNvKel@!j$tbrAu|K)4PL zQBh!cU2FV`dpM~7NvE|XFMbm4GNsSe>K(BD;23&+R!V(PgM$(3kK32eA$Si`$Lr+> zGT!afiwI#1U-vPw6SmW|^ym8CGB)D*#uQa6!`*tv!|jg!tzp0ygRJwWcA`yA7r(*V zhd6F|ur1%G&K$PI@?M`E9z^J9UXRX;$BS|`5+|JdH=grW{3y!dWh9qRjHIclia48r zJOo#sw|qMbR4)et-HP#;ccD^W4LFmKu~|<u<&IyJlSm-!!aaPxXW@cwH7D8SL`09a zydA!(7Un>G6ceZQ@EHR!mp}944M=0NGv7P)%4&C^Z>9Y-7x5(!Bib9CC^&8TtLFgz zTZTX*@WA`#L*nssaB0$mHj82t)vE15HMz|UYr5z`vj|89ZdWeuUmB(QT_RA;LzrA^ z7OV61`oYPS<j_#APqH@H5<TkuEl5O3bI!s@Dlmb<w0PhmhEOTSQ=F^i$~hzIe&lW6 zzYO91yZ4`7KZ{Dr8FE%VUhkW##3hzk+!*5$m)q@@k{n0+`0*ov-fmx{bbNmKR4VJ< zZZ{&@_gytJ$5O?od5@79Ibb^E*rh0_`@XB{vaHLx0?@~gA4T`uEf#p^Wm)_ziRf)z zU()B#pFgkb8e^0!Npl;Z=9E%Cii!)Mk|k$7j<jvZx`r5{Le*pUeJ`r@y50~`Bp=7I zZTH)40fc?ubIviwckkcb@2~g!{WuZ;eDTE>#orr3AjIR?Z%<FJ_t%u}B7z7Z#C_W( zD*!=6$tk5Af~o=$6|Eis_C0O;Cyu4K5h0?g+-^5S%1P3eB+IgtNst;ItnlH(`(sa8 zkckN?b1vTXlCAyx^hC(N`qf|l-M{zu|F3`d@BjKYzrG^BhnB^&CD27sQ!7whjr~q` zw+cp%^!f*g)f8R!%vfZv_&~6)uYb8ckCP^Wmx3}haZ~)`r|U77=;re`T|?KGFCK7y z@S%16>KHSr$dWuQJ{$m$kN`-er=mXS>SdV(aJL@KPY===vRk27EG!Wa#)6vPqpD$p zzSM*bBr2uL9`xspf&3Rw`+1n^GA`}xoE{eirDl*MqJo#%stx(X%iikP;Y&p8d4NB# z3=%;vo#3S|>p_tkUB(@F$Eky89!SzG{jP^NPk8I9gIGJ$o{qw<A+e!38Je%4(mS2x zMd#NV0w3C4Yt4HG>_L=Mbl9V73j2H{c-2>R$+Z5zByw2Z`#E(&TQzT|E8=NInvbsU zvQjzEob5x}9z2K;vj}0FglEUStsLDDK``2?aN7HQqI}`;nTEWN?z|{IzTi98#g_g` za~$ZiVX)PlCQ~Z<X!`WRL?n}s&OK5S(@r@NHV+=cu=}6!Y9E*Ep0bYTx;tiZbA)X( z(1JZX1<s8$wW`-1hbAaCzNZF_c6t!Jqtf^4K{bIM6K;fRp`E@6*0kk4m+`|Cmp<iO zK4tS_H)gj74VT!<@D6^mzNAF)zkSZuV1LE)x#@OCXP7R42t7ctA)G<)s=B%IT*ztB zsul_24D{&uYGcv9;Q52G2%xIYxo55CUcq#MHr?7Xrh)X$)$Vqb>8bI?zASRe!%38- zL602nXW=v+wXs|sD1I%5Q{#<Xq(9j8BR#-RZ4pP&0H>g}NjmYT%|&FU8a9dBTy>gp zv@3hc#WCAtmN>P++Bb5Z!#vLY@n7hWq)t|}vPb7(;_#Fc{dM+6olVzBXs9{$pNL3N zO_vA+#GxhkYSC|thY*RFxRkpsPSX-3979}|^~m|FuYdBz7he+NU;X;8a!$*#JUu<f zxFAu1eL}=_U1AJb^0wcZSR?~z2!sen+P7^hURgtOVnzT8As~_}mf}M(hJD|UBQ5bp zM1ZQAkK-t5v@f4OscHxX7&$V>Qg-+_j^Ydb^y$;S?aR6z$01U5a$e$+^1&e>0HShW z07z-C2t=wmCjkBGtFMT#<T+d2U1my0y5C>#_m>hTjaZatD52D^udm0k7mO=HTGv}X z@_y|5e(d|6vxK-ZGXP3~>4J(sK!`+$2$FT%k75ES5!$!gE$6%}>$`XF;u497nQ~6d zjD$sX4}r}+PDCPk-}VBUr7C4Imn9NG2o@ZUg!&i1{PX|r@BHmw{_+=p`Io;cY1`O# zi1$Q{lvaKt^sIakr+m`gEY0hqZG!fK0a|7dRr>oMZ<DL5M^dTn|FVw&wK-U>wrxjD zykNL*_s7P1$qmfhJM%6CL+-g8%Yf)G<oaSQ9oa&`I|QJ12127KW2pN+cxmFL-kxwZ zOq?EcpIb(vb$77eA$Ci%2WtVVh<-^1?Q54+AKzrc^J(JmUY#agiIAeDT-u#`vbiO^ z*wg`IU+AfyQ!$<k0(*3Q4-c?!5=WZUajJc%8Zr>rINW#49pnMt+?!4j_%_2Q3Bh}` zhBn4<5%4ar`EKVk^H>^mW>r7VPC~=ex|D9u2X_bXyULL2{*x*+PBDj`w_U(2fzegT zZ=8ZSOs=e;u^zz$p@k7Xa$HaR(+gUBUj8nyI)dqeY4t;g$_Zy8X(o(wI!1Nn`Hqdd z72)wftcUJJbu5pq62{xx{qM3P4MgG`a3><cv$*g7GSB&CU90&;jTHbYoo>3_IKD*v zq45^?aCRtldjlQ&MZY3$18TMzIBQSC%r?cX{c$q<^~SyatX<J+XWBsCVDS{?YWh!? zpDpgjh1Q>E!19f;neO}K_#XP*Uo0SFN`hH`lq!b8@bt70I1jVmQMXfO5>xS*&-KK# zPn^}ho4ijNfqM}cja@~vpBBB+ny0p!merloBPgSpAs!n#ujQyW4x=8y)K*0cawDK# zqd3)KItGPk>pU^r>z(r75CqFI5L^~6Hp!qG4-5_g8sdUkRvZ*TFE)*Ct01;Q0+kri z5yVispaJ9c1J7(TRBuXGqUWn_L;oOIq<$^h(rg$=uGB=2zt3ITt2tT*8gWS_mh^}% zQ3RR}(?-_@Tasr1l@N(hfC*Vt0J2Dt?XY-m2@wEAGz1n&C7%}&vZMtU=J4(BzrDY{ z+@9B*j}Qn^QrZ+yl~hAcSy@to0xiHyA#y>L+>cE@X8^q2*5~JU0B{@!B0fJq@B3?v zQ3Mbma8v+7WDe^JF(~sA0_B{RC9dm&h&d}F5C)OF-H(HEQDsZ)adCvI!m_L}L}n66 zIqxE<iXlX7P|P86j1c1!fD*At$q+tXUS63oM84e?5&rn`6Mztbpb{yEKu8=)pmoKa zQq`0)KnZIkMZUl8A{i6|M<f;1<H)z$!c2&HKSWX1H6k)0BY>o&f-$ZfID}A~z{hbA z5iyH`<dh{L3K6Ds5OGNuZUQARQ<fx>kQ7OYkcErYV_lbRyQ@kmwj7u6%};;w|NW=` zYgzu`&;ICV??1f%-EV(qLDY@9th9_pyvV3{*mn#hw)hR+sK|HTCfGM`b^A1gjQSD> zc&<=EFUp~!2D@UAA(yYU0y)%y5_+4b{$R(z@bbXLKpys|-1P;G$eGg1kZqXgTn#NZ z#=m7)l-6gk2(iLiyeQ+&R}j!1M(#&ZPR#~2hz_c;RgP70^CMT>2~M+Dw0J^<icX>a z)G<uH;`DG4aUJHM;YK4g2pMP-SbpP&q~*CcN`<Sjbg6pR55(nxPXobLc(b1-mnu_h zN?o*Yy{!DBJKc;(6nf#xH^f&Xf=9tySF_+ccD{LOIB2>bUeS5iG#)-UtZ?gbZPUw? zLnj;DJNQSYm%cGZix9b(nWk!8wqRkU7X!KeP(5a;P4A#EkCr>Ptkn-~Hm{5KK2Xfs zzU;=J$@Z;%51yaJNg=?2-_8SRzv$_cv)ut6E=|i^Jue;tc+<eSK(13i=FcB7UfVc+ zESAAr`cP6TitA!(#}D&z-Mu<=9!PumV!L!G?-SzVDe=DT5rxyDR8W@l)~d#O_qio_ zKO*=C7tX6WdT!CcUUBdsqMK^})adK$$?&78@ev7OD}dDh_9GZvk&}m6L0h@Ct4Ywy zpjqFgd9Dyi4JE`zfqn=R)s1cFTf=NqbjeFWJJi<Y)hSa4o-k9_6=lLzm+-AcfvJe& zqyAivr9Jh=gIC(`NL}vpDdI@oE&KEP#P$3kuRk0Lbl)u}uGg9N3_9;*iz?`Jj?z$A zjQHI=jYK~LjI{-*qMDP32CT*N@<46AKS;HxqkF=;31GmTYeo_E=nLLc;iG6yMyyT@ zzFbP%y)_m~RV&V0%UMT@s4t<js+v>o!Ei)GqzWPlKm+s3=a+pyzW(Oxz>EkYIi&-T z09iArs*2{65S5sT2rG;s5Ft?oA}(pP1)(bEe56AaQW8R5Z%?R@(xIwEpnxeQq+s+d zQj3lf0RZoNPC2bqjgCZ=vmoNr?P*<aMRX{KQA$Y!VvISb5?`595>3p6sG=%aRV7B= zw)?s+Ay6p+6#^Z{CL)APOaPMd5kk~b14<M?LkP>V9>=SKGDXCosvKfL<O0w=9c{?K z%#=`6n2C@$1Oz-3bWhA2IFvl<x}J!taO}HCQV?bgfvNg&834<8OW7F#AVTIPr6Xf5 zMwOJ3=pm96C?^pCqVW9gnV4R;`&Zw5{ngiB{`Rl`8aR5Q9C?rlg6EVcQ#mZu>MSsw zFC)v*lyg=v2HXpK)^B-3WI6B3d7C&ngIqyQFDsVOi%v;vGgEq_Ka;F%1M%}S9uH;D zs)f#WePbMtX@h8WqCiWeAL=~WrG!bv$8IM3%3~eq;COkMQ?%;1t+(}PKjScun8tO> zJJrWYjHlsPtP~iUi2BfA^-Af<YIz!fi<;5iA05@#4v^-D*~zl@qE5fLP_Cq?S;qCU zh}Y<BOEqjW3-}zQ`HSm^XuppjtgL&3P&r;QZUlF!&-;4N8TC#i?Lcm&MRmw?=tG)q z?_9L_n0pK{T$65d6|6o!J5crcrM>006DKqvqb|#x6AxxHAJG8V6W4LlW3^=QH+B9x z%h8&=2>$BLo(5vWp{6rP6$yG5eN|)+$@YjQ-;`+8_vfr|j(9)U&wkHEvAAUyVrqGt zt+woGHqHZibWOg>>3VY@(6qsa?;Z7@$y=^2`&2z<p&hm3`*0e|xx)=9`a((3bAG4& z<tlXIi84pl-9PqNt)`IZX#cfx@t5bdA0`fW9<w0qK(l(K`*m>_@NCd&UZ@&ZpiQOo z;S5bFHKQstpsa_i`|;iG8ohYZ6(Twhv*(1jbJE!?Y~&rLtDR!nRs{W)xBdQxzFl6W z09Q#B;4P}Bv0USCxzV_itLJvxy4W`z{BXZ455hbsj}q7aYh6E50rqijzC4LpE3n!A zCo9Fohz-1~Sdp500WI`VTkAG8V}_Ddr>K{Q!qp~oqLa(UuaA8*DXzH@$`jPX6kWB9 z=C>NhqGQCAv#L64Tu1pgCpQj(My&(2zNm_3$q6ae9Z&<XN=+aFEU>|u8L_~wmy+_L zl2o!Vhi$*_$G(Im@PdGnfl!G{yfoyTRFN4AqLpOGSyVKH64SdPa!PXSDWwFUaS8WL zkCe0Mz8%a=fe0w2Bsp^plNOcCkyVbI6CyB&lnz7;VGR;W>0l-<^+<9OKwQ=p2~tWb zA}TFz0*@oLa;um#94V>jdRv%F{-nkwrYsy7P*XY(Aq0MT+0r4)dMl-j_HAE2+%Qr) zlH^QGB^X;FD`*T60FUD!W<(~WQc~(T?tzgQa~4owBm|H$A_@lMOhm_#5C927h$0FI zSwvKb6hKo>OI$?|RLcq?fTX--QIV2`yKkF<g3uBdK)m1YArN30FT}{q;mfbT`R%tK zKYaPsH$VO6KmLdRAdtyS_=ujmVDPteDF=boZ_G-hrxV>h08PJERA(Tz?N+FryH3?* z`YBPf<1w}k=C{c?2)2|=K>M-+VUL`mUc#k@e2JF08$59a8&=n98nfyL4>Zx!XOSs@ zATXGo2hfGzy0eWPVY}m_V_G|QbhR!O6L@1&7SJL%gF5=mK5S)E%Xx1Cwi-Wdpx`um z0lJD>B{nZ`TACqPg7RSFtFSLPMgjB_(JkD-V9OsT5AggQ$4gIRZwHERVUpO4dpr3L z0hAgnlYbXB8AJ7=Zr`Zqbn(vLndIz2EmXHu@O`hh(as*HS$4te9J=}DgJ32bZ``qH z2wPLzyiJrrf?CAlvbTo(d>Kl5cDc9Ss3M6Yr$-N73v__e>I`|6%$xQaq@2l-V38mb z(bn0snsD|>U)eUd4^~)ai@)n>DQ)s_QBYegoEB|~*kCft=q!503^6nc-)}6+Wp^L< z2i4i3&KFITKR;VV?WsP9m6mCBhP)BSao7j*V+rl&FL0MRamt_6A#&tmAdhfl%*Nyc zq|NvXeNnpZ<WbP=5FF>m#~xn{XEMc(9ka9!oy?SlEJJ_Acqudx>^_{S7`u&E>My-0 zz$JWl`QVI&HVp(HQP-r&k2>&_<KstU!D}Vp)QG!qrxH1pp>A0ni2tpDe5Xm`Aq%R; zvcZ<rerqs2kGH%r%u@2#*Vr?wmf!L%E)2yUJT)sGo^R^xV?&RzpdZY@-63uY{|Jas z$e>5Id&|2We~%In{=nCdRDh)~NtZc{iAa-%Z55@J$n$=Ao1I#^swlvygpSm-)T0A# z)}Y)hKBX*Gd5hsZcTWy>oKFj7@?rf(Sm$!jHGC9F00@DrGGFkPAtM?nmzUdI<?*W5 zTQpsz-R5240@hcm)i;PyXv%Y!W?F}nh=}GuK_ORTSm}$Rh%z&hq6(-~1hJe`5*1LT zd`P^>vA?{2eo2R{@%cE8I&TW7z)Z)!FH1lSON`5Md-?n-sd!eEI1y%M+V?%iP-a^- zBQkO1z?5^!`+e7iBOw!oK!KSvAFr>kK|<kN%Mt^}oJDfNxGZZZS<1_@94Rr05Fnt6 zq*UCVno>f95Ef><ziu(!m;niy!V+)Wb}-$ZZmVe8_dBBA*2r8cA!j0GUWgJ=1f`ry zqI5*$z>5k295J#;+P0S?Wh5fas*-e1$6mC=oMGE`N!z-FbZAP62-n*U6;s-BI*1|w zazF*$_ARH(9131EQ^0_bOTI8<k$v0sMv_59L4i;~>Dbe@B_a%g4^12ZR8r2kF6+7| zq!1`4K_Em_K~ebQKl!`A_~oDf$<P1jXFvaw_4&5nH{zv%yb*#WAV6oVRWy`lY9UZ{ zrcjS3*kzC=_!t2Tbc3R=XPCVh-Hx;jn4O){tF@Kj+m@qd#Ff6mD~}SuE}?2EEr_ks zeU~8WKoo1vL*oGcOf^AG+HjgG-iz8bE-YN<q1FSGR%XnHu%Q*wH0X;mI<0=xDyOQH zoYI2NX=M^Cdu%aaga8TxDymrR;wY!{0I?@uNh>4SC4?F@j?U9%#WPV_^~E-6>Oqei zRe-N22`vyKBZ!v75CtqHUI!-ZlZ`!&g%QA|kYt*P7jcSAL!hK(8hZgl69sb5mzlXY zqD3k9c;*HwUMovAV-4g|jT|ZfMLV<XG#P^8q-U!@`>dbtRn7Q;*jGbaPU3L_iWjQT zf3vM4z(Bnh0*V#1dP7Yz>+n=R%=b`KPwBElQ+oRO$Q?9=Bc7##^FSsS&_qbyx@|S3 z&SPwnJ<KMJ$JbdiE<b#F!X(;C%f0iqiF2Q)ML#bJ^%h+I==iKOAsU<HAviZEldHe; z_PIY@S7}x|86lngq>X;gS$S}}u{L$S&CltdADRisCuQ|)eQPI9om^}sWX;xh@{(y2 zwOn6Oo3p`x&Hls|VN^z~75vYuZw<;63rnX~(G;q22U-?;DeEXIDkV8w0aS9~E>0cg zq9LfakU}v_HfZ<eesAMfC^^ZssAxG-qz6}M21}1ZGCi_c!%aBPt-4_`BbGp?+;mP` z$}V3+wK!PtMe7_Q3b$<e(w=IQ$Prah2@#c~lcWMbDFbPSahkRH&f7hXqXJ4+sRuiu zrLL6O6HrxDQOOnEk*H;TG)pqo92|?}gZXkWpLk{tZVL=H(#z26^M-<YexXYs1>b^k zn>UzYdr=dJ=7D&7*04LK9$p<N>N9}O13B|sD=T$gK`YJen{shA|23~4sQ{DPsDAbv z$I(Yl?a9o1zAP`|!Bh^OnagWZajy>Y;j=NoqwG_H2E|eTVN0?F5G2H&)qL5XDQ0Q9 z%y5`5Z}(OzCJrGI0wIz#Xx7p|&Z(4~!DjGDNr(bKWxhm&2!wF#+w1Em(frL%fAXLH z<Nq7i7$cj8pbF2=?>XSU9XS<bX;H<T^XJdow%vd7^-q~;+qM|P^YhdC6hjQ#u17kE z0ujX+*BD<uy%JfRsumSjL<-(j(aDdL0JfB~!B7?0<kC-7+3p7iQbp!iG(%O)c}F~m zV_;$?P<a3TT}tWY<wYcI`zxZZ%lqH|{#!&?*BC;0e!da$%ga6I%uLL9yFI_YzC1r; zfym1F5KSrVN5<#pcN%cp_A({QvV^c8hIh}p-9ML^Yz3AI<`yysq5|^FM6_)?04z%+ z#%;SF$MJ6Yu<d(F8Brl65fKp%aplNF2pN&rWm#e^3U$A~EbCfoCg&_EWkLo8=5QSO zNQnv8+tVNa{7?R$|L}hk@lU?_=F6|X{>xwdGKRvwEoJl#h~P`ge-H`N6LoxfhVx|s z&*$sSZEJW-4adugzup}9JqPl3=*|R4d)Zq%EFN(uYFzt#>{(&Yi-a-rGCtx6_D#ne z&b+IMg~j6CQ57x$pPK@3t{mG(@z^nV76q?$lJm3RzI@4k{XoEd=Z*ddm|Qztc;eoV z9)zn0<-3OCyLUAfv?cwXO}%kV^yYC;ry+C!MGF~daTD59Oq!&{x?7|MHWBtLla*1i z`_L<IHNpac9X;6H45+ABKsQ=?N0)50=7*m`Bi2#?03ZNKL_t&r(llyA>nI;KIjB6s z4sK&IrCGd~?~IA#W_EXoJ3SDCdPU7)t^@(q!3DRRplYE$xvRuYQL)W9d2~RvG11tI z9N65j+=d3W#ErL`3kYjmLs#%rfdK+SMi2l&DAnRv%P2|~m1qkSY6(eT=~PvhG4l>J zqfz-xjqlX8l;UA+5i8wWrP|DA)lN`kiDEk<P!bizY)%v}T$e@^xD!}2aw!OcAe5*d z=ozBL4^S7cB#D&51fbfgMr&38(O8rz%R?z<O0CizRcKKQ!!G$}hy+a4`yqf?E8$gO zpPaQ68_^o6Ti}hdNLD2zCL*LzQlAPYQBl1pEI^@DzGUKs83P4IB18&A3m~aTDXvkp zxq_fs95856wICu=*GdGXlwzoQrYc|qx(85zQc6=0K(y%GELuubl2)x45K%NqE~=yC zoIo-nDwMa07$q0uE}#ohXazb!Kov8n6zWqI6-jpP7pzuPP(jgF(X&~cwd&r`27(19 zrdS1vfMOvwgiORp94cHG5poEzl#M_HWCYEsnUR<<%ki?kzPx+}g+Ppgq(I032VgT_ zb-4DrDaXA3k$Fz?4+?ge_nOF{>gyUB6rYYwY0Ga!hbW28IgE~(ll$r7@Ii-aPc3Dw z#Cs}CGS$=py2u;>r_fF4A=P_FXjrJOeTC@+0e84mEgGSio+~%TYA~`Iw~xZDf7JDd z0>Sb!kFA!BvbA&N_j2kMk?)1qvbuh4+|i}j(~$aU_efN24p?ul?$g-TuXx641gYT? znNg{G$<&QV6`jw_Q1xAZ9B#xYqG4k%#pk0gu4%HNmbXf4fmKmO3U?_ih={OQ(KKrT zxI>jJ1z8E9fJ(`>-+6gb&~HC}``3T{>!+u8+kSt_PXM=4ZG`}U@Z-l%L|9z1PfyP= za>=k|rrT`|kyG9|5P)RKDskI(=BLm5OG+sQQh}5t#HCqq6aa3w8zL6`=b{O}zV6Es z0kEjP`@SE?@!`V<#DZvzF|PZTQ`(thjHC)FrRV2&rPyzb90CClb6}3gr(H!jgm>{h z5#~fOEFti+MrKSYzrNmMTo5p&J*Az9MDy!wQ)pw{w!AF2hyeh$`wqw<&~c=k6;VXC z`|BN5ik4gI8{hBu_wV0>LQelbbMO8mNsgV1od?Ot%<8J{o>|T8Xm_O5mG)i<vT%V5 z`~L@Qz<^=l+Wy&V$yY0_q}_RSS5-y?c^>|O5e!CVR?SE=HXNAguCB~rkPPzhJipHr zOC^a>RU%Gl0Ps>W5^{j^`HV<R0nlR%^E?BfikdkSf(s!J!!blsRR`d}wa7Wfp^ld* zl#+)b9)@Fz6%G<8q|@D<h}_>l{NfkC{O5o8ooNL|4x5Ms=$7T{s`;+g{bCE%^y4j- zh!>8n6}#@zs%)zBnxwRq$M@T|&ynsxvpP_grF$(}`*L49L3z`TYR_7qTh*govwgZ+ zXH#uO)V^|Q^r>_$P1G)Dph~$OT?ShtuNd}gq3J$$v677~^e65u<E9x%`wFhzn_Az9 z+iL$9w0gXDL}8y1*UxnWQ)q^h?S=47XZ9;Kbr(XIy8c{vG;F^@`XnpdR?BsNuv?a^ z8of?JyK&DC^vX85#KycB$b~Qb-*H`d^l|sYWvji9xE1^1Vr5=`bC-g#-g1fQdqr{C z#X!1(f{SqFb=YC47((y4Y8RJ^V;2)axEy9b&W4DzS|j_hz+MgLZfv{FFBW7cPd2ct zEeB-n>Pq)@nKOKm&wi5v`hwH=;>BIjleV#}fwe1`-u~16L0c)-Vks=U*!ys(0VxJk zB#sn0gcxIBqGg*c;Xjk23xS!rn^i@~O&4p!(bkOOHFk$fl*U`e-=+;aaMfa$q$FHC zfZ(vydqUWA-dw&ohf1_bHQQi`U!pnM!fMr)#EKQN?g3csUM6G!C#p|Xa7PM_&>Im6 z3CYw75fBE%;GF>IxuIdvvP@0u(zb<f96{ZxY3FXPY9dnHByf29?%m;Z&+&i`NIVS3 zY5*f*j42L@(}6<@Au$IgN-?G(REiIx5O@G2Fj%N2zyUo3Dk5gZDvag=3gN2auIB2Z z0ePNh6{$0$>h3O5S@q0a9kc?hni(Py26F;~5Eni|LPVs>ghyPX1!bW(T6`sDT|R=S znnUkztr?2|#!R4UYT#%Ns;VOHvPcrbh40>(In_9hn-rY^95A|5oztANsjHc(Iye#= zMF(FHYM5e(%qhlHO3Bk$=1IkB>fhoZHV0xrPn?dY!|~0L0-Vo}U;q9O`FT_=W((rF zFPnWU<!YPz1?hhM+pQL96(j3jSVG^olBJiweG~e<;;`Dl%g)}U(}e(BC8XDC@Yb6Z zRk-%%hU{7e)D1^-FT46#S+jUHCWXG%Xb+9H6ZoCIv%n-*H1*{O>w5c|=K5o<A0Gj( z!na4-Y!lrx%k|FwhBw>O$F(<IuilDoQmsF;dvo`ipl|!gH-v`k$UxKcc;D<A0q)Ww zYEt5IIxWS?m9=wklkfVo9zfWKHQFIZ*tFZ8$nI(^)fY)X=8GCv?cUW)ue0Ljg2v#L zC1}YWZ`EsNR?6%y=kw!-58r<A$6uUI2O<zvG9zZ@kmuRW(-0BK%yZ6WHQ&!*Ar>-3 zXQGPR{Cqwak>iPDNP*c*)$EXlKsb)$FbpZhQpzw4(=-7<&e_aEh^lrNP82}2m|03` z7=|^u)Xcz4-SPQ(B!ZMqAyEB*h)SN_1uzhDDY?@BrWETKhv86iAqr|XPniP|DRW>Z z00_wJ5x|Eb5mLj3PiYXz;Hb9XOV{|hnO7v|!{K03rfEXN7%QO>GY4=K$)*YcDwppH z*;NqX&6_)blnbdE0}&%L&2tvDAteBGQ)XbooTn-`>a$cegv2z|gN=y`6je~w>ew_@ z_44T_KRZ7^rIdd4t3UhS|JVO&1`N0s#QH`Jw_BDkMIT>ru(iDXbu0Ch4;unZ-Q)Yx zEW8NkR(~0GH?~M)vv9D9NQaK#?gnk+&Cb4L05^A|@BL_dKE3Tbz29mZ?G|yp?9VFk z{K}HAwtEfGRSbdGX8Y=mT$ZQ88g()RLTC5=A>G6Xb}oiXU9&a5+MK%sxR<@S;?OlY zT<wGlMPL)ceo408;p<!`BKAT!z{VZ0ivg}9z6R3hR@Y8?-xR|A(cCFAixbnXX5d;7 z_tEdGf#B;Ey#J1?HFA@!aIf)P_O}hK{j<7|F7nx~TosFm@XMxdJk&dH#r`<nALQuW z>v$1y^c62j3+?XB*BwFSi)!f$xMJ%-ymhmo#O=TKJyUV@{av#+hsld<!BtTB3#7QO z4WyZ57vXnYiz(279MPN%6Q?(Kr-#%1+i*BiOf`8*r65sCDKNWfnV#lxoad=RV}LoW zam?j`L_}Nx-fIY{2ByuHLX2utxhfz7g{tA;3WZ%!G!c=Bm>G}&X=Qv|V$(Im>ELc^ zHi@V^y5kB3t?Fv78+s3-tC?EmO{yVDL@`$|L=4D*7Jr@BVjKb|BydEi(Lw|?LRt-A z?nHf!)8f)4NR{NA+>j8k8dGsN9#5w?>2NnqV=1}hspLuWY?_A@-@Sdu!@-fkk&uSt z9fwfWhZGYr17ip&hD1mXPRt>&s;CM800sc8fn{?rH&-cHR5h2mNLH~L)UWIkW@2Wp z7Kq33ETt^eA?~U!Mch|(7;vP8DHDka*$u&rx!`gNb1Sq7OaQL6=*=COm>H=BX2Bgq zv$+vRAa=D{fu|~f9#V8u2dL9)itcO<u8If<gal>|6o+&QF#x!mqKw1=!wD%>uR$rr z%wr5Sb2%P{86qH5;87+DF%mK$PUAQ}em6dTJD$fptB9o-iP5~4QhM-6L*mon?#<z6 zUwrxS_76|re4Wqdc^uDAkFyjrtF)K99p~42#f7B3S>r=%^tID!(0jvV$066Fb)aL1 z3Ab_|c4813uw`>!-t?FCy`@FSUmqFJ#X_!cY|U-~0J@UHH>Fq~3%r)1tr}s=BJ9w? za1%j4_4T6+;0~l0FFygt=JUAqh5Z?P@ex2b0WVzFr^Ur_zSos+`a4<*`|f@B3$en} z)nePN!?&mfZuY0etZp99zAo(QX}dURw@~ngC|u2OvuY*wP1Wodf(qPRvzIr@xaD9} zL&SN`A3uI%4tIBVMRlGg=8y)e$-PTBx!Z3Gor!{~l#<Py0#)LrQc4kFo<j;|Ze~n@ zs`y*7o?Jv@+`3zx$1y}RD{~Poh}2kxD?BownF&D67XmY{#{M)-)eJT_2PLGOl{vUu zDW%?CbB1G#rOY|!;NfsM5Me20ab&xim0>v6%%6tX%p4q;m;syvA!16YlwxM}Oqz18 zzl<@O8PlT2@RDxhb#%0plz@ojJQ1^55EV0Jug^je8B#J+6^S8KXDT8QaZLp$BId9r z5iMkKwV!HA;LHIje){Rp{{F+a!*Klk^UvPDfB(%lADP0Q=kN#0jI{_KE&_(INZacM zZ`5+&?kl@n@Yc`m#^xejw(wpH-Qr+ZAnGr{3nA3npEU))`=pt{m%Y4d!*7RN)-CA^ z^vEu?1b18hrt*yI#((YAG`H5(B(z^t?~VEH^J_WW@J=pH+5SCVOhtFt_=bVC%JN$_ z<kc*-9M}C5{njnsnYb^#lr;df4tL+|tpjy8mQ4s>mgY9$y+nhzPu=`Rd)wo#OMCif zU33!QYFYmqt_?c-ss&%|M%)B!_rfk-?wUpc>tem#rQVp|<yCnr4qu{j1)!0H;WGSN z_Wz1O|7vzd%L2P?vJ&*~YnSiv;t9L{`HJJLKC}j-uH7rUtBY%N1Gxdg`g#&d^F8%8 z@U{^5-|WY7k&fPa)l|~@nXRdgWWW%H<LUkT&wlawmw*25voA2DT*`SIpP!#gE{DVM z{>^<#1DIHO{O;?oK7RZtr7%(85IKer>l^0C!*F0`rX_-F<|+o@B5J0HhPYU0>HtfI zF9%`(FjZpa7-9%1C1Nx)z{He@$X5tSL?mQ$SCK5=P19uN;AjS>Dq3>RBE{Sg+|>}l zR84BdC&)axsMy&oFD7ndwOvf?qL$6c%@LTK(E*W&lM|S)>D3i;MNPE0YduPk2{BZI zoq!yGLl{n{Pe1?si(mf9{ku;;e)z8B>HPetc|sSNCs8BEr+J>mm?8o^J>}s*hr^IU zDoXjBi;Tp<)#@n3K}r@Cm4d2_MAcV9jL2$Q=E-tFqMXm7+0<%|7!uWZFA&xxP;-xK z5-<@Ops9d6IuS4un3ignT8%gtbyfFg&;p1^0Uc{#n*$?)DVULKg?=Dk0mg92rV$`V zW~i!BO;E1sjYQZ!0z^k90;bv@KsOLM&&cU?dJ|&;L_$XbJ{&mla7@S3aX1Wb9-^Dy zKinS<i36p>@hs#Bw6Gl;A({H~`FRMZFdT-v!(q(e$Q<wQA3_Ww*-h1CJli;q-#vc! z_2W06fBya#zxs3e{O2}L<KxHQ|I6>b`ug|NG^&a<gL4biUCCkpzAfMG?QMZ2y4jMv z8d!-hL|N#t<rCwjCbPvMbj?w{;7WYyFs(ts$`tjw9KQaji)1Wh0edLv+x4Ek5Bg>5 zZ*YJD8~0(Ce01BG{|T-i4}t}Y4SWM^?&b^Vy_L64->O9*-HPhIes6yScGhDv)X8r+ zs{P`OguUXjf*e5m8+W>we_wxgerxD&TnUYQjfd?F@7@O9GO-a%)qxOJ*Q^5oBi6EH z0Cc1Zrj08)G<FQJ$P`rd@$qpS$2V`@eDmG6MKmqd5^y{oie&foC?aBJGjps7Ej~?i zbzX{ynW>orh-4s#T4I4%N(sa%B>*TzDtiz!J9s@v%zZcv?mo?<na3DKL`8`?rRWZB z<}QSMJRVewyQwZL!2l3quv#4pW@d*&tgb;3i7~1=fQ7(nRB3&yMOr)TZmMFYL_yVw zXcz_}Dy7snK-DFU0N^pk#cXz0RVjk2!Cb8d5h3DLF)}j*0464090cd{6jLxaRWnmS zjxjK^=3J-6Ox+^@5b?r)>|RPa91Z{|Duh(|fmPMrLkRVU+Jn2hyAT)w?(gsa<WIl+ z>JR@1VBD{@*L7~+?b=(;yVc-Xx85fDFMt&)VnmOy(zO9EY!mGMdP&Azu^o2Zz1Z*l zv#8deHNM>LJn)v)(RZS2_p(2GOQxB2H_eBa=yqBz)k|;WV!t=pa+xKFxZ!F0@*Wl^ z{AF_HPWW6x?5r>Ari1b&>Af=on(=?Z6<oao3u?<{Be!53whE}*_1mqHTW9k3RwKWZ zIM7LN?^9~q@LCHkw${6DyC*<%esp`{r?P&x4Rx~xYFQR9-*^+P<Mr!iJvl&ggg{GT zu4w|-@U}~#T#cULw)<Y`K<({I)^EQcZ)57d(A`&{k30C{EeYjCWovUT>|V;naIOX5 zOP}_y=6f}~J~QQ|mI1r|II?=UyZ`jpfAin}<=^}dhx<>|Ig3owl%Af&zWVIvZ@>8Y z7x(w?+<l&&$MbjL^nUp8A#iy2?%l)vJpm(f$(b0Br^D%VT%JTk#HOBe2^?xnI7Ch< z)c!p_K9*9LIK-r?s#;GjW<DMdi2nHa(abm;m{YB95)lr}90(bK0Q@|E1K=^FP@|*n zYMSR<N-@`ZCPxknv!a2Dou9{?XUX5W&Sq|66<?)BnjJw+%KSvg0LUCe2r;Jn`}?== z9uQDO*4i;b#A%+NpC5CcV+^OeV+aqbrm9HDkrDCX?Za>!I3#iW?s?)jd|-g^RT-bq z^yB>PfBU=t>yLl+XMghR|M>RPpD~ANnm>O0csLy2y?b{$-GRFl$>oud<~f%lgfz|b z<KyErO(hosA7VHR10fBEV+gU7az39KX&464*+I=*M32W))uXDy1Aw^*F@t*u9AZSo zQs(NMi#$Y5h%k=N0G3OsN`;8JD){Ik%sdPOB0oMpmLkXF5s7jsRsjiBOjT9QoQPu_ z5XqnbS_n+U)nKcrC}yUjaljM@L~@53^KgJt3L-M2NdD%V?+C;3cy~A)QjBRx$KwGI z1UbYZa5RH7r1SY40=sJ|^K6E67{{}!#1vABa}h)=V&~^+JU`|68Jyq0|MdO)Plhz) zTy&b;#ieLaPecbDKbGJ8<{yR-g6S#6FTVWpKm5g?ef#a#|M%bj{cnH!+oz|GZWcIf zyYR+NZSjLw_GZ&Kdc34tZ8bA^IinlG^GnUziphUXIr&0o7RK3?E&0Y+@P#Ab0-fXs z$}ZS2pI_<{G_9uPdHsI@1pOloV1+H4@1|N)f4tVBUID5>0Dft4yzCxcK7_3!wkmlo zywHr&=1^~-o&JI^q<)8A@RWZqS=L4V<V8<w<^Z%%?d3Oc`)(~usQP^Mn7X5>+2UUd z;AmcxOpJ&DxC*sZAXYdm3>;1M`T6|KH($Sh|Nim$S#@6IluHUcPKB962-V<>F@_Kp zO~+uK^YM7BrM$KA7=xOC_>dAatH_7v=g)rjN2`(Sfde8Q4u^Rj)f5~MEyfh%AU5Sv zR+xsGD@8?0&T|OiFvOVHW@(d?Qd*x|C9ES!jUHDyTd}@EWOqe`5CS5WB5&T@rIhA* z&N(xanU}0Rc7nT4(}ZhgGcnbC<_fn^!`C6iQs!|SW8~UME~Uz4cLg+Nj4?3>RWk(u zVvaE+v6?o|A;uVkndO}891^jJ2WC;7=eZ7~8oDB)Qly?DOtn(_a5&U+F6TVW^WB@n z!~KKGL<IloFMs`C|Chh@kj$&yzk_4BvPc{7Ojm)wVYBazpDj4nmn2-;Wt)h<5!<|3 zf!}SD+kT>YZB@9J$tJsiV#8*rt@U_FEvLG-&tDNEJsa>#{aHt|8*H<+UIO-O{l41l zn;&5v)t1!M>@?ha8CGaz@)raYUZLsqAHFWTHm}*$N6qy0%NbaG;hVLOD=CFH>+nJd zw<PTsgz(bx6@StX9mtD9xV!PjbGLfeP7ZhERn5P-4y39nuMzqFkn0tDo?f;~H@Lf& zv${tBeyLZlkSFzWW3%78O!rG4!9`de_gVMej^K)0^a6L~T7Ku32jUh#dFk52_$_5h zx-K)keftu@;uYoihCz!Rrnfg|N{i~C19&}TFPlZW)nNPdrLk0YdO)Q8l&-8fuk3|I zh?oNw^*8U{|LQOP>Q8_D*O1<13+T>>hZMuZ{kw<zz<eAA!umLl$A>@q`SG)#17Y<Z z0s+T#IEYc8khrSuYKn+O-3-Iwh{z5?1VC88tM{DJiCF+p9kYQsPLnZ*KtU%fGP?(2 zq>zkARI-bJ977bhlCxP&$cpX`%0L|BKtyiJo;W!X0=k;i<mV;x#_;W@WMbfFB4Z3l z1VDjVRn@fi?Rk81<QNC0P&e`2@h%S0Ovm$BN{J~2PV+SLI39-gC&J;7Vq_4Qris)- z3?YT%=?H|g>ijf5jnlVJQ<=vyJ{<!Lfj@ls_?!Rp?|%JPfAh&_UvL^ee4NZ3z&RX{ zBTy*n=ks}d9^(MuR*E4|NQb-OgkiW7VGe;1-P{Zjhjbt!Q9ZtSh%pkeSus~P1H{8{ zbby>Q0HipC5XWh(nHg$YlhipTWCC{rCXDXNW&l1UBci~;7Tr=;*i@9P;UN=Jh|$bN zg;Oxs8bw&53&;)(jzCImh*(5aEX24vpb^~3l@}Ejs)keTWF~gk^Z4|Rj;G_BH+OGh zOy;gCK=AbZ3_&A-xQf`*{4|YIN)gdSikna8$C}tk8bl)^s0fq^Z6<UMhrsFX{%uUh zEc!goIhPoj;~@@3R1SxM{9fnt^fV8_zJB`n-FIKVd;8{eI{t@W|HnW6#V>#R+yC}Y z|M=VIrzb+DMULFie!AWF!j^|kw&QKFV4a&Dh#G_t0@gVFRcqKPx%%MQ{+l=CXpfBe z()EhV_4}R9epwW=jqwT~ro}(%>G_g-^#7j`;EmkureppUh?f^h0uca!ar1**Ooy+S z$uE^f;R436;=iwq*lqS{|L!lasrDIPOFC)$&h=PsXC-xw-*gi9IR5m)Nne-vs^cP5 zJ|{CVr;0-DUSR=i(JwUA5pyvGRju1$3Fk5)Fk*-?IN<Mp|JC38%@--f^LZ?#@H`cr znIGJZIn^@PYK&Ff!cs(}42L8l?p_0@0Kg%t7jv0rB_wcARZ)>rxq>N%m~#g3QYH?} z%qlufV+i4RJODajczAdl<6!2@2<Ms$O(9~XT*4KMdmKk17Lmg+9FKQIB=R`V*-S$S zHOxyyh?Yw!Ma&!#RV}4-I3#yhH9}4?x{Y;CY9zM)=`I8W7>QGtI*!a7INTo}o}V9c znd-{SWvajur_&omD`i$ygha%pm>C3)$K#0^&ySC}<Pd^`nQ5Is5p@?Z!-$iYQZm)L z8pIgmc|4n%ySkfsIHkL{Z{MEJ=W!gX7eF;LM{vJ?c=LyU{V-4E%P)VCjuF7YbX~4j zq`uoWX}+Y@4E77b)N?kjsnL6Eq?cFwb)@&D3Xt#HCRenL`$P%a_WMR?)Y5t@2y3;6 zX_2xERYZ^8bhAG%op3E*cULK}_UDzO5f+lRu99N^Y5l#dvT=P2cp;r|<5j>qc5TDH zXtS%@xETU{rC{|n>Fo;)?~5Tg1VXZAD6I2_D}mfgl(VnM(w=JT`q~3gUf%eMzvDHN zd!uAund%m8qp!1qTkNJk>bk~c?mg~(&l^__t+(}o^a~xOx7+tm+qK$Tk845xmgj%n z?9IL{%GtUm`+ILFXx%U`H%^Bg-GQIImPz4VP3%R=z;zNw4?Ns7*BfJT?_SEXH@iH& z%Yp2G16rQNLK3q>Pk4DCT}ou%|7A)yKVWl3EuA-5>O0gCh~NF}v$vmq_B_eg=da#= z^4Y`bz(_zu5fOly0j%W7)XhxXi&_ZGkqJOV9Xx<h3P@y#<{*+)B?LAHGcZL21Jqh= zY-XyGONlX>0k|Qe6LLs-9Hpo@5@8WVaB~gnF~!Psc03%IDQ8hMN02g;o0)rX4wZWi zOHok^k&(G*$wirok(N9qCPGGrn$-)$$iY-+a|cFZa}zC)9sp2~ok9p9a5$^jb9OTk zcMoRaan94ZxHE-2j*KaeW!8CC^}xYHDvma*sFYI9<N4#$)8q5__~Dz!umAP)Pv0IR zpC3Pd@#UX>{^g&JvyJBh2(<#58Hu@w%=7%=!{hmU{`AvN5P&%mu{y|H%y2l|g&175 z%rg<k6hj&Sz&)#4<lsQ!3IG%n6N#e~5p^b3ubJo&FaSFfyF*QyQ>}Q*itgq*XK^r9 zWe%rP8irKFoT8X{)tvw=3>bnEo0$TMSrJ3T8YmA$3TSF+IC20$Q#B)m=on+Qb!#eN zbob@y6+N6B(9Fg;PxClV&j9!^oPbktP%%+6v-4b_2;~Wp-9gpOOih{VVmAhjp%y!d zWkvLPn&xpbDd;w&;mw-|Mjp@SIcHT3M70b~Wt92x{PA&qe$;9F@bx!u?viOX%cA8$ zJVuTw{qoB{34#CaH@}&u*%7Iw4I%9J{#s<T{lC^mZ+36zm%j=b`gJ8{^QijnT)-7r zy%zC0v=GA0;}6zi#9qI;Hc&5)n@i)oYpp+?UNM6&#!`LU4XDl+Dc3nj>)=-9Z8td` z6xsHhANJ_)xqf5>xL!-v`U__I#(#Tt2;qKa`{bfl-u;q};<tXjcJ}ws-WT1g;1m6! z?iWg7t&F%uAlJ8l5!l&YUWbs^(vy}?a4o0XpL3g=eF5BBm0kC3-7~SPt>_F)NR_Pt zmxaFchZt>zk*_^cH4;H46Z!b@10qc0C?Y8h9GD}`d8!JoNUl-YYHl${;t)bCxuiIx z#1+!n!O4^ZRX_;@a`597ls>Wm03ZNKL_t*HIE~XZO+*x9%B4(Mz>Ncm3K4~nMDp|b zIVP%Qt~I>*)mLAq6p65i<g6)$7~^=JM5Gq)ib#wAVAC|Y<KZw!DKRBNEIF$x0EQ4! zBt%z*YD^;1^Yha@FH7AVMD%bt<~)~DnE7xRh+?HoUf&0rDN{%>Ex7%rwamEMs5Pnk zFeDLe71~v~E2ZXIgNRJybUYnHU~>*33@ODJrx|TwHK0Hta-8RB7>1ORgV#q8QTB{T z73|mDR11JJF9pVg1PE%HhGgLC{`nVQ{LyEhef5WL9hHb)NR@l#m#@gOzC!pSVs;J4 z+{?%7ZSp<&KUe*{lzaQ{yj1wNN|H4+wLaQ9CEoYnzrcyTFlGHpr1Zk-LQlOgx4!?7 z*dy~c^S2Se+^h_2{0Cc9@CuFrdvLv5Z>k@AXUuF*yGc3g``=uNuNU9T#d}|$g%@w+ z0;p-#4lWMM<;UjSytvvx*0;a2H*T)^*Zmj$7q1-(4TJhtn)VOBy!k!5z1FPmZLm#| zTIX|d*jYEs-mA6F5AOcjp6Y!}02gCwTM{iJuF*a>wdPiP+iyFfi)GH%G~+Gpy!CBg z){BkZdetxSW^Oj_f2<3Jw)eh;sxSKE%R}4OwtckU(Z2GNqwfkC(7T|`&1N?b6gFS> zrq13%)7k%2Q$`nEsBM$RCc9w9G@#8|mIp{E3d89x9*$W}o}Mv<xyW2JGE^sZDR~$Y zySZb9j`9Ua*#OksR7;2lwc>7I<O+Z;lHJvTYe|&5G6(bGiwD{3(J2Det6cSUcPb(X zWX0XB$P8erng+KTWIzXiIp=xKQWSyQfB~48nF$fR1|16_5Q3`YJg+cONNWu!I_0?l zcnHDVO|qNmf=pRm^U5Ispok)<A<m+u%=L&DDFFUJ0l((XIfG-7T7MMWA?K2FCUA-j zNMa_cGK#2*$}~;qaXdeMoSz?ECM)SYl|1EN|Mh=TgDi$ff!W<ml?f1hp3dj<^W)<a z0)y9FiKPm<GC`QTO0DxkKrChqjsON`;9@G0ODTwy1_DAAne%LBf!z>LsUl?|VxzjM z#EnScYNlF?i@gzHnHLc=$VIaV05Fr9rCP&PwC*CwdOklR8WJ#*F}VRz@}Oc%Ssy__ z0s^)rs{+s}q#9TAvtl@dgQ!U@>f;n+0^+Q)OoCYvaX@r*1#>e4RgWRMfSEgj7A3D7 z!UTY(re@<fi6{W3kV1?BIZu<B6)E7Z?m5qha6W(g{PDZ#@wtp+IiJr~4&j}-%w?KO z&IOOBbVzhM#CPxCee%isfBxs+)$NQcjq@sPe65DMCD~T}eci$@Zuw2DRX(6rHL_SD zv^BUp7hn~4y~yob#qJRI?py1D(nuegIl4P;_5!@siQt7N`dTsTt)bPlu4RzWi?8ln z@MiaYF9Ot0cKyf*@a9Eu-~6>}?pT%h?ZjGL8m&}%OK{&<q`IRBeOHIp6pM}VZ;9lf zExdfzAA2k0+LmkAQD1Clp>?kcS`yR(Yt(+XqXuavdgDO4XonFQ91OKjvZr+^){fJX z=}l`|Nd0D|2n%Zu7#e;YVa;oG1#&X4IDKmsF;>VzgnDF>yE_sfFU0QVYGRNz4iSl; zAHPM=hljgT#MJU!NNG5vz>MGq3V^C=7MZB#h!GJQ1Hu|{<$BVj;V7kI;3FZMfq)Ii zfeAST<|I-GF{ZdG)EI&@hm=B!?vACXnIJ;Wb4twQB35QmUWjm+D5a<(ficBo3WN@z z!@y=G4atr3TvQ#6rm4gfQcC8^gzj!8rFh`T9P0aZa5Y7Qlwt*41h5JYX~osu)iHRW zFwJ9@aY#u~bIE3!Qmk=o1ef9n%8UTyRz0jrgu@U^u_Ae}5II7nc~>xWa)`{P3gAfW zZbdQ^#8ls+sJa^x24WxrGo7Xp(Ge-70~3iD5#ODTKp@I-xD!27IR1D4`M><n|I`0C zk25a1DRxS;H=)y^(Nvm5@3z%7rd^K~i!VsJR!zF>sg2fa+0nR3@YZbmsD?&iQ~$fB zaG@w$w%ZzvLR;;_twN@Yf?n#c0O(Z^)q<Hzcj?}+N4^pcO-tUfZf*jtFD7gvYfCBb zW*D&(LDsbVRk|%gXXOyX4W;T*aIN#~xUl6_BnIq9L_oN3DlT(Vj~{ls;HztKq*l6O zFV0V!WbcAq3k|7lcK~ftyS{?uqc&r`+wry4<%nRFuhLhsTu+CJ=30?%I-}7SE<w0V zG;Nvx&5-DZysYshp}^f%lK?m5-kvzOZLytYb!{83GxS3b^>*I1h1zn+muF$GI)JU@ zJ=hZT7Un!`aGkG2`@MVnog3QMjK2#54|?E}HC%AR>~F_zo0(=Xw^G~IrY{;K?n~&g z-PkduVcT~vXpn6PH(o^NBfyRXco8pc9d<8k<MC*j-p$3+hqK$#>YME+p}%oeU3SWA z*Hq<}SXO1np<H>9cl~Ma&Q|%30H~&?ySw3d#1J^9bUFdxl#2x>0x_FPF+$G*fC!9) zfe^tKC%TAfp&{7<1XQyi3_+19U#q)S=!&Q|SGHJpAYwu)CL*FzF@)R=5Cb7QfQZcV zgy_WNOD&QyyA%;AMO4KAC{Vx!quBveRaMm7m{?1mC6Cj@3?`-wF$4rubuc)er%EZL z2052CEC6aMQUH8FFjLS1pazn21~+1MDO$3b8ghz<h}CW@nk}0!K{_Nr6wy+0kuuG* zh!!ci%z2(PkL2ZUV6<H3iI7isci%paPD2ba61i)QK)OoK^Z5K^lJD*wz+KHmL~SwM z0|#&y5pzdGF;i1wMg%c6up%<elN&OlsF@d4DGQ(!f+B*d={#p5t_CnO1GuVzx@s|% znlx9l_X7t9n5H>|kmo6v%#7$kRWKeZ1rY!eGO9xnbs+)@<V-~I5SdoMs1T~gi4n;V z)C{}=uu?@w0dNO(cV<RH3Ovvu`H*5l1W~Ck+Dzv>F*7eQ9#VHVb74eqGc%I{%nM4D zJBXU97e&NCOo53I=W(js9CZzemU)^G{rvdV`1C=>+2$<g=h=(fy_(L`><I1=&`UPc zn3z8K<o)k||1ZAy5_l)`n=RwL{PFcSzSxu4$>Ez@eiP~I2JhX_D_U+NPliUQ;rJSC zRd3g9$#e}TwYRN0QM~o!N`N;n<VGHOF_8XvZ5DW=9^4H5)zs<%#@d0>_3r=8>qi;D zH`#|)+}iq&RmIu8T3jOCzUh1Gd~L4J?r6Ctcx-<z3S29Z?LK{d{=8c*zSm#d+1HY| zaEr!l9^78lZvOZVITq<6Vb7PmuvHKAmE_7hCg5t3v}svPTU&CR5dhK5326a0bXbvY zD@Qzgr71_ONi0asY(M}vQ*c7$Qs&3U4|k{I<KsDJtxJ(G)Bvom)I>2xT+>G@J#S?R zMnptn#t?#(;#MVGNNF%rRXGhuL~{pbVjfyL@yej?DY1JcS^$yaj+Kij#6ScNu4?WO zI1myur<A5~Vqzp>W&|`fH&-p-5dmx96p`GJD7dRh%{PV^ql#6cdC^=mwM3*sc2zJc z=7453tGTi;V8FnXLLl@IcpT@-8Bm#i5lM=`8o{nf)HPw-%n&iepz3Bym>5A-ixm|m zLPE}x%~XR8X;2jr19Cz%b6m(6NW}yy)|iCIR^hvlYgRT9C^#ZLynT<zA0N+u`B#7a zzy0msPUoouYiaSEPGQ<uCb2EMTN~s$CbpAzFVvQFqJKLl2pl_uaM%8Yu<xL`Izt^0 zfE;RoqPfrZ<;qPy;6<<Y-Me9HtzW3C^g@w_PMSB%ttO8k^dDX4>FoaA$qm{Z4V_xN z8^|^{-Zjy;>D%01zMYmMy~&$qA}<GABQV%B{N8%M9?OO_?b|?>b{E2wO9q|(CG;Y< zTL#!G@%#RFPv1^WY;qYlC#m=Kx0gli`-QsA<T^1;;n=wke6u_@*X~|B>EFx6>bkss zu=U%w(@n*C>^M~Lk~S-AED=|4y?01;-u375^t?VUZ8yN)LxC$B+4dU+Ctvs~>Y2W8 zZRv8`>=&o!I`c?t@MJF;@M7n7KlE;KZ)^2JUM&n>D+3d*sOc@cyLl^mQs`BGY3R1g z{~fM3cG2<%*Sfd~$hQ)4Ysm@SiN70rw@=zwIv>g!?{(~Xlc~F_d1RV1ZdEAU!R(L@ z??3(QXTSJUj}KD;MwgPonM18zVo{st*_|o_t&-=QW8y#rV1$tKEK;$K>Y$x@+3X@J zY6z@qL>gnLVO1$Y%!njfyapr9n3!3!8aSA{<V;M5bVq=$DpDpbrh){BD54@7C|HOY zQ6#4nE2~0<-zuey)0j2K$V?DI@MKJ6=2A>mI7Cr3ms|=VRsc@bB3jTr15D#+t`!?u zMQY-hlmcc<NQfo{k=#H;MT?aA{^3ovNlVdOWX^e<rZVT8Cn>W_4tk!?9|-iEM<%|1 z`&Nq7D()f$2!|9nq?Dq_oO3}8Z{8eEr@K;0DN>QWLL_EF#0ml;xu}Y{4k<~In!@dF zM&_=}i3n9nHmT$oTs;PWHAk${UWO2vLc{0HIhzTh7s;xMNKB-G&`2trw`7wUozzve zjL#X|weorZgT+ILqOMxhEDXb&yHnsH=K|_T=qe%w5E&2d?rI3+NM@$4x%jfs-HF}Y zv;tEDh|J(r6Ydb)R7#!%&^X4J7TpeXI!`IZ5V_`7n>!P$St(MafJ2C}N*^_oTymb4 z96Bo^*-Qz&<ScpA>8#VJ^PH#WLu5cy0}*2e0#hlH1yt#DI3Dj}OnI8tBeh8z-atAK z0CcU--wW_YtLyvC+lN?J8)=OTHt~A_F0e_wRe2+THRG=xzD<19Bv$Y$#C$#bcajG> z6B^n<(0<boXO+Nxq<M2$UT8$!$=)kJXwaLuzG#e&h|a#3nR}`J(_cSH3Us@=Gif;? zR*1+;9c~Rw-C&Wz{_pO1?%zk>>?<i}{ZZQAwf{mD4IL8IC0WSkGO_)=>!+7w2Ac~6 z`w?u@QguaZHtf}@w*Pm%qq?ri%?fc`OVpO+{tBB>$?DCWxgrj%;OX9S<d)=WGym6r z{r$tc_e=~fH6a%O%urMjlqn2}nW+@T%Cm;JfI>T{TCEKRpmF>dLPX*aIRp~1A_@SA zR5OPgpwxn_AYy9f!POPO49uJ<q!fspnGv0k%#?^?j13y9vI1(cz>JI{GEJEoRm}~| zfCD)=5xdpmYBm#93xOPf2mux-=?0Fyrfyk`$-Mw5EJ)Q0_6ai+V@;r{fLrx^0)SEq zpf8oWrhpIv0gy<kA!PuV=gb7|P#*&TwZ0mlQagBs=FWM}vxLC)$gI-d6r`w`5mVq; ztf(5169+_}=h?sw;B-1^k*~h``paMZ^39vKAHRL9bj{sT>~+V>{j!f4_OYOTk96wX z#X{}1I_QXS{bD7zI*<#?;d=M>Vx-reZM8aJ|AqAzO&Tl;WGnvf$8r;;8Mn`O|Gbb+ z{iiFV%&woWH`@>n+ZnR}gk1U(usK0H`{5S2*YfqNTEQ)$#=8mh#$Z%Q<~!2eeX8`; zSoZP|3~?RE#fg5+Gqn3gt?Ovy@coT1J#kSKu;cZu6@QJDy%j<&!?_mGH=1pyNu!v) zm_x+tlA3KYTPgTeHR;Qz(GR*7lgv8n6xT{)cQgQUpn7mG5Ra%`WWEQgs1RuV7<#n^ z5CzeFqd~5I{mN|5t3Se)0!!qT0UNqMSF3ARxK%xCwzP?BSar$x*qQ}z30d_;DC~fa zd$X2S)Q^_iMQi?l2LVtMroe!zp3Q(&NhL?C;Y|Q`?~@6ux~Z#pqv~3ATOWajD4i~` zbIBpt$}X|ysBUAiE2NS-UIwqQbz%Qf)`5T{GGN7MEeqBGkOQwHvaTnMNyQMH9MQ?$ z5C|w9-n>6P{Ol>?`NMaIkO|!lO%V|fhcrzyE^cB|gbXEwWJ<GuiaGc=jpl;rZca#t z!@(8`MpLz%rR2%X?@kHKRJ{}xF(NY)2PFdL0LV}0XSL$4A%qwQ2T-+nE@oyb^E|6+ z^|t3c&*ND{&Z;pSLI~3wQpML)GqZZUmXZ}jgzoN+fTV_^R<epXVJxaLpTW_c)V+vu zq+D{&BQq9J2jj@%Cb_5@I8w1(G{!K*0g%BFiOM`92Sgapk0H;~G$E5C&AEJhe0+X< zEYrkbkpOMVkN^73@BZoC!#k#UeE+jg{^*Z^5->QRXcm=O$=&biL6s&!4#zj|K5<vc zj~vk4z%)h<5k=;lXBDrk!U*){a35(<tH2<I6CRF75fjO3LgWbUW+7CzB1fbmN<?me zK+GXTHj`3Dwam=SQDiPsPNyStrCfA11A~f_5;zi(8wH}AGa?e98;FaW<zfI7V+!#E zn4X^JBBf|ShLBja0Dz#>#Tml@=DCceh=?Lm3^B$yKR>G$2PJR@R8S>kW_MFjcN}6k zKaWb9OCe<DFplFe49Ehch~hfuSrE*@L}n?urs}veIJuch9>)<0RAxX`&818Z>RP7r zI6aRtesswOqUb`bAf|?<u9J(I!X!TM5cwFwaRyNrLPgv}*}@VE3Rs2qD#U8C(vo4s zn~l25oN9v0u!={rrG>h$ea&OqZF$EfyGqv<7VyJP8n0<_SZlA1@Zv1)0<()`Zg{}D zWejb_IM|P6jnJ(E9DNgg&?=&}J6@?X)H}o8mw1e$tswi?%1mE_^Ale`sR6urTWO!V zY_LW;yIgr(Blvq3shuxmuSqQVY`Q>CFINi(y+jpt;k~%#Y-q~*a&<N^B9L#R=vlT_ z@-A-!X@KC^H3dxt_cfDxeet>wr8#2d9>gt|>6YH+2nOT`o^!zg7op{DZiLnUPv&MS zutW%{B7#;Xy*l?qHR9^b_PgKx^Zmm+Vp_O$)y8p3DODe@h(0}?PbVlvLc9wc92T}A z5lJZ#vWmwrFcYGu6qu=$xs>8=Ip>rjBGvC#>#;&-5g~wy%xOqcL_~=K5i*k*ib!QT zUdch7h*Wi&CRI}fGdC3?GFK5jogN5Lykb0xx;T)kr4&*eEQE2KrYRHEVLAW|!%&UP zYLpTM6)B~tse{%17(yr|1A5Jzsqd+}pBDn;k`cj7bCD1@MslYjr4~WeEU60dKbszg zLuC)HQvrY}9%JxYCQZa<#({<*)uN*iLRA?n^t6LBN9Isry_iwmOU|{htVSh1eEjei zfA;5}efINjzxwWce%xv*cDbyVFmD^wEqLP$>Z%9Z#<*yw-}1EEk2TWkeOYOHbSu1H z(>1-<^804H%u*D9K5M9Lz?=B{`v}<9^7U`7uXS=3Cu^Urw06c@9_BUX^GnjX&3S=V zLbH9pujB1I)^o9T#W}l4SVh$h6uthXEFrJOb?p74VY7kTZ(ahYU5{<-55*NAcZqJj zE`)oZCSFg%&0A^9{<>&#N%ZZEDBQbWUqsn$^P`uCLT7faan1g0=)Dik1#m%u`y;Qm z2zLatt2gP|-frKhL++8o`>Va;9>J@*U^=X|?-@krUb(sZc0aV5F1z|}LjZXJPH*Q* zzWIokD0Vj?v#xZ%aFj1ellA+rERqc-uoaA44P+~0z8J_}hw+>6;C4fFG&R@Pw|QBN z@RI*-!NICA6+++`&*Svr!$%zMkH>*c=Q&$8B0z$9p7NZT19OxjbDojJ^jsl}z|q{8 z;BXphfe-is{PFbk(X9HZE13|R>ok>|i>fn+TEto;SBsZ8iD;wxJD<-gHVmg2be_dc zYyQ+Yj^jAyJXau+5Ms``B5tfIgw69@nSPLvV_=FZE;5N0Hz4Fvj42L>KtyJ4YJ^;* z;8e>~fskW3nCYCyoF{h;ArgfUB5}k8KvV!(i<z3MiDXfo^33K%WtK9I^Z7h!$$=bA zo*q9uefx*;yWi)>M|yZL6CxT8hk4FL4Ja_9DXJ=mP^3IPKf5_GJ)a+QE~pY?5YZyy z4rag<R9(cR6jg~Kx$EQ82USHPCa5}+8>*;-BXdh>cCS`47RgIdwh90^u)A^K0S8qp zx#S`#4VA4!L<2_=t3hLM6Ip;orzx8`BGj~YqTuet3zl0cc~RKR&CR5y!pi~%PK?0w zRNTOzRE9}2&AIAV1<-1uL&aH{B@aUa1QAuSX)54&91<X!Dgd2MM|TsIY0hdH5dir4 z`Rs10xkz@0AsyXa#K7E5ixdEpG69-fDN<Bt$$37XRWcJ|4DN(6sF_GH6DFJIi3tH& z)TU{IArkZI(Zeoj<pta+zdEokxBN{de=mw(ym~k8wfJhk(GF0mv$rq%)9?sx2^PPg zM!$H<O#$A@?q1i6_QUbl$8r@V{E4ogHUbPwaAAkU_=4)ZeRN~qebqsHr(*8)GjHDI zSN!f5h2wA)>)1bd(<Yays`Z5I&zOr*T$UYfDb#>1(Wzsr@53zCWn}ej-W-S{I1+%E zd;Jd<`d?tGeCbYzj)W_EGh*cwU#xF+t9-p=3SWQq&0#nk4u|LG5x^@tan(yg2q8of zDb>`=k(te{hGfmG68xAMaXg)lHHbRTQ?<}mK<0YpS!H{x)@Dkv*7}xGaG@6#k;2Rz zD3`pL%IQ!84`vo)tY$eP4e5Z$)dWSS)9J4E2S5>#iE=K0#EdzYd7c0vgm65bDnK-? zfYOz72oY;p3Q@>;G|z}m0g3T&9Oijmr?(ao+dR)HrIb>2fxmfkx0ZFenwBg8rUpn5 zQ$#{DyT89f2t*67($muu0HicjXpMQ!3od`nj*8LDa-Ky*#j4R8W2*RPA%tm~L<9j# z5qB_mWJ)RB-QC^a-;2nf{p!zu_Yc2&di+4VYRs3^a4)Q`3y2{6!JKlt#or_PUVrn4 z#K(G{UstG)H!Eje8b~KMv6Ui!@6~hMz2u6zkZC`};Mr#rEeI1oWN!P6)4s6qd#{F3 z)GQ}jSr&Tw;@8j7o6W9o2U~h=S9W~WMvvIN31NpHJbOFox~Bg6YI6H(12gUx;lE|k zE(3X`ME2skh#b-nS^_`(^3FTZpMBV+?0Ua4JM(PeguD^9UUyLMXt3?Bwn4D>;l7~U zZ2qa+16cp#of_o({_Lu7`+?l5b@vtlz-|*=WkWP1=Nc#XK9XD=<=*-Gdd2IOg4K2$ z_LFnLDZPg4*E((7Zl>i%?{gYqr-@=^YUHJ@MQP@(M%sHnQC)V9ms_>j*vsryxJ&{H z9H(h|e0)6dkqGB;R9z||&Ba`q_;_S@$<?1rg(#+!m{>$*DGvsBkRn<#q8FK`X(Zxd z7(!rkMX!7lSks`GYwA|D&5X$1ZQ*mmY9~PmX&924<Y@+QW+o&xHM5%Jg-E7uR;m-f zn!x}N0-F^xLk#FtO7)eSiXdVLL_~m=%Y=vs<PKR&2n^t+=5Di>d3sXSIZtLn1ga1N zxn*}C1~kiaDaAsF09Yi?(=<)vG>=0-a}%|kbIBvPP4jqu`gZ*I&HVJi#*Z$g0y7va z;7uW*qPkV|AF33FC1(!7-R60$Vr`n{oM%K297GfY0YC`E6oWVui{u(74<P^(5{MLn zpyp~SqN;_605WqRVkz=`{s@jS4a0B*v{I}VcOzopNEnca2<N%foVWrDhNy^|K~)H= z23X_sgd}Q+WgN%Kj)_=dVv0y{HwCIC;8s)cC8u;?1`{nJ%&LeBVg*pi6A_3gxB@W) zSK3HK(hBsf=58qs9O_dPz(Yu-%tTlu=R7eHdaQZ$W);p&bIz(@W>u~+<2=o!%%<60 z!OhglTwJYksCZ49R8h?iLgXP}2yAW(dWxG_P3Y5=ao6|qr-`73xzMV#nuM|K)Ii+X zd)@#w8fpW;=FGi$G{0gr0zh9C5;sj?;R^0z9<Y+`dJoC5BFOl4f3OpJEl$w&(>oXB za**{EXV-RYC+%Of<ZeQQ{502(GJxG+0cWcJT$hDAA->=Nf&KAw`=WMlr><RV+wFby z2hzV|j<z;$aAx@{{+LVG@Ba36|Lk7*qJ_3hY=oAXe33+Vxln5I01>K#o3-q!je*ct z-E_6&YsP<dyt!j7;;+VYjA_bwn&%;<!(mWUL{ha70%BzkQdOPjnTXt6L;!)-tCU=F z0U#n)JEs&wh!x4OW(d1`DH;OASlzLPfQ01c21>-G<Zr*7m_rCLgrusEkB_zSI^LX1 zF8S_sY6D~@5ovPA%nw5X0A`-1sg#mZayKSF9tI>RQbdZXp3mpXMO>YlYFaJo8mFxb zAf;iNW?~E>nz^dxoNMMb0LB=Y%?xS~xH=0;Da^zSYF2W|S=<YAI37>6*e2&(ikK=h zSMIxNrZV$9XH~5T9U_wREK+g~HP`y??v9z=u*!XRQ<GX36hbgJKnNj@^Hi77Fr+tk zcmMd0|M>aOKYw_5`!E0UPkZXleyP8*0ryq4OX13fl7+iC-o-ZQR_}FA?@POK`SmO8 zHLpm$l_;+(&|4ERTIi=m^O}+NswC}p&|bXs-}twCB7L3D?%rK!aR<5!m!{)u7v1V) z>%Sw~4yea{tq*rZ>U!0Gtq%|0Z1%?N`IdsUmRl@tQ1=@F$(zmoKs$VMDXt*Aem%Y2 zmtSeN*}&I>+EBH&ebf%RR}Y#l#@=rH;iuA?k#xm~xWXo_`pV`|>URq5Y+!5!<W=!% z_S=QOwP`JDgNSf7iq?<oHP9B-YM`!T@ikYXJqz2p*<-P^o~%|L)+5hwmrd4XU+>bm z_P&qHO!#fvUghUsmCg6JY<7(N;I_n^(eD8+fA}?^M|9x4HUI5FOFG^7^&$mb~Mg ze`;HP*KcGQ%M$9YdmB;Bi-?*MSdpTFmG#fTa?YpI$;{oQq6C@QFfj9y{8sHrchDkc z4uIya;zaBYKuzib001BWNkl<Z6=;`;naI6(g<z(|3|4hjC8`}EHxpA_YrmLLRdX&< z3awczHP03R0!IKWr69Vh%3|CG#F`_<m8+qMR3;}kSbD-iL=efBI#P14gbT5<50;V< z5k0I)wqAje!CAG21>9VwX$Bw%bMtAQr)exXlYj*fDWWE7B9rAjK7M<C`nHT8p^Tt~ z)~qHqFDizlh{e?u(2$v{<^TXp=%8j6I3SV~GxHECf{CkIRhd)-+>pXFja6YNg+kzz z5(mmfM8sVID~gJnX$UdKsH&w*h#VmRsH&^kkYZKM>tbRG01K{D)pE_8$!)1_+b$wP zU?L7kB6-c5TWB)PYBFQRDj_3uaN-5X8iCAeD7&odftiA8CLmXJFs^ZJ2=284ywrgI zqWsicVsf=&*@_fI5Gg8ZWDLZC%)H{Ki3*dhdai-1o0T%D%qkg7%~VR3IhzzzaV=Jg ziMoiJ5;&71LRHuRoRDff$-SlrUO?9GK{T2?`G078*Cttx<VwsR5t-F}0n7}*$B;9& zCQ2sm+G^MI|G%t$fmUm_pG8u`rL+>s;Q+YZRT<$Aeej6L$gHXcNPs!l?p$<NWkzI1 zdidk`IrpH{-R@D}?oWXX9t`Gqsqw)pzo)Qw8s|H67YG=i8n}E$v<(wycV*sD0C+Z@ zeu;BkVLrpy$XY-$kNeSF9%>`c+1npkZ}{gOKd}NlT+hKXHWKQm9qafFf8s|XG>Mny zd5qA1l$8*H$9{0UpQF!zzEWRRFqd~8&mxjN6Z<3Lp0DjcJ0B+kkFH<bf8--|3v($u zF3I}~bL4OB|BvITV|$%~@10D+8HtD)qPPk@m?j`V7(p?3&`z~%1w^w*%eKnzfB*Zh zzWN0-UvIaU*JUf!OfYnn5TpOL(L$O5qDX{%LA^&rXr_pqIGce;5JBZ=6<(I*a#`Jt z$V(|NmzP*1QP|{^OruGfQc5o`FWa`o<{2BFsgnpI+-}zh<3n}b3>vX5TA1LR^SZ9# zf~S;TUSEQ_I_DJodiXt&s3ycnc{a{0<dhRQs+P;kYt9^1YcsoCE^P&y)ml4v8${F% z^0KJ-?e>1TEJQ?<*EQ8DaiRE1^h*z&ClMh=sRB?+k@)cC61R&3r=D{T&=(?_Ix{gR zKmzgDbpkNP%!GUkC8tC=r7yqw^1uF{|Mh?UU;g8t{^_6m?stE6EALGE0z10kkIJ(i z-EPBzN7@gManYQ{8)4E3m+L+Bnyz@}xjByK47VOb3Kw~YCEo=Sy{36M2yoYwAEc>M zn(6fUxf<E*%x(l8lv@rHd2-yd@(e|mA53I+N+ImfXrD^2ccYmi)e)HWTG_7tH<`tL zOkEj2W-b$8HToDIj0a%f?^*!tjVK7an9T<hxxah&Ox@n2-5&jpSgGIeyCCP;X|d5e z&w<CoA&vZn4?2?%C2;=*DU$OU9u9u`2R>Z+5AW?^J9@-zHvbzR1n`f8#__)Fsik<} z#})Oco2mWAkJZ$}`TID~PnHBGO_96jHAts?XN;dSGX0|mg1{EajyC3rzthJs;KAMA zZ&2If_dxXiSv<N4`zZVf#Xjc#5ITX~gxEfm1#tQn^xT$>8hA7ZxqB(q9VjTDNqU@# zK?Tf|Qess#tsO0bLA`;F5%(fd=A}3CK+Ys8gyt;_jbfdZ&|FPy=7_EmJjM}7cr-NC zS`iS5S_QI7z}2F2RmD<<IcMP>v7sWm8K^)?nUD-LLb%9T=e$Iy9=>8o;MQ78DXPMp z7@>Ov5Y@lpTeKOANU2v5$$1T^tw<56<_ZQ<^>(|KDrPRVZ13N1Z{J$Ik_(^!2y-Gt zrbHAR)WsOZ#0|+)AjtYA-YT4kAjL(*%oHIWN5GFusZzJZNJO`-1REIun5C2w8HPs@ zFLl&NH3-Y1fZICWO|_c2yEB8k2e?|riFz#DO_sZF+lB~<Q@A=r#LPqth=`PkYP}IL zGY6GPtyNW0CXV-6z|_qJf#W#_t*EJ>2{1MO2zNL1+5&+f042gwC3vdB;jFb1adf(> znu?hPkWj<bBqz0!ol7aT7F7{drU;(R%`j-TbaSnsBDF{@wG@+TCa9G}OslDzs;h#> zpZ0<gA`w$G!Mp8yP@`@-nfg;TZVoHDA=<Tno`oUL4d&72xI?HvL?6<4TXAQKcHC*N z#uy%YP<}TaJX*8!)%)r0=sa30(zBiD*)ggVa`(kK5&82UKSu!UKI!9)yE%oy51zFh z&Tu{{PM+CF6%S128MB0k{blgn#DC8nZqM(aM>E^3zUYY5JS=!VTJ*bjU^;8xfWnat zec6#U!R|ypOpElh^*<d@LCD0})Xkg-dPHQ*)CI~Qs-vR^DjY>KN3h_G>6BFb```cm z%P+rLm*v~<zBN}0XbrW{FfWUWv_z?S1j5^9>$(yx9Z>`3Xoi5m{fIhnXPFX2Uh)#V z4iN!TtqK54$pHu{;6^EBBCNH>EeP9-h{1dqadp{>nX9RpVlzyjsu8P4aTN*F#kKKu zXfMD9`4$n2sDm;uoX8E_jau3`*ntSZ-8?TjY)Y*)0*Q5faYJx%@+Gg#SfvIN7`PJ! z-M>bbHwxyQ7$Lbi5)c6*s8xU<d&~gNjOLOuhgQL!b45h7lsM<;3g+AGmQw1uNi_4s z$<fWDJ?4Vs>t*@PZ~y$S{_2nZ_P_m(i4Y&g1G9TNrFa?)=9y<deS0kX-qhOaKQr0; zxdJm%r*~%_A~c7%aU_CHkk0$j`1Gbs42nCd=iwKR1*>p#vFofnz2eEazdt7&Pa8iT zn8v3Y1MYCCDPOybls<VJdtP?ho?CC~fGRzX#~k#dP!aAWX9x7_dCPA9@)VqQ9r*n* zeSFb5f*SHa&4l`h{^k;SByOHYokP|3blM++l<(xay_a=oZTvwA+<)=$v|8Ts2>9@l zG~6JV8na=4t)7i?PS89u6o+>c&U{x75E7#z@vOgh&h0*$CC<Ekj|u`uU+pfn*J8e- z-5XrZ^GwIwX);UL*H{aTCmy{AsuzB=b;rCOKEJVXy2E>Yrrzue4ghy-^*Oh8CQKOw zCI)C0q7Q(MwN`g^*9dBeU|E)0YwXtmK!oe%#T`^dszxhQU~Umn)zktHrM=hG0icwv zl=5;(%;b)$CRN&28*Nd3BNAdxIh=tO+q8X|xX0L%64hD*ldKvlZ5mr)1a<&W>Q>4P z5tuXcCFc~oZ6I}9ZrZ~m5Jb#rHS@^zyZf@NIb{U??)&e8MueFHtCdnpiAAK85|TMh zW}_kLz{~|iwW?GRxxHVv>t}XZ2%KH38Yrhsh?FmR{e-lX?HV;1A~Mms2?7way9cWX zF{<kJxp@~*{dR+#a|Fq?R&cwl%k8#BO*qmA;a|PKl_+<cYbhHiZWW0rhoH9@QmTl> zx4!>=i@18*sv9m#cDH5CgA665WTs#dC&wYRRx@DYWm$<R<d}&#mPaX@s30xNl2#-p zun0p%mY0{r(FkCK5VDkJ?yag%rrPq6NWztfwsJGmlsKH6c&4{aV;KiFz7I^JT2QxZ zWsW2TA`pSO-L|W$FcK3+OzW;Ho0glF%|%_sP0$6v5C9sIyt;{-0fAXX3Y0hjps4n= z;F(AB#6USE-Hz6$eVFck8OM)AKlRWz{^z(Ou47}srW7;!GFo2psTF!Qo{#s1PHcUj zh-}vB$u4#bkLD>+6Y{xFYfkz&{|d)X?*Z=4Bl@%@hW~dag*qfepQ`zRpK_@_LBGyS zV&im&GXDW{wF9DNv8+27TO(wRi~Go_06gqioB#a-j#MPFyV4P1kK|hb+&F;_ORZ6y z`W%hyOg4#^BBMPOraC#eb((Y6Xb6sp60z+>ZRB8xkeB@JAHMZ}<LkNtfLY}fHC`uL zB8*nmXy^sRoS74g)Md%hQt0j?HE09Zbs@sYGzU^Q(sBU0EEmLdyA?!Q*KEON2ySQy zNQn^ecD(|^<#Gw6&{hgVNDU9y#F(>ct)ii|%bX<u%m_?8qQ_b{W&%VvQ<ZHiIWH+O z(a@xA2`6`}BH*|zYw$Fyctg1$#w@~krIgGHGY87e49p-UPMm^tT14GcQ~<%un0W~? z2D2DeVkAb@(E20h431`|RzwPOjz{U<x}KO>wYsY+#?}^F8jY~laak5JR2MVNnZN$} z7p2^O{bzsjXMg@@zx&(Y_3pt(t9@v=jh>BNDRi#K9x8{&l|OmdO&h%vFQ4iYFx0Jg zrk3L?GR2J}_the<hg1qvHLTT<W;NHjL3dIeJ144U(UDQv8v)W3mY)k?Ctm3LxqP5~ zdT+;D9$~t@G+OaTHo+VI9Qvsa^`qn6=ykb0e4X>VI|-JbTWjv^+qgy3uC@yg&gI01 zPp8EOJ}%)C&iTQzJS_vC9;kyiZp_vyc?fT;dmYb=a6j|DS|SFXp3W3dKbXaRdSzse zS~T*rFkl@y+fRoh;9wPgn3@^8+x_vu7pI`=2WBu9!-QkP@z3$9jD7Y4==;2{J)Fpg z9veK{aDyQ8u4sIJiJ=8@&Uy8W3E-akX)FKXcn)ZYqyF3gIzId2NkaTMLipfm&WCk) zVYe{Y>_@=E+#QLKld9HQ0141i;^3r+XttDcyH&FsFOoN^#a89(luK@Ih>&wYXWPRK z?3F3hT1#ok>qr@g${-LeOOE!}NDW6%Q`{&s2k>AjV&<G!#A+?7T18S?*cgJqx0G$W ziPn_p@<J)Y`}MO~({zY)ro;eX+E6p4)P|)piw^|qIA>ODad>RCx7)3htxBo2AOI&X z<@<=zw{0t>007~&Zkrjnxk*J+S8)|k0V^(BzPy+UWj5ej(XDzy1cF+Nlz@@b>+2HZ z3EjB&_bX@!D`o&Mr9{*hC@^r_0LoU^^%D8?fh>D}e@6u76#OGvtO36fi6|u|%<fjU z3Lp_t$9E%iBu0_Ctc#heh7zPjA^-qul>ju0)Ka!!JG*ULVon)zP9pXFJqTQYkUxL_ zzN`t630v*Ns-lBixRAQ$rPf<Y6xn<;1;A@9BEp;~p=hnQ3gD{Zo+1+w#NZ-T908pu zMW<LRKAP215G^q2F)wCT)n&;d=q6^Oy6Lv5+~oFdQVBefS5Y@H7c_M<Ffezp5Go~i zQ?txyss^lTQdPwe$Xz=!^vRp~fdPjP?cNW3asH%XmyeiQi+h;c0^SiW{VR><)ZBYI zex&&tADB924zA<0&;Hz*<~V+00PNHM2jNp}D%N+#aT7-=AX>f0zen9;KMb@r^aZDM z^Wm&JP1MEl_Bi>zb@y<-=82B-!7&YdxZ{y>Xi`Bv34GX+_xip+;gIa5jE?adiof3V z1r>qZ`IuGSN9A{U?zmiJ!4jtpwkEv;?(W1$1kw4>@PP_QbN_&k22PAf7%ivt_V#_* z%IoW=C1)b2BBq82h&k{us&-i~A{7uWFU!lz%k}yeIpZjqUT<$qi>kP1Rk_}-%aT>q z-D=&4XkAw`uVo7k>R=RneSHxXQ!sM}6RF#_#mH5H^`6!RQc95k4=4^Gte3@a8zAMJ z5b<`sGAC6Ksfe^JD>&40OX-qQCK|m!#=H_y$OXISAS&Fpt&}aLysis?<s~z<-VbJe zd;fg7T$Uv-OLkAUn{HdFMQataz&YngS_6`ZY}*adqYpU}?WlHp-<U1ugv4rAN~8S% zFmo5JrEEkPtu^bqE=vYLQzN8WrIam5vm#f0yWIdV=OyR-`m(4Sh?}UXDf-vneDjb0 z^bcSD;;TRX&9C#im>JW=r#inBhv;{Xc1~}QkE+5kDToK#irqrZfd4brx5t)yEc7VR zIKl}Z?(9rV_3$;>;W~IY&pkG{so+jmnq2s<Tsnx2`v+*h*5Qr!`}edLa!1j~J0~_C zjqPlOV$@Ts;UN`@-FW%&-nOyh)J`%DdsHt^c=h-gx&@{D-F@);M>a~hcg#uWrP3P^ zBhAzoSg+g8_xcEwJ+pnx$p~-DU{8j&w%)L$QyVZGrs?C7_op3mIYF}h?(WTS--oXW zJo^0EZ+MQ%zCYx6(fPoA3J;ut=R96Mjq33i@3O|{i%x1ryU+y=w#vSGd#u=6l;`*N zZX!>Q{=`4H36H<luHKg4eTP&#hHBI}M#_vQ3a+__S@$WQuX=VdkI!0<0#V2D_+IRO z<iI@6b0GjABMydY_lZ<5s@!IVkaB9;ytUTb_4f95Eu~y87a~`cV8n=QH6kv{qUz?s z8$=N=MF3f9b=92Gx-PX!)Zdsnr4$uiH?OsBTZ=ZCY4nI9A!m|WQsO~CFi1U?WhJEB z?W$T|UM}%PRdF|F;(+>^1#J={Glg)JizxF(M7P`K4w1nJfMr=kq-@p9JC1F?TorLM z!Vt4Ca0qfrcgQ)X6y;3>@N&JDQdK3sD<Z0rxK^pAPEL#j#38?9rD!SOm6;m>l#?2n zQmLj^G5TS}+)2a;$yyJWm#r=>bsyc)9GoUC`ED-Nm`Os@$bFR10RVd=ai<+^5Nl?R zJ~d{JNr?zG5J6nYL=_Pcv$=_gREg_uTXFSTin%faQV@@Ij3I$YaiGhZOkGvYt=5tf z)glfRk(Ruq6oMBz6n#SLSe2M{bc6Qlx(02ynFdr_B)Z2N7;yCWrX-zd!h=ov{kDM% zQiB?a*xTD%tZG$3cSbigwc=I*1iYFEwnYvMiOkJh82}l82;CgqeaSg5t0^He00Xc) zBPIku=O(xII3uQ$ReAWzKRfQJp87w$2b^e!h_~y&w;Gu99-yFixj^fo*0b?E%g}wm zbp0X!7Wmy<?sMxteT=#@X_JF7e2gRB>gPUwQUHv*Dm(6#_Lfhb<>sy5>pn4`Bs~s( z#(Z}Ic-Hm#&;UaSF&a3ctt`47fY6a}Uwiw~4C*%T4yf<xUf<OP5l00eD$Lq_Wb1dy zClKAFXXw-fBk7Pz>0=hh)=NKv;1F+gcYc7~8Vn*2bHm;!0Vw)$s+u_v5hc!UNNpoG zMlO!z<Qgiqu2vhHK%;uFT2Z8yDsP{^|MdFBmtTDO`SyLS#T@|Y0x#>js%qk8Symw6 z6am<_EHCZ|z-D#ZZtJ?{g&j;ykTB=WOw1H{V&=3gFQ&dMOU|pAMv2%Q05mr`Wf3jw z3p3@MQvt{hM651SJ?wJM$sE7^!?%~q%9&KbfpbnQ1;9lMA`#-Y)!Xfc1OP?#8u{rj zzW5^NT#DSTo2qc4U;N@1-+%v3M9j;&CT3ceylpo#iJswY+Z^0XBWo;DMKt<PLh0dh zS#stWx!p>zYUhMVNYR3V&O}RI5-nT3mMVY?5xL{KUJ&X1{d<unlt+{hL9|52j));7 z5qE%;mdL~dfSCkn+zq4(yn2v?kdZsQZ@0W&{`T+w?w5b`^`HFtAAk9)PyhJ${|LO` zo(36JPCCAE-LUS=F~igXB2BFabM$*;#2q$z80bd7%*R(7j%SDtOr3t-UCF)BdVB@u z*vSU@ZMT&a($_Z0)6cIh0x)8TaL&fvd!f-B0E}>laYla!x(!}LoQE@weD0N)xdX<S z?SP@gaf)G`aJtV^whjaAVLKZHQd4U65GCrBsJ+)ZtQ;XQfcbcuz>#`$0B}9J<#YVw zQ^kG`ZXY%bTYp}0iHtbO>JFJi==_=euJ-54$K`Z_30O}$Fn~KM4z0yufzPGOdEXrt z^^{hyM{}8<*X*xM<zJYk2PSC4$X@{AQT6Aa6a7NJ+vD#UH88ykdmF-(hQRxj{3BoL zkir?uY|2v~hH*Sb?{V+M9xp|2NIS659Rs<M@4iQ49S7O!|0lG_NYI?n2lE-izBS~) zkx6b!xbLgulpeaz&CMJ$$BfnCCO>(^BQpr6bIz{9qqE{Xs`L5=fV(y2VfdhFK7oUa z=>;iqGSS<1GYfgoRws-$)YyN+fe}$c3dWE~aMyB+nlK?SxhjF%?Y2deYU?$1Ck&C^ z5T1Z&Om#OR=EUa8DV&`a{WA0D%VlCSB_c$KisfzFOg*KXICbLg2Cm+=!ikn8Cnk|< zrlr)JGf@*Y9Q;YDM(#Ot{M<~#XEZYd?GS85K=75ARV5(YQCfr!tW&Kjf?$YVw$07J zAsDqxM5VY?mujliV}2u2aCOV;y2;hdO{!`1BvY*tJ*Ck$h=}IuPC;56>Op~cH&eF& z*+~S1?agzqwbUvJ5W&@=5{rnmEIAOxNKwi3z=XGcDznH?sA>pVU9a!aOBImylo9|i zrj%0L2>^()e>@#kH5bBEN+C>$#K@4cnh*gJcD_{arwm^g+8Q%+CjhUt05}n=YG>Rq zZ}3Z3HB}sOJ^)5R*pyRZ)!LVYs0x5EvO7jZy)28Fid1kza21iVX)UhREm{DKkT{Ae z04Q$cNPtLYEdZm)vp6C$0>vLUa1VHKcgy$A-jnT$cX!`FdnelDs2ofa?C04zN}kx^ z1`77`XB-bk#0MkNOw4qbK=gY%JYRQ+)xq?u4~926Esu|Bg!it{G(nhszmJeaKlS+e zWss)FOuKXNk=ow8KlRM(>4ea=0sGDG9o;+o*6>-TEW+vN8ZB-gj|Y*C7|yXT-qYJY zoXAP?a^H3FgUxcd2zwdrsLvTcHFrV+Ze4a5T<!!27MwT11;yOf5+-mr6C^T4_r|P= zW-l+V=J@S*-+ukgAOGs>umAA7e@ZC@Ei-_Za(jJ!mD*VS1DP45(9xyCOs}tBtn0dM zHMYZ?^W}00!l#@G5mZg2=DdcW5@M8Y)WHxfF`9#FWyUYQd=2E)lCwLi=<BDK_xJbc zc)4D0fq70Tsd_1;Y}eZjRBOPi0C2mN+pVnYg$YN)jJu19nnc)RZlJ;R(9klags!jT zoQP6%9EC_75tkw&8a>sjZD(~uRddhp?{CYRmxaKIkW=DPwozNIMH4S6Eu2!c6_rvV zH+i|d<g^kccOXhl)XFf(HkV~F4g3I^>u6(MmL(+);Pkd_p+-PNMT)7Vlz;ilU;fQs z|Fx?B@>jq5?Qeeb_y5m-hh+hO6h@x^aaxC?hV$`ji<8Zq*s~rRtl7NY+t&Nj(qmZZ zyoC%L;|X9qmvNqs=XA*)?F^L4F77>AB0hk*J~aBL`*S~$*1dV0!rf>O(l|djmtifZ z=Hb@i+=q((=)uk!vybL7ncdT`8X-qVU>?3cuGMk}6LR<mHidm6{p8yGiFpioAAy`J z-p}vPeIzq>myybu^EJ~a8webK#P0UbIQBI1ymf?P{DB(7C*`M+C$;JCc_W^;Aei2} zG3+@b1~6U4asJHsdOS+>{ae^FY$H}YPh?J`?4r~MTs@3iO+B+Pdv)AT<~_=Tp+a{E zVozFw=*P7^Ud)4)aERo^-FI=;-yR@~JyUp`8g>+A%t(79@Lo0#T-%%r!~I$GyS-a5 z8Uhdy+4Dv^4Sfm&+)iWZI*=lW8AZ{`gg}ukBXdf`<mRE^YN3mhm<a491|Dp^M5t<R zvGOo6DuL8ZM6S0hb8^>Ow$A<#m}g@mA{40r7Hn2TVCu_qQE5^&)cqJjH>+l`J7Xv> z+-{{70VFafW>q7y2!TY!ToWRKnS%xmN(dPO#X=}$lUhBfP$Js(#(3h6QM4p9KyVXm zg~Vb;DjZ@sYNA?IRkfO`)J>!kf~(e2q7v;YT5nq3T`IaD0urHTO3BGEJ7hJg3S3pt zoBV}4sG6!MB1BKID-nt)c0Eh8SSRK#A{87MnFv#IB6YW@X9UrRnNy>wL32+jGb14r zvIFGArB(<<79cYX=TcQo%^lQntA!}FHws*}fIH_Xng``7N>wBRuwH5omQbez%;W$_ zY^9i6LP8`n5v#3<y7#J93EmTSKywwTIb|~mkfgbq2k;wO*E$d)sW<`wx|s$B%H7<| zTQpt~4Jo;UiUGiqb4q-@7Sn=m=IXUrxtbK$3f5SQkuxC}Isv#7Bz6-(FckxF@I*PX z5Ev}&1IOeO*sbS?eFtRC`Rkdh4|>>q@)P{{lVOww(_~NI@2R@om-E@L^SKN#PTp<K zUH8`*L)S-|Q@YfVDPiZkW!o*%Tr_?%m&1oA<G&~CX9fhE^oplh;B?wU6YI};{Ja71 z2o&Sqb)xVC>Dir3=zfb%U5KY&W4KyQM}>pVHR^^K#oi$y0F&G8Ls@>P`Arq}b|##% zHBl{%r9f^PJb2S!o;y7_uviB_hMGJ9xC5TQK2H-7)N$xN(%~fmKquxT>ShoSSMRKb z1NRm1q~0e?h?$5mEJzIAkceMiU*F%~Znx{#-~6g^FB_Pdr~sfy71b)m0WL2up~o8~ z*_09!BawT|$RoN7{E52*P%TwWkl=Dz5n08@DBaK<h&T~%Znc(Lg3aQZ^Ad6LXhUip zIK)JByVdcMm;qu$t>dK?nTw`g+^0!I=@@B{Pc*aY~rd5)DOzjxywt05I_yjDaD2 z97=ZpAXU3`gb?w%E>Y`HRnfXYPH7=b=tPV;L#^PZ2*jL_kQj+tvOJ(pK|P{?)GH?< zvM#v;z|5U;PKmQM4zEV}Km^gtlov)?B7jFgCI%1Uet7-#)#uOGHLw4}U;M>?`Op7{ zsuB|I0bYbCwOPhz8g4M<tqwl)!$mvu;?5jY9}@R9o33NcKX?%yykX<Ff%ehP4sePa z=MBmFME1JV9q-&|3TN|qCzy+e57GfUy#yXMrziJk{^e<!6K_zb<b=~k@>JsW;Vn8r z+&cj^4mRUQUj>+uuJ;ppCT)+McQ+U~wB4GKL-85+j(rw3-L8AWq=P+dn*$Q!xJ8Ye z=4nC_N0Q~q>Uv<q=V|(0>GjF!*`Eu+5Rlk+w-1uvKkD#<y3fH|@|{|;$6Bq@q6559 z001BWNkl<Z-dpAOvhbb5(<En4F@Hlw;2r><(FeXS1{}9_oYv=ii(?s20Iu`3=9BNB z1{~e~dsb+k$k5y9%l@3f@ov0kyvcaJM?Gygz9Yk%9IyIL{4oduc)FJPK$jeTH9Cyi z{cQWJ54UgM#D_xI@!9v>1Wt*7-I;Mfn`-EXhtf_9*tj_m4JlZ;!3?ynIk__!hs<y2 z@dVv2rP#rZ2~|a<7&;QF7*Rq@W^Mq$5ujd8Yfj{5wHi3N2c4cVGa!nps30Oy2>&V} zf<<3$m!OacdP9M!ZEC6}Vo}eeK(!*NM#(zl04)fKMT-k2UYRmDAz+IMRidvq%HaTD zs*XWKjP9iBBAQe9K}Lkc7`iwB$qgJ-y+#1+rYf~=n_6W8ZH>?d0B8bMzyv`N9T><M zoj7F&<Ltb+LV3SQ-86A#A|#JWt+&NsYNAqdVizMIcWF-{aciA50fWStQ${rR@Js{% z!5I-u-OY(xVLK&KaVJNnFpSjS_n-=EzL|Aui6{uTyBiV&4BMLK?T`w<oy#zG&`v>u z=#ia|+bANc9A#SvueIjPMA%9?*si3C@f`D#YLPJPYOd}E(U+}+z?hg41c@{#xDo-l zl_HTN&{oyJsNAX<IvBOzxmA@)CS(FqLDeNZ4UT?zB%t64PYIntqqHQEv2x;`(rv+C zV^qfhP8qvHFY}I?U+8!T*+gfuKp?=NE)uwV=MRWfe`JT<k0D~9oqN*_o^qWdbLRk# zdym*`xretmHk3I<IMRq={wHMe2%Hb@)?}!04wXlU>&HJ4XPu(FM}&%dI@RD#_2*|f ze%1hZ_k-t6Xf)DH7|e%X9((IU$Jh6beE(^K{X~CkX9C5E5CR5Sd52yf{Qg5N0d~^A z0Nzj!N26;1Cs5V-i^sdLBbg6g<Ze*H8+};n!JaN~*kj;MvD<cQCt^?uZgy`sp>@~> z?O_y72PX$p0ssu%wH9}QsZmO|+wFRNS5x8uflxEgE~S=e#7>;4%N0b`5s_5gMF^Rh zN2^SHfH|oK0X~2mA~2JxFf)LQSk75B_^1IKP5tfd%1nXAAtYwTF3Y|*DT(H^60zrK z!4)-0DKeIv5`-jDl`=~!6A^%klpy>t!w>-uEe9eZ;#x%5h?|^gOsCe$#G$H~5^*M` z9FQRZA|i*^h)`QbAEA^QrQ@JUjEW8-8CbL%MbsJ<0N_9$zu%zQj~*&f4bi4ZUZj+y ziZ@)4ckSgG2&lNvgP>~&43@3_@|RzK_wBc9&cFH1Z@>8J%j<QUs(%A7>c@9vTGGQ1 zAE=%_2)9P8HC~FDg9@I1af-nnH^vN`_$<uBCQLu227TtHYBjo9{Cyt}o==D9VJt@3 zcJF5FvB#rv>@o1}Mn4+r2k~lnz1mFW1JvtmNGI}Pe^!y+L*G86DNH&)m(!gY&N{>C z_<>eZoRkb2XW?|;=CFLOdyg&r$?7`vc(>3r_Rqm@`Gn_u{JEP5Oso_4#oIlBI~){% zQLjcgJdu%J8B4*Rt=NCTF%ta4(;2H}XJ?+mA?lQh=lglo!5(C!eMY-B!7TXqtlN41 zN7wT8A0#Q6Ugv|YfWuG5C!O~Ybb5LF_-A<YY$fIt(rKIy4_4W!AoC35f0zhjXRib} zx*7L(FCO14Me#IY)4xdFN9xkeU~N%71)v-rN^nLav=&@<Fa_ou5(YVE>QuVHG3oBL z3IgW5gxg>y2-sUs(G8JPL>eNxEDIt<D-$zGm65G>_xJbrP(XA?6-UyP_<DOwye><M z{k_zpT6?k{8*<nTz=;qOapJ^`XaLs4EIdSmu;Xbdr`Y1n3{=I;ODXHRB+j?n797g} zo)U^05l3mBnQ~rgtpH62*e!6vW(MX}twt~(9M+-tqGAY`n9LPg8&`-t1$mOWIXW^g z;7Gs-q*ZS3H#Bl!(F&l<X<hSBVCrqF!d=rlTBJ?Am>>}%o12=ex@a}CT1%}Jk#k!6 z4L21H1hSdeTA7->NGZXj(<GN8WUV4YrjwcT5|YcNssOYkW@Z&bq~QtgO1ubwE?V8N z@3W{X>tzjZr|V66;I{!1QSyKv0;QBA7G!3mDENo=kefR)ySkK0+#FvtcW~7P7>pyj zf{7?f5=7v-ArXSPc`YUYYNAy{N(!Ua(iV=9nj#_s#HMu|s@7Dx+CXQVaW^C<?9hU~ z{MzfhXB$s8WkioKiLTH4(dm`PDZ4kM+K<`%$JS^VE9?<6^xDImJ#Vn`UEcC+aE`m! zU53BUcUaJep3IcU-l0AB9_9zfu><t*#d|O1=RAH|0DK%<V>v!JZFu;^`OABh0=<-b z&WavDcRgou_-)rM!0r+}V9h=a<2;_O>9zYY&AGy93V7f4Jzjv5pXb<U!0533PTzi@ zs4$Il&jdX1&myN3XcP4=(=adb2OgnAa8T{hkAa9LVo`m6f4^O?mvw!=Uc1NvxSOel z6i`YDp-I(WE*C^_Gm#)A=IFE;mttl!hX(F#GQ1He2FGAX>@t&E&>>=87I$Y(AytPI zwP+)xqGga(IzdWH&Wo9svX!EQ#GHm#6vGIn!3fu5b5*U@^aHKdxH<=B8<9+{6iG>$ z6BBz1lB!1LjL7cDjFf6lORW;U%_*gv(|6x}S4vHci4cHlt!BO~IWXARdv8X;IT#vi zt*XNo0}*Q{eu!O1Ro~t|L#x<Pv^mvUa}L^)>Tc`$DXMw#EfG<$Uwrk8Km5}l%;1}E zzWMd9fBn~g{eO*&+w?y680J9)_3=CV<nTQ>cy!KZKIQoNLo0~~V|qVG?@`J@P;@sZ z<0tcY9_av&*9M`5!SSO}35O}y_Q)I`S|}gipZM7PVj`aGq)!j!ZnDRb9&VC7+>l1} zyOR$bK7q~OI`7}3v-D`Nj$A$uYNy!#?vJd`V&veCM(KV(et66mZJ=MAa-bi!*Y1qs zXKvoZ3V*V?_LKA?#=ae#wxpkl|M{b1CYTsZRP#?xX^y$?^n=i}gX$0c-t!5cxi3w2 zzMuKtS$W2iiqlv6yT9Ws#!E!gG=E4v>u}nhd^wNjgJX75Pm<stE>!H4GrI`clxoLQ zR6nH!KS=lNm+RP;9RhYQMR7WIFu8-HI|8lC<#KsdOzNWQFUtj>>Bq*lUTYOmA|~d4 z`u(?v&Iwb>AwURFRn=V0$emJ3%d$>c2q3~wpFUOD;zv=-WoA>mmK$?gmSncM<5sRY z1p#us-mZwaEV&6RsfLhYAj{&kW_sHyQ*vNHLUcqBsenwB5UJLBy<UleSh%VFY@4Ww zR6zt#a91-X;#z}*8NuMa3N_It1#}_?Kq3TiQ;1r!xoWN8p)Q$BZCw|$_nXyPMeF8L zz^X`bsUQMHNGSoU6BwW(87-74lpswVB|yc2K8p-aN=a2xN-D|=chsH{p&KBi#7-Ez zp>(@lqc-3UrGzjN6GhS06Q}F@4Uq}Gl+Daj!dfNH8MilRy4}INriAG=RjFo<Kq)a1 z)}k-3tEo02DUoO!UX~p9->km9eFlKU82}<<(z*g1y>$y?WI#H_nwo(-Bc;?z?y}u( zrIdJ6%*-4J*bVZsx`~Rai!%^00+w3ct@m<wHgEM(H8FA0vTd~p0%m46t+kj6BY{Z( z3(btFi9$vNAyOfTjeZFUh>1DWJ<Qye9B3nf<`gJ^_WIqtWzSLW;G&~L1iM?d4>I6` zY46^AJ)xVzxgTm`OFs0T&=as1-Tmju+}Uv=GabVRd+rFo^|%xL;Jz>d;Q6|zO2EI$ z@e?b+C!}$k3F4eiKHe`pE```6_M8}c6Asx?L!IoKhD2Z|X>Dv$({25@O8#g({U_0X zPY7<>&pGyE3*P=mzWB^UGCd^6P`3|P(Dy>dyf2=R^gH|@2(=%>`w-oo2$;#eaR5T+ z&3E@E1=b6~aks<-oM>%)c@VsWstXgSU9a!&*S9af`to|aMZ|@@DJ!~WRe{)oT2NJp z79z}<RH>AjGdIXhi#DZ}`svf+j-^VivTa*bqdSzBf*o3_)moWT&X>@jiXb^mXDJmh z*t2q!J=f*({(g(d|9X8d<+iS^mK#Cxx~`%BZl+!OZwc|_%Y{>7Q#X}u+n70ma8)Z? zB`R$rWLgskrs(D66#!LC)XcPOLYM~OnW~1B@4Yc-rY|p-sYVfUzEHLr7@<-&_sh%6 z%lF^EnHytJbkucSO1YI%;#AwVrIbo7L;?H;ks9#nk)bT5N)^$jYA_bSr`MNdS<QTX zS^x5X{>#7lo8JXTsPBlE5vks<u83ZK4CTOh5oT+v(;M-@YXY$IMc-p-#@X&2-}?ya zR31Fe<@mNvVVDo$)cv$R;`k;K7GFAstkck@Q}%Y9AG$x2RKb3_;Y078KhLBEA58JU zrGIBej&M!53q<d?mPg8d=bi6_Yic(lfc8FSIwcPJdFV(|eLC(ZvX3qDLeIX~#kWqC zcI@-%x$D6faagnu?_STpG%bRMx$|dIhj&@@AE1r+@bJS@$GyxrD%kTXimy!F`?#;Q z!y=kb+lkiNcgGi>9utSzh|SJ;wkIprj{)$2hK=j(*X<vBzMt<mc5s;@JQ>g9(ZJ4# zNt1Yzeek_Wahi@P0E1}+<IQL$ZfE_(4^w5sN7UZy+wspaVt?orcpEl4SWw&{GOw3Q zUKRubr<4}rPwrMriOg^B1A>$mL@Zm0YLRSGYmNOY=e(|KB-x`6$Ta2=O`%$Ab%)SN z8Vts&>JB-t%aVzp)J;VlNLAdx!8>G$E|(RNqQxm%sB%usq^iu6at`5{(TY`TRnuPS zh+t6F5Y%H^jMsHp7DQ0f=sX(S$f|PNwofl#M#mO_rNpM{u5Ms%9u2(+wN^qvhbn5S zOe~^xd)KmoRWQ*~Om1!!0#WP$Kn$n`+jaBLZ!6@Sa@0{A2#^p#wBel1oQQJHIcIhN zYO2ePW<;C!KTItX5i%1DbzDT|E^S4GsvezIBEeius@Byy+}%|akeCwysu_TqX-b5^ zQB>bH0f1aNpaD@KsI{h)%uS>KcuMJuFFr+Yok$5xAM+)At#Perg$rsG6*Kj!@^T64 zuaIl9l$NO91W<ue0!46jAm-g_1xIMFAhgPasv**vR|l{4h6o(l1p;enjNQeKl^lr` zcMVcT;ufQ{-bge68&#Ze=iJpi@D%2*W*!BkeZQW!v)$%(6Y3Mw)dwAud&{dfBo59o z@JHXA2p4*XSDW?OL>yDVC%kl*AUYF#97zoiV8CZbH+L-=H(75ye|OKK?MR;<0OLT- z^t}2<QTI<ees&V9!EG~uNk1e8b&&lyxjx?g8-A1o9fHB3S48{bdvHmAgjhHovokbt zmi{P(t~o9A&^;Qv)cvMD)^ST5I2_akkDI+m|1L41;;5|l&f7ga3xan5K;XeE7&8i? z`A9dq`|Wmn`~3FxpMJe<n;X!Yx*VKs+x7CYq{K`VJWL`rB~CdLrT_!yoKj*lb1*Y0 zMVNCbTaYOt(dW-^h#Xbi%jI&pTp|e#9s&beDhAPUY@e}%g5$d8bzPSwsmk?wbuea7 zt*V0P%)FItS(mW;0PyM4r^rw;GoqLp0x=~=BgR?_B7gOZuSDwgdPRg~$;|0;S+Cb? zt($v#$(Nkdw%y*|K8L+SBsWlz%ggKA+ZzDpoK@@XcKha=Z#rET0{U&cUM_1qixBG@ z+rWa$k{3W{CNo{vB}AJL@cmtgz`;c%cEm0w!I#VW^73Nl*XvEizWm}V!02ou54x<p zdJY{wy<C=Ut0LucS+rJF`w#!|Km4cv^uNho;hB{uhyQwi{7BBd$>_H>$R7#*Jk~r< zW7tU)VQN)4UGdZ@_md|Q*KLu5&Akct(Tg7%UB)q574An1$1QD4b1u`J6u%#h@JES) z_FIabetCj)-W5XUV+`*ew$zgs7+oZG_uD?lz)JbNc^{(giL&U&Ok}o}A6akrU4VMp zgXc8-DPsRYBRuw_Q&IHc2!F(Ee*EzunR2@59^@Yr3OJ#Prte39Y!6P`+kB=n!kKpN z-jRYsLSS_BoR1G`w$ra35M{+>W>)YHJlq{7c=TcpKXL@14<~YZl<j8j_^G>5``D28 z?>vOb;K}oxk`52v=uqmt8_W@1e?*Rr8}az2?QT)LtQ5*aq5_<Vm?&@8YivvdofIWF z5xre+;LgGPgAiM4v=jwSILs{*F(;AQ<5jA)bQCTHbykFDDKR2dsijsoSCy19QIyRa zq;-&SM4L}=Od@(@ldtbJ=j;w57M)OljiNcOHU1GeTX2f=yIUvcYGlrF#ZYIA-5K}J zb4V!#bMY7n_AW7i_)jdit(MJdaTON{S@zy0@BO6+Qcv5qP3fJ|1rT2@mrGv7F`~Gf zm$<Rvr@1wVTqN;Z;?|9r0nk)UD;WuZs*Of7Gs~F+PE53hLPX*e@!^1@M-?O`rlusB z%2o#+t(4*pk<;JD<Iu_<U9$=i1Mc4Cb~vgmUB(E5HpM*feID9T)(-$oDLIfx$Vwq` zdvK~2xd2CZ1v4|LEnDOPK-7+nZ$oO_S^y%d5}~X`zqtobOYpx^<c52WXMXG4k-$u& zVcxvcZnbg+A|gi*aL-ncg=%I4Kz=-?VDjlceoC;OzCP^F9iQ{zTYI7qTf<i{mUlY_ zryTd5=I?;^{fZ9VNAh`6(?6!1-J`kO9|M=yH>o=-9YDIh_~1Qf=tr>6*}nd~yX=1a z!~l5o9gPz92;7I7-}5`@!y})(-hHXenQ3d--Ht``h7k%clN=of`_5wrVl<#X+P!wL zWyjVZ5*{CDGfs`&<12%&wbgyKN71<V^v;Q&aR!KDT_0p`GnkV%h=5>-Kom9J=J<G! zLjw{rpqop4AQ+pP20$b@p<|)lx7)@kmr}p|{=47)#h<^tTo7|-)yE(ocEdnanR!5V zL#LjQIpt5UuiI8c2*5bex-OSXb|>ac*m_ehmy4P#%Q742oO90UdVPC)t8uw#GwzMV z3nHbI-`_uf_gy7|lycdwTd6r&%Dk+k<|g*}^XCu%M8xa$x@}u2w`EyX9h`!j$C~1U zBbroAIj^e{fogTv2pHDO!koeJcDrrc)lA;rJ|m(T5T(m{k!m?DO*c=Jh;FxABo{@h zLQR>j*Y}jtx?TqId0p31V~2<>2AQ$e;=#pbcDucCN`pY#-Cti{<Ngpeau+uT##(i7 zXs5h{HRI^=G6TdfzIc6myS{#U`TT7ywf^?E|K?AB{U`tT-~BgtZEO^c0qz6$^qwyN z-jAG_193_`&1y!^j3zh6LL6<wv)1`T-d&o0HQarMW(#;S96xp<=)-W?G?AuohUlFq z<ZdDu;E5BG^CX1h$E(j+pnaO*pN!oOeX@k-W4<kL{726S;C%N6D5mFP_a5m}9nib> z>6qSVnT}0Ldt5XsQ9};OAKql2+K>i#xL<dc{=1(D-c4k}lzwD{2Xk3-uMr0`vmI<Z z4sN!=>M^D{CNe#^9U^{uE<=jxM`F2u{PFOLc>Kw;1-}RRhxl-R(WaL59<cc#&OeQ$ z>smLz>hMMQs4Q^I1f6Gx!RNGJWEL#)ll#-&sUamYP2qHNV$<9o%A<5o>z?Sm%H1j+ zX_@aPGD|Z&`t5yMr+IO+?8gV|r0@AYO=PNm{}70vry=%BjaC|Q6=uVTb0FSO57Opk zU4nK|Bp9CsiNjHeD~<q_5E0PKATxUlZ~A8>sFR6|nWAwvrATCl%98ig+a5BFo}iv7 z7|6At#=wvR1Q73`V@$1sV9|ny$rQkX5lYokUQOIVQ|74nxdnAz^ML|4huzbQ%er~M zcZnzp4DKqbt`bDpYEVis(dfqoGwLj<{qduBS1T=<a&`b9OeqmJE=dGP%p=M|KoM!B zyAdv;GpBAcT~*N<MHCSZe$(i_j^`QSx)~7n%13)N?OB+snW|w5P(j3YNG(1ki|BVM zu6mVV(r#KrqVXAsGpjlWdW{$nBNalynhZe`jiGO3W>MqKIjI&zASNPEwOWH*)V<Lb zxVf9Dnc)uZjQmT4ofwUDfCP?iCMpP!5}^YJYxN$Z1`-?FGwoR;A|^!D8o2THN*i=y zu<<rx<82P2L4=+&ns>2hrs7DKIQ<rnpL+zw!biT@(}tsogAng>ljFOyje_Ifcyy~y zhfm!`&tYf>J3P$YLBZ~*N9PBtxH~ZIi=C<QbRW*?#ecrI;N#=xs{kMFydOehIFe4C zzczk#z!Jwx(9)>Er{dU~<PNKKI!kvz&rBpA?;pqKaTv%r$w|%ce8P#?pgFXiJ<EGr z;gD#eVKn1Z?Y$a;E{>64i<q_ZuMfAz3Dj#>1VQL54Av65?m_p=9L}hB#CWGpCuATu zFmN{|NGj#}_8!(LS_cs@rQ92PfQZ82B4Vj!Su!CaF`{p!)S_Q~^+~jrvZ+>LBII>( zH5V}^2EfFbDS?LueWSu-4tuQtq$&XEa=C2V7By|c6gXmct5waNDVbTRg?NeNE;FS> z%d#xXCHD2p<%Jm$Nu|b)yKUu*FJ9eEO?qNGpx1x|rD`qe4pM6^LQIhae|dRT6Vqt0 zK~8*qzcQzkvze)A6)mNtlvE8|nUN_mai?l%Sy)c|#TQ@HT12ZmFsDdAgF6v&UXTnR zGz=PqDXeWuNu<<LLY!&a%CcZ|GN;TbB~vG2;vh*0rcNh<FTeOyZ`*deF3b9tfBA3! z{{Q=b>sBW3Z7x(kG9viwH?uS6`-gp``bH+mk1tCzU(-+M!8yl!AE`$l9X0bwhK9;1 zAbgUPo%W7nB6x0!oxR~Xyl+gqoyzXs@1FXQPd%AuY|^p&Wk1uj^NsI5ej?2ro}Y*x ztKa(xMq+h5^zn&jMmQ{|-EE@tvf*QM<8a)4=Wm#9P^VUy`Fq9&j2}I|?j-cvJMSi^ zM}Hb=kFMh(_td!iyd@2)q$9ff93G#7t7(w<Ou-928s3jRaL*|tz)p=et<ndlpIc0y z4edzsv<I<AK=p&^G(0Bm_b}qEK`?gr#pc$`%MT}7$ARE@cpOUi1G&)P$9r4bIPKsp z9olJ6&fH(d{_CL>^0WfnhcVH*B2JuP10V6>L>@=5J4(*SYWL12eU?E!P2=Q>?7~RR zW)We)OafX7TBUevX@@Gclv|Z8r3IW2JteA5Zh%5dc3sw{nqx+Zk-*K|L8L|?)D>le z_jlZa2ujmdsv9te%C|A+kra-~Uc~2-Vs=+>#wZ*!2lI2{(D3sJV*)rmBIodML<%vc zl)%B<0Mc!{5(82W=|Ld&pwMzh0A@roM%Re>9SLYOA4M@iMMa8A3H~G%Gc`9u1N4?C zX*w3}9#T<mK;UdZbot_C`Ql4UYg%4&&MLK(YT7!#L_|bdv>Ca6N)eR;M7E&G#hbaA zGK|;^2Mg&S3W;GeHzLwFxtXb2N=vLybBQEH6=6<@NR;BmB=i6nw^bD>3A9=T92;I* zBfCC2bQmEh*0^gg%d#x34&N%t=Aa&0OAca?C=rK<QV`HId_jYC@Zj-jwOJ+_h!1Zh z4sMaKc6Xqltp;!cj;3)!P!W^R`;B^-5jP26a6qKQglHZ42q6vv=xW+1up2A310;Y1 zfJ})HBK~dr_|PGH>?u8Opx8}fuk8(tu@6oAXSQqjF{ABkV6bNh?H$#><DfX|Ti$?c zouvNmulNDI#f<QceV_W7M=Q;JKt7-RIMZRe{fBn3pY`}@0q{YteXyl>J-S1_WO{7- z%&9-}Aj=)9fV;;tgf4n7n+;J;=ng1ibO9WM3U{&SelHtLZf;>8MGPE!ZCtGB>mJ>p z+07kgkoKep=SzGHn|_x+YD&f~wAE(eK00$Dv_2fH@wXBp;$^*bjT|)#4s>+D;#CDy zfR@f;3mQHgHHD0Z>H#N00(1w9M`h?i5a}u=q+7A7zxu_mKEK^W+})aW&dI^m#1)vp z-KeJ^++C{HYRm)(k*ljB8RAh;<nvNuBuJc8Woq2fl%N(tq?|9R2EeB72Dz!`Rzv3y zpTYzHriku2EutC%=^im;Y7HCi7~E8*5=|vjr4AfSwVE0tZ`-COd0CkW9F%~GQ(CsN zp+j00#N=+a8GtW2m_HgwJ1W&FCqPIkFL@DEA`iq@qP}?~0$?)%u$+@9f&d~hXR}Ha zMw`PfcZiWTpq3Z_BCtCKL?>#zy#)mb5z*C@45~<#&E1x?#NM_nmt|Q#fB*d-zWwgs z{kwnvU;g+1{D<4OeU069qRz{5_VRH^lFVU4U!;dT<%~nN$t+B~>+OQw$`3S7r(DAQ zDlolt*!%xa7aGRoVRdfW4-N*WRlt0w*Khlo`y8~N5Zd#QV*HG8f6im*@TUV<w@2-c zJFWlW?sZ*EKh%+W(v+Zec%0J1UF6`fMNJ==J{hrosBlaVVh9VLBE6Z3@ji`+)2f&s zM3(~g)8p{L7YdFY9Q4o#?@5XA6`W^;boWHYdY+-z{br&M5V%Kk(VoJG?rjV;i}74w zKgrA)vB&&<@820g=iT8RMf@)~PVXJ`d=MPjs^$;Fw2R^0ug1Hh(+#w~2VsX%_+ibq zW2BsBHI%;aoTp2l9I5f)nap_r#6EzT49{Vj%T!M2U+*~rA71I?6h1a_hj)CcB)jj3 z35UB&_J2%h5ggaDM<Mq}b)A~FP79+yltCIdzrXu}zd!be0#4mzIDo~z@8EgKFRw4_ znmsXRR4ZG#YK2<0)+)NW+x2>Vc|qn3VBnS#s#(bFIyx~8e6na|2WCns)hbe}cTi;r z>kuU(a1VxLk0M+5Z5WZGh@@&FH7a|-kQCKR74!_3%S*^rSl1is0)@iYr~m*U07*na zR6=H^gXA*2ppM@bq}XR6$a|}lOsMXzpkkgv+Q%XZ#*9Q>O7*>8)k@jiK}BMjt5(tK zuGrKXf<xHRkuV{HxyDIb-B|@xh}hB6k~pXQvgDU9czFebN?>jXs;1jkR7FIVb;&6c zbFDQ2lp;t5U?SD@7Vs{20M}>_Mr`5{%u(5PGpkbEl{pbmaHfdV(F7OnE21$aW{koE z6DD2&v6E4YYNKurLQ_>Ws6<4Vh!Oyn650GjO@}*0Iiv%{;}42TK;<0-(Na!o5+&bQ zKSWVX$5BpH)dn^&M^sM96#}*$JkRl&&`>s$W`h__G<?5UdrMxxr6nq?IZ<wkZUk<o zZk&h-$*r{>s5W>P5feEgapFco)cWib0)s;!wynh_gn`~Vzt{6Sed@cpf91nySPPN7 z3)6VF!-sD?u*2Y?s5JPZ#@^S=<}n7|bIHwEjYt)sq4xZt?Rwbib^6%6eb3!b6TLs4 zU4lLan#}cRGsfOlbJ__0wT_<@0ON6^!r49DWBTqB`{cEZ4;(s|cCJ-`>GsW;cR2c9 z@f{!n!YQPL!^#<+)+zjs!zLP)DX50X6URBHWXX<G>K<@ReXoJExVL+#vtuykPB5r* zn?|-zirVHX=1N4D<&qcv>dP;eHA|K2^%h+rZm8~x9$XJSIc~i{uSf6Rpd}GX18^jq zf)_rB55b%eT>bX;{>|6l+}{7Ycr`UuO*t`>L5Kusbc3YCYEF?UQ$?c06j{KOvO8QZ zpWK~OcE?UY51dH0ijJ5A;A9AB?l~<?%eK|vb=<bHUUH_?_9UYqJP7?>0JvOU!^)e7 zih}`otwq%mXQE^Z=71K7(m)(RtyQgV+tnSGd@(m7$|*4?!o*~%`110qDu5oz)Z6W5 zibT9Dm)NZ@FKe{>n#E^$$vH1;N(OF3h)7i{^J1z9#0gbZwIc1Md^12`GfO#{d96iF zL~1;**y+vPjYNbw!ZRRZfWTcx4m%oTH2ATiF(#m52xJC%Svm3F|HD80#sBy}{pweL z^!<15t`-~CV1au2QtwN2bcxLH(J3(7U&=<i)||+Lh9@;t|NQ#zW^r!(IMoKnpT61n z$rOH2g*%#>2D)w&+3|1t$A;0_^Iv@;gU+FcvN(ls2;+nu+cTYJ<cysT6FJWUkASFo z6B?V#ka0fp6dW3L<{fv0!E-yMO*!VF20Wvrrkv((x#lM_L|?|kg?&he;`9CE=x+T% z>Tr&_9buQXJCY2|80@(fe1z8Xh31saK+BJ=t|?24-c*bGz>kmSA&h8jUSq+}bcv^o z$<K1!vj;yTD1Nkr4##PBhqZlJ28XXa461+31gCVv{zST{#vyz4V>q;)U2&Xw9_sxW z=E2M$6uTSe!^qk1{_{w5vZMa)$N6wc+)s1-r*_8-?|wB;;V#$UjiCSu^Rh1Mn%C7S zDfqT+V4gTBDIyS(XvvuYv=mV_bV!Uyq!L*YP?dl(nc1KR0)SeJig8Lq)85^pLzNiK zP^|^X&B1kcv&;HoZl)#5m9>_Jcf@E|Mj|%zZ7c3-uBw$N6Oy~BikTvzYL}t`13;pL zl!GNJhPRas(ZDInfabPsm6!>sO6WGN+xA{cA!PR<cnO49%>t4uTD{S+5+`QTV#Ps2 zZ6{<GfYFNe6kFVW1H_c_dbwO)Uuanzoj9fRijME~tyL5_5dtHcii!|`TXbWoyAl8; za#Mwp^TL?iibzdqanp!nO0`ldG%{z-IVGmsb_>4(0CGy4axjAs0|Qvo0cK_-h7hAt z)n!Rlgrey;9=ZtyavKu>F>&H-CV-CUh{%-GjG4?tM9rdWjRp@EpqW)-Bmxmtt%Q`) zB2thj;EDjwL;{eQQp$j?Uc-%8mTY3%wy8+acL%0Ap60SFp-&<pK_mu9B5GRA1i_Hd z#pB+B3!0j0Y}GB9?m>-)IdKqN1&tX|k0zo*BeuLGXkQd}MLan+{{ka_pBy~dhuPsd zS%!zN{P4bJ`J6ir%Y#iik&k>}haZ}qXTLgC2gm0hinrZ4Do<_xzxwgBl3*R6yuHh= zr8nmNwa<2cYJPV+XcC)l>u`cT_6rUNbWe@nEy}~HeMo<De|WDS#f%6BvE-?sivg5x ztTTt^^HEa@Se;Kvqxfs;qjK}6YaU$@BBqjZ=GT`?UR|o9m95;~-_+u_F6Iu%1X9I4 z1ylqO2?;uEY^3PSL=2b`LR6AH2${f<nN!M${*V9o4`2WBABz-`|DU#ZTaqM6t^@UA z<`I#V)zv*0E(ZfFK>>shD<uE_FCYX+S&`+w;Ud5QJ2TzYl^O14s%Ib6%-q5wGP^n5 zbSbH-%m}}jxx1R`QPp#bXpSOYGuI?JFCqycOHRfNm7J4silwv;()^UtvgBH;dyQ^Y zvuFhw+CoM|c?sZ++G?FOjA>*yRfA2TwZ_Df+3EFDUbJl0oX_XWy1v%p?tVTeYU^=Q z;Zn<KIj5Z6++%{xdizs7Urs5hJKQU?u&CD%$|LVAi`%w2{ONQ~NkA^jLv(jgR+@@h zA?9sctrktWl$v$f%Bql)EX4Bq`kHd&9=X=~`uZA_8=4gGT1)g_xue$Tfq}5dk~zrt zK`G^&maS}GUcNt_mP<N?dT<D=pU)SwT*`L6t|AFeW_~`OKYji6KmFrBee=yXzy0$+ z|JQ%{-S?kAN4lHkt>%dXrM^!Ur2W@#yezjKUYE$bdF7}5=L9K6GVNC97W2X1Ipf1c zXl~{lVCOs#?&#XS-SRW>WP(QQ9s2@};=jG%J)9m=<OAA^uhW1B-q;R+@i@(1u*4(K z-PKm#8UBc4<6i|l<P33hi#rC)H|gU2u;~53M+t<7XS_M-+t)KPy>d&Y^>C$h8a1?- z<*DVas%DhUKVm)`D8PYpm~lMm{#*<`^V^Tc%FrNyS*QKy+Q#+YDk-!!Y~4`+8a?DX zU-~ra{qbNKht&zc7@f?s--GE75wt_~(SI~5u!a{k;Y0%wfZSXp?ffk54;17798Wm+ zw7{(&7H<GYMT}3~+K1ci=pt2Z*(3N)fgU*rZPhc>tC(8Dc^43h^v>vk-(ecNwG4CN zm`?b(Ps6`=MQ(i7AnBQI7Pp?h{RzBnZP;&3oLHvg^s}=G5g^s&<5%CDFJH5s48%l< z#W|Z-cp<M0CkGQ-sikc0mNYqMhqX{gf;lVILOCxHIYdFMs*VcS^C^i)N|j=XH5bVz z&9&Cx*Kn(FKA+D-4!0nEGT?m5wN~@sgicZ1<Zb{!=3Z;vRG~`-%<EdclCx@3$th)m zJ1P-EA_$I94RSA{q^i+x#mNXQOk!}YZUu>1pl+z8gg{QjMu`)PnO6dlCzZ^Am*QTP z2;#&Qs3AV@Zp7_Aa4X+Y)Fgb#`GZI{7{hBVWO99ZDdn1zFo}7wvbwWK%EZLtbz}D| z60*SVHK#;OjLM>-nFyc?c4iV~mCTgQVAX_}97Z)9&0xC<#^cpqRkhZ-ZO+^TlM8&^ zUV&DPT+Q99Hufx-twhF@VD4f}UR#t~nITHdyg55;S#sPgW(Ep8q@)@T$Z|R*O{H#3 zl7v}E1<q1SRTUL3rHV*W0#LU~1QKV65S3D`T1)y@*Oc6?zvQx&DnufZlRDQBgRgD| zr`9CtX2rckn#Y}(lZc{2|A2$43Nb2yo!o6BDhyAmAh8O9GLv}`0<oKIrF<bOU4=$_ zt&?=S(ar1t)o;>ov)veIezzNYHw|vrHJ@Mkuqprp!O4fo@N)M<TDXK^f_AD7+Ts2^ z_rL_D9@v9=2M~lv7)KZB)`<0cGUt<<A~67+_S?CN+xH{!xl=GsXf^9ibq@_Dj(5so ze$w`{vp~;0u44_DT8uEKeRjEm&>8EE-7`r^C+Thyf48UVd;)#7et1E%`q2nw$1?Vq z=!}_K88e6|_e+}Tb0Zss-2>h=IR`n=0c@T^g5K2xw^EAN3a>!09D$<{8vgq7!i<0T z*WcAr+G$%A1`+FWzAUGcJDb%ksb}CDQ({Dq5!bOq3?{<jL{Y8et-zRxX)D{m{_DT| zU;pJlyH~R!svI4`M5@`rUM(fLT%P*;h$hWBZ)+)~cE&%dwf@_`{oB*iW%d|CR^f8F znAy6nfG^7vG2HFTm#aIS&ldonK7CwH8Njx!*Xw${Zp{4g<HsPlic@Um6##QSEoUOE z>-zHYMMQIkh&x=#MM)ghN(kS5c>a)bE|o8rCxE_uf8Eyd;luN{-~Mr3uTM{x%jLuO z-~ZmtHOVQRi0FE~21FWfW-xQ9=ICAy+QaB1d42sp<lwCq=5)C{fov<Qx&SC;t9844 z$U&ezC>&3x6EigHlRRCoRh9CRiGmrT5c#L)Gn{H&Ly||7FPGCGeoQGxGq6bTbGPiV znX{19qRQv<`E)*&TK~g;{LBCMfBw&Jzx|^^bq@d@g)uz-o)y&(xxV{tRPqdCa%j{< zuladP8crVV_&z8&DuNzu`(ofzS<Yku?)TuaBf;kvc6j7-7Hcpwac`>|)ug+09<V33 zZ%SJp4CK+=qT_lEKpcjPZmiJbEeJ(rf`6w(AJ3&Vk5pK3yVQYO)H><BJUZii?;c#w zWO8RCOp~>IJdoQj%niDe@(s;OGb2Wtq18vsTld?f!v4mmb0hKerZ8^L@+WO`h`ujR zJIJ!@QtS)O!>sH(@6M>YnzQ{6E}}<cLyu=Z_}FpqTFn(A_hZ=!gFxfaz0auJH=rN# zB)C27K`XLhQ2lkg&yY{2n_l_-A>qL$HDIq<Q0<T^pX<8sPxpR`{_xH5_v7y92AuCL zRdaD6#vC_K7V`Arlao|)BM5_u-0b!B%gEHJYH&M;2M~J^AR4T4!B7>oFoQ5W<Y8L@ zu&Am;XA?xkNw|{<tJ0977(Jg|0#|~wib;eU%|dtNxc7x3govZmSwyJ9+_I)n%>mf0 zlv27zP6#!%I$k(iaq0!yp?Lu(BH?f;oyZ{}cf%CxvY9z5$g{FnPaGst#t02qxI5fh zX|-7+C?W3Q5EBVVMY2dLR<~_qQ#SPqVI?LjMU<jgEQyGSJC(tRD3VhSDP<9!Dz<`A zrVWP}B5V#8QPoIY=9JcTHFI`hf~Z7gTqnfZUx%(&6r7-;Od0u-kh4N9S7FWhl=IT- z#XP1FAg08OQnpUZ>;x*MFh{9i?Rgh=YY8hiFII?zIiwsh;O2&S5E#DJby*e_fy6BX z3%l3WAjK54TjUOlzUv0cc@*B82}c0z96gN6Bp?zMj>nK2ITpFQk%>rPD2UsZvpdI~ z)fA=X9=Y)vOm2JgWyjENgWX0T*I(DE+HNo98gKKS3hS&uw=X^K|6($^*v$x!))Jn~ z*KV4|Rn3Q${g>@xC&KwdR`{Wp_`q=CW)Z|)2k-89><4Ld4g(dPcj4PveY9TxByquM z`*{Q45$J<hcYhZTlLNEP`^5dYPks9oM`&c<<~AN8Oq?9^S?2j2C;frx!`{O@E=;ES z{+j_ummYBMj}G+Xuoi~53>B?TZpCZufwVDElFUKnTq=P?5{scdrX#mzumV?2Vs6Yy z5W1fpb~BiS9d1?#&dhMHa3W%94rMSli3kaO_xamWw!Eb3uBsu>XNIkAr{%-t@*!va z^5yk(T27}^<TK4|TZ?)9^5x6ratWU2AbaQxjl3+&>2!)=r<77sz}EHE%sxCnozBa8 z-9CT*P9%v+sauEuEz3eA(YO-QcB=a2%V*&1?n%$c!c0qEo__uBy7&Qd;$>N?U;Bd1 zdCAL?<Ls)M(jvU5%FCA*B3hPHkaIjgKMO}nwg$2D<#JiqbzQHeP)aFO1S9c#KA$g_ z%k_F)*DDd0C95ov0zaP?k@WmLbb$GCIfWMyoLD0>?`~UJ3A`*%X0?_|Ow6(@3xF?Q zzMM{HhcUyfeExjBUN_Z{N8UmL!d<s*6J=G7wwzF1N-5g5?Q*$%{`~p3fBxIAzW($N z|M2$?>kChQ^ELV5$m*>f=cda0z2_X!-L}*J{+QF^_GtGmrcZ|G7J&OvM;`glem!rJ zLhWhZwobKy4C%c1Yv`iiZ`16(Im~&mKT_DK3tu%|BAUo^=lPv)_u<GRNz3%+#ZL!n z%smmPAB^yPzvijC2XuF~zI`Axvb&w0n&r_b=2?2UNFUDl)^j#TWe=aO!yo!FtI40b z^~28k0;8ykW}N8m0@~efw-pmqv`hYsU*0=j`$yJz^7{ha`<_PcnRgzS`9KfR`YB2q zx8sIJ<iR5`{cVpxq=&)(80lWL)jh3|?CqyJh>k#*yG+CGUd#^J@KVNe#glsH{D8d! zPVw75+`SJoSs_e$BzA%f*LT1NAQ4ID%d>-9`)RdO%et<wuh#(MnwSs^Gm9f)vWUV| z)KP0K?#8SlWLB9&ZeW*$5fNogiEAbAtW-nu3?QbUJjO0^Yt|JCo4|w$&=I8w)exz? zChD8G<rqT8hj;q3hyz*&vWrMciHIP%_XcCM@AgChF{@|_%^|cjs5Duiz|CWdA+PJ| z5cf)`jN)EkH7KBA1vbh5g2|a&NR?Q@Laan$hIOl%M4XwG$=nQ}T5ac#ZYu;LT@k{| zW*x-?JK*NT6eOh9YP1{UX?R-0ZbnL0gn(LWlYQ#WSQL8)HX+oLq3y?=g&H|$t5-u& zS3m(4VP*xWnz<vX1n-xm00@GbG}yB&D6WH4tldyYsg;SDbpWqX%HH*uT7h1dry3v# ziIBMyI5Pao!QaZ(vJW5wskxh5l%tcIyCbnOf!H{j&tjI{K+fd-lyCrqz+zHLDoV`K zK;vFN8Qfq_#0ruil3*Nc{@%rN%L;L{!w36xYf0{xV7h(f4`Ag)X|!W@GBxhLWr4?G zhx|=1$ijT^hug#AySu|aI4S6cG(nF39y+l?W8xfP+W+3_=${w>&**8FNob{I6IIo5 zg&uue?~{!6eQzeb`HQ?8{xG-0Q+(vL#G1X!=-sf$#_JHUTptL6fq5p@m`6H}+%UQ6 zM&9a8cNaJw^P2?^Odxk<n%su~$K#ld^@;#ht;UnJBqETL)oP_Imvg8cM2CM@ukC0b zqKUM<Y>k=12MXvx$)GG>USGfc_S>hYC$Mf?Eu{oRlb0t^ako;O2(?;Db~>FzWZSma z*Dra=VMeJFV~7Zmt=meVoR^5%B90A>!EM_D22Lq0%MyCRfhh*plsnGnlZa^Al>;OE zTb3*;tzFh(2If|`oO6D8eW`U-RlsVsU^raYHOjdOg(<|A%-wU&k(iAM<$zsTM3jhB zln5-r&_+3@*efWSFXwZuo4bg{oNH8w5j6q&m<=;0fmc&?0)jYNH2{L@&cYTF^8uE} zlJ@fQvTa+fYtAVp8T|Xf4-q~@Ef7(6gM*btbY0gjjVPC=i>m(q4}bW@FMsu`U;p}i zxzw`tIlg~Qf;7&%*ElPI&9CIm`+oOU;_%z!?o8d|JRbHK_{?wAv1MhTX%9OgF<Xi0 z@Hd0)yUVm&{DX$I)6Uhw6Vf(PLujN=k&}t4%Uwz3*e9_&-*-tNp5v%{t>AuXZ(2*f zKkQHp0c^xhz#&OB>Yv{NS#KGVAH+6eu+!Zi?Z7uva2MwQkK)FMSiopLzc0f^M=EE? z`2Jo`T1L|X-)_po^=HsGJdl4FV_~94X!p;%?Qrm1l<PZZCf_cRk1zEmtcnVw>9BX9 zTKg${>pFER?MoX7OkMvBG@%kR58V9~?W16xX~X*A9~8HbD+S&f>CTik-eWY%Xc`=8 z)@n5Ny1{X*PRBA}Bi@N*x(&E@^5(w>7QnP?ygj~F8kwTU&{9mhKiYlVuU<RNKDiYP z2!WV1>2f}Q5XpczP_3?IyRO$@U5<oj;Nx9cN<~yyLB=dh%4F_PAr&dx#!SLG1ca%P zL6Rm0v26(8xU05CpC=0|3x}9Wz~v&+rAnDOkyOBe5Z9>z%{OjdLed<eDYL4kEMn#k z=k5%sYNvzNpezQ&-GlEl62g7nqCyP}2z+=8y?PKSMemrytC!;SYH)&c(5%$8mQ74i z&CS@I!7wLxGLSKmh$fOGl37ygbOnPLzKi`b$+lHt5HZ}yT|~X>;r1|<qmRj>jNhRu z?!>LTjk}@`M-TH*R1Ss3NL{YmR;!06Fuaj)DMJH<$%BX+O^UZ+7CE1TO)B)Efks{( zS@dAW=?-3q3@Njyl39saV5aax+?`nnWVJ&DOzs?Mh5#&xNjQqvOjXNPx~m-J0WJbS zTF~$AMk)djoZ$>NLV<Zt!AJiBm^IXmK*gPU-(Q6rlQSVD1t?n1th%r;Ypa!P_(SA) z89>C^EUBBj%0Xc@LYq+*1Uy39=Ukc`KAC>`2r}CVjI2X!_Xgq6ZQ6gyZ^yAWI*vXW zaO?*B!LHcHf;Vl~Jg~b<ok9N@-#jeYQ#V|bJbpZmpT7M}8DJdz<9pP<Z_RZ%RM{PZ z!@b07ca8bx5$U~lec5~9h)ipIdsdHSoO_hW<AdIf6KbEBOa2}{ptrI55fpiI$5sFU z7p5i**P9`me;p%tSoNf-uvD|XcCE#PW&s$&gO7@Yu$O(#Z-B&cqv55O!C>&|iz+~W z_`@H+`uO#_*+%tzKC{TW7UHm3TlDKhH*ApaFU#`u;VE*DIcF7h#}GeQ^1{q1DZn8Y z6s0Bzo@#9`s%pAi6d+agmVD+~3o}IwTuU?;@uyE;Z`&%te~%h6NFrQH3G8s>rNg%f zP&4qzh}a!)ueDZ(F}FxEVCf*Zipn2%-?k#6r4(`mW;)h>Lg*tvB-+v#;99Y5<#Jwz zaqob4BDP=^2ZdBpVir|qVK*PT7s4D!YCzNxi#E)dc#hQrHF$lw=De5{^Bw4ov*(<^ zlpHTFFTefGZ~y&o{_LA?e(}41`DfZis&5`fX1dk3eGAFE4^iUf3LE|Cec$($>18>* zqz8j|e8KKsop@8{GNk+KnFsP#BtP$k{oOxG_8m4suj`oY4)-PJO`5R>cD!S^4^8|I z>pp^79~}{B&LMY{pC4MS`Rw;G`O$XWZ}%$}@4Xp3v*LHF_~sDigLoIixa}F)Bipy1 zt~=X4{pii8-bZCTJ<sFe9HsT#<raMkxkp&_W>dgV3y2>;OndY@&CkQM^CO_SKdEmY z_90Kn43G^<ZP}OUosnY?z<yw4?Zs++!WbG?!>*1Y+%)Zv9=5k>KIlP{*j=38xqKVg zH!gh$MsV-w9*D_!Hl`Pi$NbE_@pA?KJpYfTWslMi&+|=Z?*kh(GCW5QbppRAw0_d% z=|j$^SEtPiF#&EA%OXbdGb+47sa1r}mvhif3G1?)`WnP3X%lD-K4Mh>?zXPiQdVXv zWytfA2-j-DDblvw>HW;iszDGT6O+JE>jtuvvWS{j0E;exfS0mDqMVzUCFc_nnQdl9 zWFzqqD`{VCxs=K*De>?gBf5?ttyWvNjm!y=h$azcNkk6RvTe1zc)eOR_}0uK+^yKQ z!8XEKMI`$09n~Gx<9QJh(JZ>;(<SAFoAhHUFJ=951r^O;W-G-ElEoeHN{-W_peP|` zGhf$DgxwqH>h6Fs>$+Wud}-xuoKmi}Ze>-`DEn$&N0h(=ZnagHhK#dBbr{@;l?m>! zfgqTfh%WgQ)TnV2g9QzZVt~wynbVTUm4pGe8h3#zY5*40B!+A_Kg^U;PU#%F(^3Cy zZUj=%@LO8@BQt<%wIle<Ow~+8RFheg@Yt+oRdT4PkZfjTeT{>Aln*rbEb!k#AYp~O zTZI`%1q72Kd6$@G(a=D0N909R)yN3$q;N8e_S9$x@XlGVi#kx`lv@+*Bg@PW6mTa? za$w_oY}uGGxO0z|VRqhrc$)=o=7P0*NctYHf4h{gt6e+-Ku4yUCnD0jvyE0V=Gm6- z5#P_f{qzj*=zkci>4@FmR>Y!*j@Q`c9;d;N+QQ)JA)4e>TJ_!3D>c}sc(k!iE(;FW z|7~U;lb`}XVsx|J!4(e%d5;Y3-vNj@l*(9CMU<%`7`660-CnL*s!A48LZRMa&{sbI z26&|PqJ+cXL53ALS@gZQLzO@#tbxM?_hHxNb9D&kKm6g_uRr}VKFc|CV6N_NRZ;@5 zuBESk9^XkR0hLH{N+PM&EdoL!I-M@6tSZbZEZbI9m2>F+u^X8|qTQK=$OAu)ORBXp zyJ{wA;He_|{QUg#B7q=Ub(Ub)pn#U6oI9mN)LL$qMI*dlmL;OcZQH6<7DDxuLYc5d z!Y?l`%(Ubj?JI8Rz^9u=uSkiT;*L_Hpo>#l8bdF{jmA;|pqdHu`IL*3GBc?=mZf$0 zsA}TmVrDRJ&q=Igu_oo5b6z4Ujudgsd_>48rIa;i0g1WAI}&T5s<N=TnH!5#v)}yL zZ~u?q{Mo<!^FQMlPRy@icvmyF_ZISoo4s}_AiH}t#vbo?VBQx99sKy)WXqled;fag z@A;ftC_50=l@KDB7rv<-?b9Z=3CY6&-wD+w3p0-eGri<IkVEg~Th?-R(*t5>Ml=A^ z4a@QIAaD0|^OR+J{GGA%OE<H=FQvzI;ZV`^BcjAuDbYL9ZwE4}V0xPFjWS@G6YR%< zbb_;4sCitw?CuC|-HY~Y@cx?o%<J;|9LOUKJACb7Mt$^1--d9<@5mdz7d1}Qw(|1P z1@Wnl;74uqi##|~?vn8A^WAK;A$u>tJ8r|=4}3RF7GZ6>AM6e0cNX0g?4R9CKB8k) zh-4CJ8&BXvxc~Ndw=EL4*D*bE$6GwU^}Z`8#L6kBbS6m*7GWo^ZX%q|=UR$c%{fQT z*4+a7G_z8+NR*k?QHvB|uv@Ke%W@9I-BL?yuZWZZ@&EuJ07*naRCNHxbc!qO>NsrH zf;tg}J2O-@N}p27MDqG_1)!Qh><;&GI-O!&>+-^My<VG4tCh%IZ`&5ZNjy05OEd20 z%G<W7Ch{6mN|9hNkHs1Q%&QVbGf^qk9Vv(KQo93QYu&c?g1Hd|LQNv7oCNUdaWEBy zc&LQ1h~zV;tU0r4H0*Bcy1rI;a&j+KgyEi&!rk1MkVMQ4#3|*RQzQTYq@*HhaouK7 zgGR*LwnZ&lfDvvL5(HN?dZ#1Q1V}UmY!R~>^KZ38)31YS-3GmAYceLU)mqr>j^6d% zip(`Li;)RSpeMlr9yhMVtV~1=E9sh59-qFxUYR-PwB(GeB2t@TmPNKhHEx852c;US z(N4%gZ4N-CrG4BS4w$o26RdJ`7{ghp)(vKns*U+EbC?CAP?W)$TQmcMNK~s?Ej21X z&8pMV2PG-zuReWxe*PF5tZrYdywvJMw60r-b}*AFkNV@cw|DIDJNq%Q_L$;ufOm>b zesCK&KX*%eSX16A(LE@4ym8n^A2AQ9_Pc}PmJe*I+vPuTfIqzbWF6p}=yxEePE5Cb zN{6izMe;EZ4n8=<hmp^vbQ85&AftN?)nI9hkHSIJc7$NA!2$Xnt$g#}LW3pp!9eEL z$A=U2mSfRbrs2X_M41(C!h1g+IK<^?+sfr~5m6!moGCo>$n>_$3fn<WtSn9GRNToN zjjF-Toj~q@gu0$cq(}ov6_J$mkH7zp{!&y@@D-c8NK$4NN?D2M`|r258g~ABW>!Ur z1BGI(YARbWX-QBf=e$@YfO1|y<W@^5s<N$>NtwCS0yN;Q)^feBrEHhWsn*w=PbwLp zT76rKN^)2!uiLgQ%K|LXxDu<QnVn820*6+*rWV+YFI=y$MELme`Q;_5bgY!nf{%t7 ztlKq22m#)<%B;*{2KSn?s%qJ+lp19@1U{e7rEYLq@<}yC0K1hES$!~@ySt^7qT@t0 zHLD(Cf^Zg6=9F|@*HVi2P&TEM(vnjGa9yuGv(2^Ei1V4TZm;WFB5gjpzRe8eAb0ZT zk6-=%_kaAwFMsvhKmUvW{<nYU00SbuXo9-j5qyeK4}Rn=H^Q#rHqgF_AMSy0+<05( z6wM(w(m5E8A=xOoae~sG`|Yt-L?drr&n!MP2cKgggQuOxyAL$dsV0PRydGu}>^9-} zUbiwx9DdsxZfH<0w@x7=zKwxLOV2*c;S<m5rqfMn*}0gXMwlB-;(?A$_w@FrbPe`y zgzs(&9gN<6R4^VGpV}bj9p|`l;2`^CAD=G5;52TNy*K@aV&U8&8OwHXlgOL%v)?Jc zQ;e7oHLoTSNDOyiR(l%tHC+N1{c#$X{ga~NiJYwc=avq-ml_<rpnYp_c_h7w$ftD; z9X0UjHJ^`k$Dkg~dsA{?Zax~A7xR6s_<TXwciExp{c?{383f(?8D|Rg`@_;*$;x;J z21PRgp#Tp-@V*5&m2~fyeJF}PT+>9p9j|7ePEe3#-VKJQe_Ns1o>yj;qlIYOFr@SO zZz=2OP3Vf5<7R8hnv|F|<pkR5%EImzwPo&JYjL=$h8jXN#hBGdnMU9=YNR7~7ZtOm zlv<nv`DK_@Kx+v$<{q#yF-uC~AVRE7t{TUWYF`7ngHhdKM68Wv!{#<)hr`UgMxYx} z+^D9GDsfd|VIg+FtcWmR4iY5^(ZSFz>Uor;ifW@J#LR15Yu%zLiCI{4$9zB`i40cF z!pRF+<Os=`owbV_Hr=T+Y09TdH6xehl<St{qIHEsA(1n1x27iq_fm?gN1bgc#oaUo z8}pE4@?e}2VO6Qs2VItkoR%aaZm6}YW+EXN92Rb!SukiaQwU5jE8xu9pMt1-jzq3R z!H}c2J180zaB(ksnn8OJO6#K@)oQ);-AdgCF|ApJSBj$g2oZ%GZdP0OwPPsyMn*wI zM`<QOKwh?uNmPQlCZgYJW!HkHs4FC~Qef5H$)hNm;bfhAJh;KMEsdc~5|2TsRV5J_ zO~19)lr=h(pTGL}t6%^6yqr>6tU9nV6@Y88>vdhX_2uQ|+wcDP-M4>O*H>-%kf28E zuPxt;IL@#9VSzqcw*G$^0Nt&1I-u2WZS!Ggfs76T9vipr&Edqt*ig7mN_6A{JDl{^ zgW9DK@6Q+0H65pC)c-fN8~t1)SchBERWy$Z%l&IVfRgOWpU1~$T7f4V;(wJRyRjZl zB~tS!CX^jhN7Ii!{7qisW_9jAa9=!$qwR%nTx}WNIWyH-h|eKCJ{1<WQBW^&v1+7^ zT_LKs!wiWqbJ_<)?(pbw4bUz!ydb2MUteES($o2LT9%Zvh!Cj(1PY~uZ@&J-ETx*P zo0++rs^%o8Q;K>jB2i82x<$qHx^CC&7ZH8BeEh{Peg&dh3K3r}Pv3m=>E+A1Z6zi7 z@bsjr)d~@%l+R~&x9`9IKG0$)Y09ed^70xet*U<b@FXIyudg4UKd$RmYUxB-U$(WX zrqd}iQz;uUpU>y(^?JQt0Z&O@UtXDI+t#FMSx(Vg`|;y*LzLZW@gRXtDY|Wo!_Mbt z=2Y25*x}o{K7F{nUaw_a-H<e&&*$s<I*O1}N)EcNYoHUN40x$q&L>S8aJ$1wxd!E! zRU=T+lu`nWnXDFJVJ55fx?V4ra~OTqP>tGNUtgnRxmK&y&*#&3-+h;JK3^6VA<*S= z`R9N7=imJM-~95IzdAo%zW@Ar(O3n?(>h9jd3vGVPNeL6&FwBzi1N<f;~4jbb$?Ud zKj|Ej>8;&=*y#JtMU3;^W?8|25o7M@-FIu{{}XlWO}%s&ig&0D#--l#_a4HY+poX* z^C3X(O}$OZ7{vC#EB`Uu58lTI-@doQ?@z_y=zEZMcg$J9=?6z~m>=44hep3Y{E{QO zu`gc46rB7&_M|`K#vKrG>W<((58M@!ALb8dFo=6QE6_j$o})Owk?6qC)xe~GHZuH= zFY~>W?C4I~qwe8l`R)PSl?#GEunsiH^p$}Pjnb;2ki66IQp+BA8wia$1tQW3BDwhw zGj7rR!|e#q*rpM+)Hl<tqV(3Qdhk+a{K)r4=r$#tB!&hGHc1?Fha?Ve;ymv{r}HTY zDJs>?{JLGYx`9w@wQ3P#Zsq#)^g)z~$qk64pc&JMUM!{D{RD+mXI~0PJsgylRET{d z#9fxmOkjpZlO+*TlSKqO%&HTqyNQU(iG`!s3ZMv~Ypw34%AkmgNJLXt9uCC`gin%` z8HQRdxIbA~ff~V`RioZnVG-4f2*Y8G6HC<Ht$oYf+^di*!b~t0C1Ym_7VQ9BNraQI zGYk}+uuhsZpDv<Fl5VwtT{5v^S(L06a}p?Xq!^_&y0Hfxm#aomu~$?BeA}vU3a$@T zHK$T4bIaBS*qu^RX*4b(n$ki<W&jBhL@1@RSpgY^*XO>Rl4ufAYnmP0Y05x><FLA$ zN;WeHhkqD%wznA*5j3e=i^C%@?uBWib<ahT2-jL25Kd+uI8jJG#-T<Fp2LY<B}cXM zsLfGLfRiMS!eapwRSR0apmZi-*{T^;CIie-Tla5Z6V9^~P}CwafsE2AgLvCYtu@3o z2E{<gVLCwYYW2FJlyXgL(tLg0SnTQPbU8m&l;v{HXFNUIS6~0?^XG5>@gM(wefeXL zEQSf~=rDRe=8dK8c{1R}vhgT`+D%Z)dmZiYJ$OA?upLYv1f`8k5!7wk;|%Lul{V1Q z(VaV&ZBMZtPnh`rQ7^h~E4<#GrC;=(G(Fnk;4OP!Px4ROep&#$Yd{4I5YMFcHP~nu z_v^-e5E!;rpV=2|(pVz^?TnM&T>)o|)o7Me3U6-^y$mgZE>1<GE_$jq1cQV~o0KBQ zvlYl<s~jd0CT-X=c&~a2^&@Uw!hll)+k}I#6oE8Li$epN#h%du5lD%-m`M`NTIv=9 zVImH-LnegsIvERC2_B6EV-)0W>vla|&Si_%KP3XQRa+aT6~4TvRYzc)Bya``k+<e! z6u0fPEZg<^`SbsGzFa<B^17ARwJ!O|K}j+}YC&1cvYY{5edWvY^mJL4w62CugC0$_ z(H^XtYR$1?fBfp%ybyV)$+;J^vX!e@b&zAboKK~iY6uCR@>eJKdcD4?3JaNC*VXf~ zobq`qaL4(aFXtz#U%q@<YprHA;ucl@_|=EtM=WJ6^;I>ySAd=_&qP?aYc-rtr}OD! zt@V1niqO-C)Af2)4W0wiB+Dtkyj;(hg^6p8GNIJjB3zh6J=%&yX*r$Fr;8{VE!S%m zfq5n4WjPZG$V#cpBKaiMuB8;_Q_d$5t+j01Rtj=rK$$sdN-AGoUUE(%2_Zqr_WXP@ zvu!IPDW`?NIiCr_tjlr^l4`U1{QN<clV*{W6_#BVf%-50-8cW|fB1|4@ppemk{mMH z(1_6FzUB<%ZoEe1&`n-rXQ|!4l<Ctwfr<SfAP$Mn-33P+7PAJ@pii6_1o!}sPI<N# zyGYN{#lls)J&oK0h=^tM!OksqW8oQ&GEc@TY`OI1le)-W>pBa<R5Vs?nI>T}+#OwJ zb_&skIlyaa+p*07xe?FHPcZ7w?KeFug?YNHbuWY91Smm>JHdVjT>Ba`ZtnPz`c(I9 zDh=hN28t6?6GYvifrI$a+`Bjet%2zdDdVYK978vC_Wnx%gY9A<KxEz9_4Hah2PzSm zwf{IvG4;c?=Bqx#BcHsN+D=owN8K|KkxvNdyw{*{3P@E#Xd~8zAHRy;Z3paOq5*r~ z*SUF?Zct*LKOE@QTrhQW(y5keUu_?UTXCp6&7r%*e!LTyh&}nOi^t8_caGD!VPSf@ z+6ZRLFz@cfQGg(machr$PiOV+qX)A(R7S!|%;u&)07o<RXh7X2&>kjFkT>_?>~q}D zgZ}#Le09XbX7Z6Z9Ry)IEsHrywavZs)(%l!ubb5xaY8B8th&R^&7#^<%}hnjQEO%5 zswE1Gf=ijeL@7!oLpVpc<%XlOo7v4q=bHDr4~kaW&b<wX<&>fxN?JX$)oOteH<I4o z<s0?D;owPEEo!6{AOKcslw_-BZhe-{+$cVYSw!Q>i}F@NFrI3QzC0+nj2M7`lvqTf zD4JQksmppLC6Q2YlEzD~%+6pYO|mSSk_Z>KTB<l%ErATE3JCzz1C~qV4vmWXpnSF- zs!8-GlPF2jC~Q`hUjE%uvS#KErbyH`Lcow{&N(wjca=AdPOGY^5hEkCEl89*r829s zo3m(C9|n`zAW0Dsmgeh5xjT<L3aZu+1%?7a2aP6h)o~n$b8m0%>k&tAPVB-ilENjS zMhzeUl4?9NZdC;2#spOkXik_2Fe^kRjR6bsymgf?74dl6c~oYDa!w$Q8u8$89qeu_ z!OKM=0QmK~y}rDXgGpY#TvL{hpFTc6eN~F(d`c;6N+~~m^(ntzx8JSbyVXg3a8yVg zx<0#AZ_C_FGcg<CVcCTClGTGL9^l=*5grIK?`tm4jVCiTCLfQ`4BkWv!$f<9T6||` zvAJyx;~l`gF`Ne}$HR7GhkMn`PgzWVVEgF-@Z9l?-OZxm-^>g4+^;p}ai6t*6Z;ai z^Vv)@ep4OLaFpqRYu~)>Hy=5!!|J$aq`R$d1h0FtV9$)v?cD_v5X&m>{v{t04t<0) zC}sQgx8=)`mL<9Ib*zj-TyzlJJF^I@cTV?lqyQ1m&B8^yg%Xi-xPwu-#1?$Wt(hbW zU#P(rj3{R&kX8HcyYJ5DGswUF?%TYas~CX;I#tbOD|yLo)@g%1_@bEQbUH1|!YqJo zTUnMYLZY%POH@*=>ot0DnVC6nTZKb3sj^x5!yo_f@#9yuRygM@DK$8-T1m_~XXYA& z*lHw#lvGqsr^Sp?N|D;li`KerD}psDR*N9jh`tsPS(aR@nVWBGB#leiqK;ZM1C7r^ zL{6uy%4W_?%aWN{1ezKU+Z7a|s@Y#&UQ$*O(Uja=R5Yb%f+FH-WnDKS?=p;>E=x4p zEK3GLjev(d!$5P~qR=ayPI+CoWuctU=hG$D<{;1(;plv3Cec&KA+(xzq7To{pTB%Q zU6%j!pZ@y){_lSq{vQr?6vtZM?(pG22R*6AjhJEo^x&G$Z`mYOw>#M*(KL+X^qpIu zefqK2r_G<z{N<UcXmXqPeaBg3AYx1%aGi#M!-)0^X^UyI*Y|0k_8#wk^L}~5aPeWf z=3(C2%sBuUAnyK!z4Mkkw@*JJCcATcg*=gL4P@a#3(&(GdOH`iU()2+k7Ch#BfKxI zhmrDVzHKywO~wX$fEtrevfp7eM{0yOd^<lktR&O2us?3&O*ke7_hH^BI`&|uy$FYR z?<a0|4>oR=wqd~c;n3__P4CHAd@x8yZez=%ME32|*cchd?<Z!cF>IcH)9EQ_<VbI7 zzR>8?XB_`f=6zo%*iYRXv%6O~J*Yf$xuH{P&AkIMx!iR3Om<%l!zSF$342HVu)o0b z!`Bz>8(Y&d)g$e5*Ge$B)92yN{^jBAn;dA2sQBi6jq^G&a?VCloq}B=i@Hd0j)fjD zhcWZE6{70qZV*+~g@_z(wVGR!RJJWX3Xqgp2-bK}G>D5_ghh!!kxT}0jX(uVA!nqa z(8D4enhxF*g)Hc*HwHLC0H{b(r47|q5y>g3rU=>FIN9M4kf_4EmI`-KQQ`=}d9PT9 z2xpOMCM?9{W)2q#Mq)E}4<THN&Y)mOF|ecYcQLUNi<^r!9Il1-P1nZ=1WuIC>3q`M z3cYFtDi}`8S(QcHt%{l(5yL&io|rr*1w0C=<1Xq+qS!dNrbI=BnIS?UT?vO<#CQ%c z$bi&|%1DG$5_g-HCkS&Xg-If}4|vwpIN_pKM$sWElE{F&MJu?wr<6n#Fo&BNQxJ$s zV^bwp@9Cc=?aPiqQI60wjv9LwQE4PK?%|gK<OU<uh`@y<+RNcaY9LfA@R~Dwrwt!+ zCM@yzcwfSKhx6kJ6mHHoOGs5QYm~@E0bSBeBtgC?VqkKIpdA3_FP}e`Z6lzpB`q0l z<+_Pxk(ZPfO(~_EQu_4i7r+1A-xu@SaCBIbhGTYd^%m%N%QFZF#_~Ob^|3y8a@=vq zeMz0IXgKzCLxDM|wBm-A^5N2UyP)jmYe%=6_|C2Y@hG-JuUBeqEPS)f5{(}_m@@1z z4`bU`{|6#?KYja&CD3#CSKnH7@j$F;>fRY1%njr)txl1W>V;A))BN5Oy7t9r_fGT{ zzL@^g7NlEtE}DYdomZ-%7V+x#HletfahFF7zt>52A9Wuonk4V!_|7Y5XGj!PO^Joc z{kGw!ZM7P+h$MpbV~ik#;62bKxQ8+zGpjcW2jL)(V+slNc0*bM3ekw6wVFAzeEY}G zzx?H|Q(B1l>FGlxxKvx;qb4PChe>zDm}S=$6bW4=cdOBm6H4bmH0VYFPtI9b9SBPo zGPcaD8c|$hfqi{l5gN$MBAk<4uUlAWcSH#>K;{q@cdOM?7S&YiH8aO$N4~mNv+5$A za#E#MUInNo(Ol{V(D{4@IG86w8#xA5YXK-PDzb!_Q*=HDL1oUtQ|+}@GniG81g;T6 z*IH|}zy-E#HLFoo6n+LAW(BCsTIyD7WAHDvxI-ib?F0ztB}XM!*z@+B!b%Mw-)gP3 z77^AoYUh|7PI!8{{O))Eayc!3{ujUf#W$b6`~11T^#{-E;1tf%aEFLtaPHGx1bhG5 zcIv-f=WWhAbx*GSG`A+w{fjUx%>EMH`Hy#jTwhv_0~uo(=b6%a^BOd+XCFdunZD_H z9*OI{Kc+k7cg58E>f?968YYX57kNwYzE3Ybk|FKreA|&^8eo{`xWL05nV^jpC;M^U z9)^22vVMp8KN#WB!acq-A9+`{Y=&;H9rcz&=9$Ej_er23HaJ}{Pu81gSCt>=#LbiP z&Ki5TDMPJchfaD-@)H*79Twr+bIljwPTrR&>D|bq_UyKdB9ive#maMrocBlKM%tJA zlH4gzcYI)=4&0p}Zt6SnWx0I|rh5eJ#Nf<#HFDhRu*Sp^J$lFnI6gj<>Cax#$8*-A zo0LI4$~(Co@3)ml4M^`*ZuNVZ2-xP^G3fMLjck-36Bw<yjQ7KaQIK&{W~%v7*wQOd z_|Ql{pEqW{()5(^UUnGOr_j@hmNVfb#bBk@b-i9+%O-BZAm%I!<)sv3=Bx?A%ye2V zfNk5xL`!OFy|n_xM4&=MvTd(Pv#11vrh8Ep;?${_+}&!mq&cM%vjPUH=9M{!e46|5 z^7@i<ii)iUeTl`sLMp0Oy_AwP7g!;fMU-aDZeHP@NK;BgY+&J>Sjl<a3fv_{s9Vgc zC_zHVn%P5vC<=gUE#~fdNukXYs4>A=;9f=DP!V{si@Pvgohnd6APJ`I3@8D@Cp~{S zKR=%?=dy04k|0ZZQr23En<;Thr=muXl#;svl_fDbnG;-?nG-V;#N28z5DUWqt3^a| zQg@hb05d5(IvYeth-6t7z}NL9vabMY-G~S<kTD37mYh|S8<;DzS#1D1Q-s(8BR5x# zs>2BXSS5*yh%#}oMyaI8pNETUw#8Ybaeg;$XW?WhW+6z1Q%(%8R;_FxSIH?Ywbr^t zJ34!HhPioS7AErwY(bXYiL!9g47O^u<>x_BFcr&!J2BXt$e1XpI<qqe`wEFDSgMO^ zio)+G>4ytZR>^Qe?>GRdNMeGJc(s?$pSSC46k>T*SRq@_my0Y4Utmkc0?X&qMJ1J% zPCIx7VR?LCgBse^Y!|aN&t=4)Jcm3!;hytq5GA)a-Job@e?${9SrXw%9$xm&n$Zg; z^P%<?cGMrmB7%lCcEoe81Uxo2?~#04Hzv}AHX@mf7*Btif&+^;-N~PO`-uVYBulu% z0R66WXA_}A@!sTaj(dC~gfJ>+28#R+#6B<;;>RNL(<;)IE4gvOxh+~u6de?eLU{n^ z+<9eN3_JjdK%0bb7HjTa7wyU9R=L-{fC-EtP*Zv5c>QRKE81peIjf3J;lXf2F_M-J zxEpcmRc`_(14JMa#6E3A(c~a3?cH)%bvJ0r-+lMFRy$uVr{$b;-nJSgNN#1VRW+9q z?0jq{?i8X&5d%j8GXh<LJ3^Xx5F~i5)y-v5fK*f^&_B+3S(c^AGicCA)@>^}r<~Ni z!YK;0+)Y&+C}k_9q_kKyQFXViSgGad=@P8bwVDb8ysjk{J(gX367ZasoYmo~QmdU# zOXtM4bzPTbad-1-wTdvX)LNHi2@b}lX-q+SDXL(WYGu7{AD%Dh)jOpYtCmtG2vdBY zb6!%)0K74Ll$;}+_TXr!wYs}V3a(KVR+a1ZCH$3A3LGgV)_T3Z)aq_tO4&+Tmb}p7 zZo-lilWHm3`Fsw1;p?wI{l~xh%fI=XzhRQzyLEU?M*hKjq<0$^VOX(AyLx}+y|>NJ z$)Bl$8lz&ie{^FIJ7N25C?3D>Z;1epZKsRq4(fc&-jp(G7cqy#!_7YwB@UQuHqd-? zSn_a~M(YmW^GF}Ya!4E<MmhWOgMVV2aSp!`MRYfZ03GVs=lE(e#mB?aG{ZC1_B#_k z2h5LZL1$2T*wXzmK>t0r`1Yng-231Aj-YAYdQ;Qw6Fctugv-p6JAjXy7#KHScyLn= z%X5o?af1Z?jN7=LahE|PJe0VO-@Mm~oZrEBcp1lc$GkieYQDjLJMPRrc{%S7WL(dP zf#vRc=Irr|%1u%FzWa|ksXhA6Jh42vaStc(;l7ilYFB!TK>hGx=ik5o<jhxl|IKNb z3{ILqJXNpjM&39lx3U#P5;mL!qRZuyb8Th<jWH<rm7=y*6*(_vy=@rLwE@w{{t+`v zN;#*kkzm2hN-e6Ia<W?7O@!;VmQteftJZ5NCER>>F2$L1&Pyj-ax+^?@K9P58oO7K zl(RA?cXJdk#v;lJc!aFc@dSWSQwp{ehImj`fv_wI;94D^V%w4z0Gc?<A|j=%ny6RI zCAeAL(rNMP;d?}$qnZ&4g_;mtnMnY5VNwxJi6xual24*1kPw3KxiF|RhEixoGAE); z?A!XnBClUwL?o0N&1-b2x;wE5ORbg{E~So#t=6haDQWa_npv$|S6Zg#YZVZ?2>142 zODSl|+HHpW^}3EUsXNSys)$mntY!-C5;M2D5wR#QDP6CtJ5-mXiMgdcgvDwdRmSVO zMhTt>!WmoFnv$fH0VTq^UPUxzbw>oZk|bxvidsu4h&l!LDngMs2}Mi<mmOO6*UW@i zm`Q}lVID{ew|-1+DIfG+#Au-5J?a~&a<mq2WfkRxiBvVGbOpBcwQg4fL|Ew@9+avw ziLi*KC_C3ADGLk1(5pWlz4G{xul)PHCoNCcou~s>V*Go50p3IFgX3{e>N(S+Jd_yV zeNq15?fpvTsdtt5M_AyWZTm?9@D8K$oFIyy_ewURv0n4-!Zt5&4G#hLj4pQ}qEW`z zzkVwkOvK<|Iv8#2``7OM)Q30hrevR4S^=t~YZJ{uK8-huM#Tk!8HaCsa%K-~A8!|! z+<Q%;?5B7vNY1@bKE7yX%M#MD&B^7d?h!!QN?sN#738AfLq_rKJ{3_WA~ISXh#0~l z5NBaD(~@6buiLhL`0&gu-+udTt$se8&wOH`T8wBroi0(*95(%W_0SQlwT4<xq;RFt zDkA8NBL<G8G3TY{w0&JGn+bEs01{EGly0;v%jtA7D`AUODc0s?NvG3NE8I!7<qd)$ zYF*dpS*q2Dwv@EfU688goJ2T|u&(8FI>p17Qd-wFs))C(408W!wU#X<i6ZLPmse&! zpU<kgu509YUtd@5IcsYqjjWn`Rvbb<#OeS5AOJ~3K~zz3ttzL}*{nM3bULS$wr%qs z@SjeLYVO1yUYoju*RqLd&I<VTy47kTVzw2or)62rY-Xy7Lrno5OxLv*6=l|#_S5P7 z_19n5ZDp_j`M>^`zx{9j&1|mv#8m&xdw}=YSj{NaBf)pNE6k%7RAV@r4~+82G|GJj zj&EYN*amIPBfx8ysOd{c>!mm(`*>;s9Kr4Q;#~U;qMhV+s?VM^hsXH$5saRq9!~88 z8A3iiAUS|&vF(zlK{zu)vb(X2@B6sUUKg_?eRmWR^UrrIlraf-D;~gfZ4)p&EP2;d zz%cvseZM2ho{syV4z@p15pYIZb)Vat3gJg<CyxW%owCD|^L6cGfj&aq?-dj$?33FQ zb=dK^VExE#f7=f5yi=<I-(m9p#NNkLGuR=0rKU%b=X9xvGy?JT5bjrn-dK370hwp% zA%=xsJ(1fIziR{zzR9__Lhg<{Rm!zq^nua5mA`)jV;a}9`y@VrL2)DBgWdaO&yK;t zq4c}M4j!6`T4ravnXshyPWotT8nDjFr^~t2QVawVc2!O)Ov3KOB+l->ZCeY3V6_$^ zPI@v6*_uF*t2+ltZ@Y4q(|HM+;=$!9!f=TaQ+I+h3D;urHUvY`Xc`K_&YV-|9jZ1O zs&!rC*^6(QS*@0mh_FUWmscN^(!>N9YDDrNI8b8o<w{H}iJX~Sl~R%b*&Dx#Lxjw0 zEk-0cFRD2uZCoS{uVz*Vv|d*LDhbgvt1PNs)dL|FW+#xbf{7)IkR)A*lt97)7I&1g zzPx;4D#}r`3=!QUF7jI4wl(C4!Ut<?)mZ^1m#9HjO&sNW;8M-ERaHSzL<WFr-AbvB z%1+f-m_;%%2c=dN)<vrtn({5N$Z2WNgPFmrxh*-H@dy_IyuQAslt!I;kZ==8a7zae zX;xLGBPq15Yve*iLbP&o$D)fnIh@EvxU2itQq8RrBWK;VwbmAUi}Io;AXz0MQc+PR zkQu>14a^C?<wgX{68zmPaJV(*4I(1$d|vS+H;rPe)gr(am{(>935Y>1io7h5Cl1La z0)f1DCUP+87&+L%rmFB7ecH?*_SOM~Ir%3y@#J0?_BQCo2g7oQ6^?4SsH?(cB^vwJ zodw%jkR}*0pw)flojX~^s?l-kU8j8%WDVf^p+G%7vXF;M>gI9Bvd857czxsl<?SbC zfM?aFsfoN9^XZ~7<Lyy06boMayuWWvS8d$sTYUv?BvH3p)WI_YZ<2u@7wNY=lGesF zH-o|7A|LAqX-aWDO5fd<LE896L=k&A5#^Lm%c+)iy3YM^?~NJCB2@2%J-L*Umj&d} z2JCL+&eC8r?tL~<I>^jntzzpE_PlQEhjV78*Voq%&qY=K@cTbD_>e4s)g_<Is;ZvP z=Ve(UxUEglyyacZ4ApZ^su@5n<#IXKYNyjlgx&4s^$U}1n=MNYQD0Sdc+NRE9z`Un zZkvm+*=TzhYDTLj&iO>d+g74M1t3*@dV1Qn65zDEn;|Bl(?vLum$K!YnKfhpN6K16 zmL<iGaT9}&D(26k4O=95vudrE%f;QdZ9Si#a!wKd2Q)AQjhR`KDrru+l&#d_ZZ9t{ zDWzpua^_lHkcoI*w^C}Y)=8f0_uqe?(vma-l5-M~SgYa-L|9IjWm!U~DVmu(xgwQP znO@WL$7NYcEvM6IeSPt*{MBFm_4D)d=g(VzuI?YoSvTlD7=0%_auX6CBDB5?#PW21 z(#O8|bmaF<>ceeFjXWI4=(A|f@uZFe>MP|ALCtf;@8g{f+?tIB6B8+@JV>ccJH9a- zZsKRagQ?>kETg*^dM8mhTCf8UdB45$(ZicH-PyMAj~MunO~o6J!T4r`UPoKn|7~5( zdpQjsLifWq`p{<FVNAlqJm-9>w?2I9W<_<;&zJ`uDOPl1MY>5KbnJ!>#Y*Ec4>!8y zkl!Cf+#wr>xSfR^>|i?76wE8vy`$5*qA<{y88bh8ZU4`p%ZibXh_}bUk8W<q^~M`L zldl}Fr~hZJUYWOtVe`PqW<bR6=JQa?HqHCqljTHnN!r85c)D89-Q2e82}Tc5J)KWx zmB6(+!-SzK4O`;Sir{GTiQAycB1u)ZZDo<1vq)bDVX=xOZRDoGoV91u(4fF*r&Oh& zDQ>JAO<yqhG9V&BI1~(Xt!m7%ZQDfegpgfihBsKe<rO;Cj25E@f-H^8D%1_k3PAym zSP~$&sDkEb`DLc~CJT#D>mPM@IC*GOB2tVKcU$cgXzitwc)A=QClOI@D$|JWGvDgw zW>yQaYa|7$fk<`XsJU}@w@`%&h+%*NQ9noUD9sb$V0>~XCK48H<#Rz}MoiJD;36TA z*&=>7?+wqpXU-y#x`=ebcweH&4P>EAIXGyV$cU9LUR6DWi>Oh8wvJzK-fXQ+4XeYT z4Vv$F4CYP0syhZqNi|XLVP=t#AZ+r)nnYMt8RT%IctDzvCsjA$Xhn?M0jnEeA|#q( zpQy-d1&3~cLr9FORkzCAQX`!q3(@ZlcUFm-epDkkkr8C*{+I#gN+#k&2Jt9)=%($^ z;XlATnGIhz;P1ThgFtJKhPWx@Ofu}ft_pi`&||&b-q8snCLgflEDF$(!F@G3czrVu z)+`h7mifYDzV5NnsNwZKZzBetr|4&7*|^z$VgTHT(I0&@v<KdDUJv@5hkbtpkLEyU znT~zPJLr2~81U%0eEf*J;0f&x$8jJSxrol`dY>_vve0*VF^)b>G4rUSa3@i|TdG6U ztwy1=4JPgBfbJHgdG6ktZ@V`7FkvYrM=*A_wQW=;$Ey#oR?E6xzy0>RU;N@%pFVy4 z-S^+0&rdmLQB5fYP1Kh!Up{<zetLQeq&CFOLrGxUN@P1bbtI{(YWni!OU}7gclXHs zp3j%3%d-e?8<>%o{PgsssxL1up@|2Sr_1xUt?POXyfB9F^70a8IVovMNi{KhDJ4$v z;ll?J4l}E&nsltYQDUtkA3uIv*EM|Tfk~&7USD6Y*D#dojxXQ85YckV+qM$p<MXq7 z-PWyI;Hh|h{qpInZ!S+~xSQ2lx0jbM&mTX;G8V1EQ3V9IVB^j?YoP3A-+lL;s;Y{+ zFN*{Q|Mc|Kr5BM>s@1Got<FNrvc$a}8Fe%I@Zl=}>$<sHlxL&2VKKG)Yt>U)nAII$ zfBp4e|J7gr?ce=BrBvA)_QpFhsTsZT%DwyPUa$Ko26$&jzBRt@Z*$wl93age<PTQn z+}I!BmWpP#KM$|x-GRJk^rn*!0F_3K%sh|*7Y2>|+lGsRQKjk1+{v-Z021H0j<-Mr ze#_`R8uCmAF+qofTln^ejPMBd?jIi9Bo#+?q8YcI&VR#=_`y5Ufo&QcF>@evm?EF< z+S@nfPv7Rpcm||sFSKeuJ_v!RyFF7AHQj&>gWd7C;{oW|b*FX#+nZg8N88YYH0guc z9>T=^V;*O_yPh6wv@WEF#~&B`_@N4#;y!vbalpet4sX`u`jq>dGG$SCNS^F1Nqr76 zlL6d<U9*L`ckhljWgm2V8Xs1^w2Mia^0HiOt<X|7va)1J!VCsA_4z25B_ekQHDUT% z3($%LR5kK`!5YP+s)?D`b@LvJ2E9=5j|^QL04e4A|I_w%-LfRdby)0(%&I>3&Wtdk zZ4d%U5uji%>qSfU|9|mcpiJ8|<p*oYkO%=Yz|1|Tt1=_P50RObRo&+j-~hE|0q1si zePv}u#>bAmYiTiM#2b!S^+L+A)>6vO%zy<G^|*uhJ$pm0R@Fc_$IS=6%-xB#<EXty z5aw<KbMjh?JG+~cp^}<jY<66EkXT#O1PVdlh%iCkj!zBvZPeCNAJvv<8YWW~mL#DY z;tnS&rM}(oW|{;dAop6UxiY7C{aXK%SqrB7WvFUo9|8zXjb(~etx13Y!*5YH4}PhD z081Ct1VyDZ2DTGlH6bDnCS}#o?~MbBh&9g5%AJHYhB~tCJwk5cnn|RQ{kV7j7j#sh zj;=Q!Y)tTgYB&91vM3I>m5Z4fr4)cUNgOBq(s0ir)&)?ihTj$;Q)oalGaPQ#E41!z zXpb0V;o>$k6WxDN)DOB)VWcF(6KI@V?y8!Cq&h(FrXVB62!NYhcFH4h+Z>7Bs_zFT z=u{6tU#?CL%)wAF7V#-P_ZWhnnpuvf%ae^cOwZN7IhKbj0qW&EgB^4F!Rd~kN7?g- z?i~y4W2rq~4LYk<yCVZGLC~Kh`u$@Cz<5$4_0J=@ZMviRXR$EIWb3cT?f=8aj^1+> zCtB&jmeIXH%qi{Dn077u881Dr%16fi0EitW-&5ZA?10L|`udoEHgYgn)si5mwHI?n z`uxBl)Vi^x9<)p(J&n`Z)HH;`%}bKS4gK{CHE%GpRd#Fj@_zA*Kx@Rlq<P8r``fl} zKl;(XOesZQ3QGdSjNEIO>Cq6omz@P>4hr5vxbw24losX$f;oYZQ*sKXsG8Cu!tUyX zys%gv*AokK;HGZt3JyIs4x1SLx9*<O!Vpus-SX?}Ybhmw;@^M&eGIK?bxLXqqGes9 zrdsx*!Xk;0iWc&=283Qzt<|jDZZA3I`+XNl>w1gTC7dT!yWh7c9){VyZ?Dl{OhjfS zWll*{Ef7te@|w5pwd{8=Ga98<s1(Eimc6JVrA0NsMUmo_aNs0S<UdmqV2$-=-*;8Z zDOJ{#QqQ;_BxJReSl=CqSwNIiHp%-||NZ~^zx@6G{h!MI9U}-JBNr$XAY@P@T07p# zQ!eJ5SDLp0bM57b=|yl%L@!Tl+04)Mw20TGP1_qi;#;0xld0Jij3Ib-WzOp_-_QZ- z@8?k0nc~Lj=ktk<Yrg#K^SwP`yJkFa!-!0jVRjzmkTp4>iyw|zod(;&<;!RgcrS7u z_V8(d@&3Jx&PM0sp<_tPq7PQ*5E@EOhXB$OBiyd%h-WVApM36mn%wav72R_yCnD}k zEH|LGeR4Jx*}j?_JRdX_2|u^?{WAg2$0cE0X3L+B)zII0M~>y-y;GmCTIU`8d{XpA zfN`!)IngeNyYS&>vLwgR&evx>S$xv<dDwGA`qzYVbZH!L;iH3t-U0c~e&(sExP{j3 zR5NMT!x0`oY?FBq-VMru^X%$W@pBHMhZaxL?x%g9euhD~^;kurR)&=f$z^wq0K?SO z5TdbKwQ4DK-}lfKii(_Sbt_3oM9ehke{)La4u%!0>RgEk`(C-z)HTer8w*<lCr5+v zkpdtes8Q-6u@QN#D&it7h!PQo5Zo!;3{x{ka-)cSMz*Uzc1P#(h-cSjlMEpBQGWC& z07g8Pl8A_^MD!b%G!EP4!HvjNE6{nM-CEJO=?S5os+z028fRol1d)`OQ}bX{-Kv2B zDtoE>9^+8GGIQw(hzP(!206NOV^_dA3BV~u_*xsiIXB(iS_{F4KvbX5-eKfyRwP9` zTr0(I+ZKc+F<sp~d=+K^8kwq@5kk>7B258kxFt>o65_zPQE)`}NItl%eH0bqsoC_@ z%*?~(g$!q}hdmK>A1><w2zOOgfKtLJS;tHg;g<i6=d4O*O*|@;x5Bk;l+li+UF-}) z=N>{Mol$aPm-fh28SKHe6~t85iLDS#mj`|EFhQ#7Hj@R?X*uZL(TS4&c$Izp_=tf= zL>++U$Xx~;`yju(=Ifs?K<5NpWFtFDj?TE(aZPx~B;ru&d48scaHlOF{_rjO%^k+G zR}HTN^rzT<SO9#iE2n>Vb9@2IU9!|;mnn7He#71Ec#rbo($?D{>_@`Gdy-`msef{v zH2?m%`o@GgzC5is6L=DI^cg&TLSyBdm%3AG1mH;2i6rLK^{K}JhU=|BN=deNGSsFj zDRHy@J*SF^N!&fS^;`DYEbLc=mmPCcQ_9<R-?uGVa6_agL=;tBgnF;+9_yB>W=^5s z3zD#1x7#`(LS~+G5|L$DnE`B(uyk_O+H<-#DF8(;5EJa><<?2CiCKvJ!-tp16b2uE zDFuWG0*R=Ul5<wwmnDa3YCXv~q%q7$B=7r<6j)+n=16a^>$<K>G=b+O=e(pOBE0Xr zsxQl;Rz)ZT?wGOfTPal}1y9wICF<d5=||+8qtyyb(ZE9p0f1<Q%FJAL-M2mViYZaO z0x;8*g&LI0N-42GdZd%hmb{dr%o2Iu=8y#LS|rFe)WIxnmh)P8`}Vir{o;T8w?F#P z|MvRn)u*<FiF=^WJ|8rN*Vkl{gt<6~PZi$$;eQ`?9JO3rs%mF@GT!=wzIgBx_MaVX zkf*NK3p>;dW*glZKHl$Z`YFymb~zpKZ0X;llz6<6-W=;gv}s!KsE6p$)=LKhHfHr~ zQv5J+hp%y*cb4qCK842x?;NEcAAg>Pus@U;jeLw!%jrJI$v(L6$G4Z^nr>vA?X+0> zWQ6^6BSc3ii^o%3V!_d0`T*PMM)aUId3Qzj4*co={=*Q_Q?xl=C?71=qZ<6M=!~@b zD0ZB-dB>;j(UG6({uxi9WzWbsTCTZ$HA<21E`QU1KJLXEi}gvO__UWliax}JSofEn z`gt?G$oRICbss;tJnMJzS??a!r^C*m7=MV#XUFu>Dt-n_GM{$>P&l35vY8|n>~4_6 z`9??#ad66sg@kn9w|lAkwl!3+xri_))j~wVsd_ap46misTFEJjw2_C6wi<WRs@@^B zBe0ZYrD}w}{V_H93?~|TIUp&emRi;|GbbQ?3Dl}ld^I(-fJrw;LL^0nIRdQ+jcQe` z6&4;yBNJBBV7}PPM(#;^PhAgjBP$&}&#Eeo8)?9J9e}xN-AmocEN3An)2dpV#15RJ zBeWWulYvQ0A<ii+IdRTO)}_2{0Oy>xt(3B-6mKq*)4uKNx|UL+)r*MS^tSNG0;H6Q zu<v&OArs*ZAbkjZM!7g#$G~-uJie+%Hs7pPt<2msu)9=8kE~)eqVB;1UmYp;;Ps5y zGs{wHHLp1fGuIkiWmH@{zE65UUPX9WvZ|L-M3TE}=rlRjHNlx02bcheuJ2)~R2^Vd zch^zkZjalVfCy0rU}`b*8cBh8t-Gs%z{H^DC|WHYJK!zuW(EfaJP8xbK?*YA)WZ0x z#_bg@v}Z|V4q@g5XD4=d1^@>;gqTTnmL~G5C3=I+DA;zU)~a}W`z!xEcswt@P803! z{4KQ^MI%u=mn$BV_w#~sG>@FF=gEf7vGUX~zUSeb&wKic$>*?Y4&tW1U+>_eKUK_o z+J0aKIJP+ji@_|@zZ#xmECu=yzIszVJ+dIw+`jH4Hg9(1>-!2h;o@-Qm8oM3efZPU zaL;_CJs~j~aE9~W+nBo=>cv;W1pGQC_~ev?l=zfHKXLiYEdbQgWMD{=TF;VEjmwVQ zsbgKHE}%BhaB{7hQsMwMJN3Q`1q+zm)!Z40J3^-CuBZ{}899;dHQiF#_wBv`bi3V% z+&mI#K}n3vK_yiJncQSKnU|b$Ue$cxN^02SV_3{W?<u9EJ!Pw<>@P1bDdl}DwWz8w zB&F7(6X~u&pv6q)^zz|GZ(&%i*7El1>$<LK36VN?6@j^=-iw=;rIxzwo4ci)gav4b z7jVl!6M2%9({g*sBC>6zcN5i=B9TeLoYqu|GgCBHH);){SnWi_l-vlyZe;F&m$L8s z-HB4lkq!W}6IHDV;xKdC%f6T5WWf*yP^l%7Faa2IQ+0E-S~XU!i95#3Dmci%yqCu_ zQU*wJrm7)GzvTSJ^4)je{q@g&{*#~l<k!FcZ?CVPxb@Wc(2KMwd$wtTX)1Pnj?XXk zBTM1@&!<7}nEl7MlgjHTq_iI&1p0ltPs#erYtjXZrxoX5U^-o1zxdIOc+Av695MT> zoe?Tlj!8hzr*|3GQ}m#=7kdvE=G5;uT4)@7B{&wksGR$W6PeGqbGp~lgNO%tDGR?3 ztC{~EX^v}=s@36rly>Kb>yuc*{7{bbjuDtDho@8ENJ?~^O`iyIzVMi*XHf0+j>ZoC z8ro&gA=$8pJ`Ez%b*juadL50^*uozl#vigp;zOpQ^vvG;nWFupsPDYZJ3az#4~DJQ zV@UwIOwsXecUI=)!n<c2pAYV?@rd=aSP~+acP45$2943^{WFen8^TCD-R6bK%%)F1 z!#+h1k7K4trBR1G?>Jx!7o#_)$=*YD&~#y!wAy?<hn04BLCSJ-7k31+o~e@UAWBKx zQYjTcN-u7t)mRddx$BY_^J-R9D-lUkoe0<{!G#>PR-!uE`y=wnIfFfCGLyhO6Vbl! z!Q~+gb<KHAk|Tg+uxTuAEf@o!>PgzF#*GDIC+Fav?$3?_oLXzGWrJ^kNXlj!hbcvg zbl>-sNYTPGGmZRrG$o}ZrbeJ75+O>c9)|D)S#c^LTh`UI)Uul?JhUzms992jIvG)Q zsz%k>SUe&qEB3bSrIdZ!w|(CjUW!Jj4Cc(FYRp)cH8OXlY_+~_+XkeRa@keQYOOg- z6av9!9%7a}`h;7KJ4BUrZ-S02O%Bt&lu~tn$u}ZIQ!Wv4C|Q96!^fPGh#8_RU)6{Z zN{u4oPG#4!-y_#wc8$JVqEu_inMTPW4lW|@y6-jW2Oue>xEq)N-nO!&aO%7i3uQ_= z5W=wwfD)OAs9Qvd81QA0XeW-D={1P=NlisY-WMTQRlPI~6gR7dS==I|Cpa;O8X1@c zR6#XHRaL7xA<%Xy^gc^*SJvuIOq7TW5M~gmdvzLOpgxFW+!>)c_axK!St6*@64}K# zXjY8t<dNQ!cdb(RS-92{OM-5`K5v3%_wRB0yzRPJT0h?l^}lhp%q{io{sdC|C)$3v z4)D`0T!G_T_rYrtPcfYr?BRlkvJkwjk!`SWU?971#XX%&$I1kLaBk+~lT2&aRGJ|3 zfKRvX0tzx!%mRHQUTo29zb(gvXm3*%+<Z1VY<E9Y10{yyxp%=-Gpi($atigf2M;5R zl&3^2u-X)u&;>#nZmJ+lkYIq0i?U$P0;`o65@G3tSVt-`B5>hVccTSvet&ztzrB9( z;lppf{l?r<qGjQr-Df6(0x9R^w%*>}wr$%QmPP`}vz6k^iCG5tWZ&z)*9gl~k^oVw z>asX9%uuUF6ej|L2gv$2zxgJ*VVSY*<#xNZkPn;^n?X(0G)vOR)VjXD?wl5w6OpP> zRTkXeHh2B-;U(wf>gLs9=5^b)T0N&Fr*&Cwrm9*?sip3c*r=M<NX;(G;-soDGZAJ^ zX8Pen6HZJiC&_o+YgMYfABoJoGSgn2Q;uaRgoOdJoRTHLwz@faF;IfQja=h@-0!>h z{I@tEuYz7!Cs2gGsxHiuKn~UF7X3(MUZDzdw+dic@_M^{dVPJ{%FloCH~;BB|G(eA ze$ONkL-ll0xNps2_0dq!dkWxue&y%5;%W`2Du@%YKk^J;-A(Him7X#uMo%KebRTA9 zfQ_g0DhLdp;vDbqdsLV)Xa=njY+k|ucY?KiDIUWKYpBl?_4J@gv?DXnC=KJyj!P8) z7tZP_BgW*0*1yE=K+EN|ES!NS+StGzHF^wpCrUo-<S>v2h3|QUpV&h>f7q8{jAe3& z)pg0)1KQKsgQhq?ejkQsg!;gsr<T5c&p~E9R+*}L-YE_HDMmx(QC=N7^C!;yhua*- zw+VZOBY`qnwrsY#IIHH;c{Lfz!^5i>*!6jrfA;oJscsOb_uAU0u9=o)_a{KRwq2s% zCzWuJk;{Wd*IaNuj|rX~YR-P2PR&GhBtFg!z$0dUuR;AtMo*cm=@eJAJNH%yJ6{ia zvTKecFPG8p@$ds@D8zK{<K$Bl{-9}lc6Wy|+cWpF^Dp_)4;7iLt|0nYw`m9!;k@LV zsh52-sH>4yn58v|QRUiR(9l6_lvHens>MvrwA9KFadGlk>|9-IH67u7@M%JlfUqo! zdTG&G2m>-N%c8XsDD;xF*0khs(LyRYNn*rRIGHCFkM3WPsou-3rYWr=$w>n{OF*N6 z>IeWc)2i0nxkCMjS%VKaq;8^ZDypsVbRs$4F;f(|b*;5GC_1^<{T>~j(J&e{nADS) zLBT~@yc9BkGbB5xlE2;GO5BoLMAuEl2O=WoT8gHWyg|VU;Iu66rb>uTT7$4Kg3d!3 zBqDEb8>8XW&{4gi0~BjxidN(3xpoIACyowovryutl#*37H+Kv0zNvww_u;fzZRVy* z4iTtQ>y{4vEK@h+oPn^<=wDG#mQ<~blw>h?7B+QLbuwWPMQ87LQ@EoDnHg@u*M&x0 zM(r+=Bo>LlKO)^)YN&g;n`vzxO4HcZC}cB(AO@vIOzrL#!p33TG@N5q3JMsJT1!eI zl32vuYu%VUadsoKN~8fWXJnw^t5q$~3W0H8#*%Y`aYuid5%ZMo{@j`{=bgtkbmqH* z@jSwvU@2o|yq@fFL78;x#y2N(ibrGmj(I=d#jt%x7J9J#p*cu1vbrx=!wBPgz&~L$ z{70z(kF6C?;7^!dr=fr6^LR+!5b9?-=y!(T==>fl>wMUA8D}th`<3Z&Fr{{0L2j>2 zGg9>Au>KU=)?0}%FXRt=JUGqe=tUvt+q%BJeh<D*EI`~ee9FXm^LxuL9CYDu)h-?7 zZr1ppg5H7%hzE^9PS6&15OWGlRHr@`V}Jeh`rB`R_ZNTlSHJo8w<6+>s?Gv&0=QON zS0?he`(3pLnl}PG5&7`(!@lp^w%u;Gb-fW`-}m@UIMB7$Prv*0<(FSA%c5FKDW)Dd zQ8m?~B3PC+`1Dov<>e)mjh2N<*|)8vltmySUw!q}_uqg2`uf&$6Zqoe7u2aTy7*or z?9l4Uwxs30-HBW!3B~{bAOJ~3K~#`ZCQoL2RsHnoQ%cKT?(4d|yxf*0x3&;+B3G;T zP1kk#^2;wjefl)Ao>7CX)oQ&1o0)I-l2U48Oh%;Zdb{s$5k*I)a9P$`YxGDn^H*Pe z_1$;hEz5Gd1>U<R$!2`Nzm2g?Db-qUw-?pw=FB2F-SW%Z+Z!bYu~sdmsCr5()e<wJ zm5Uq2g{`;c<Hrxb`qe-F;urts@Ba7y@XKHRazHMQw{LW5b`Hkp@7+AxpIhb6e><O% z&M)t0Ql#_tEE1TzJ<*K`eV)Afay^giGC2M5#CFAha-43k5BO#Ac)GP=$6(wWB}yNS zn1=Tjw#x$cG*&sbfAWc3VwJhT^_gu9_-9T!YI;L8;a&RWcKRk&-BO$vi`dWn``qRz zM1P)aeC}2`mhS5rPa)qst=B(j8y8=v)c%mso@<*ly|5!^-g$cHQn5Tkf4wh=qb2*G z%C^yK3}S~&@vS$Zv>pdWLJIKfXrIV9>NGQ3;-L3711<GDuhE$9C3bQeX{>hj+*{E7 zoOc-A`%a{hbekN#8C^9HXQLK9C+3dSGtsQ@F$qc!fWw3j2RXRuZyy}&)S&@>!mQcl zq0p2o_rZ$SQfQ7=Ac$CRya25qkSutaSdz$6_RaPk>E=#q1Q${^^IFU;R<zyR9Ap-y zMP?F6N|N1*8-)N;(0saks0oG~p!LiYC`61r-exyq5(t|bydlfTSR@g<o4RU)Ho99i zM}!CFPAt$`8eX>bTq-yN)vOvRg4)=@oES`!g7?HshbUSQJ||g&(j_7(kwmT{4vr*< zRwHs_7m%APkukhlbZ>^g1XW{BLh6WSV~aT*5gl1&E3nPI5)w)FbTdh>W#4Lv{->PS zl&UEa<<_U9s>OXbjV4<FLPib<Cyt7aMQ3kQJW@Bc3gVoWsFZr}p|Ue0aUvqKoxCEj zvQddNCm^x7Ih+y)&b+{g5w50_ky;^fiP3foXkp?6H?11)8H0qW5e+htx|+sw?Sxox zb4DU_*Pyl0y?%=JV~`7jXz0mt8{dQCC_1#Gvs&F@77$Ts;}e*3vY23|Zq><+<7v84 z^|?6-G-l{PDYf7^ltH<*hLgLw74phZVGWhdloD7}LxR{jf!T>GVJ9d#6D3D-2tl0K ziGj?0bqlWR5JvKlV`>eD@J@PrKu`}OJY%MYUo>8Eo<9kucWMp6-6BnC_hBPjT_f5J zkL2kv!ZR3ld^jyAK43=|3X%x~)JQSVD-+%!g3}6h0IcSs!mzj67M(eOhfk^enfzs1 zk>AY+{9)T4GXQoEaig)~K3?Bv6awdw#rXmJlR1FPqV;&#$k1Qdea5Uh)q?yKPCq$s zPZZ924i9HMFn;KiDl>P^CGi~e5R{iZ^Nq~s1YkyHNO|4%tt&$grLUl}FkxY!s^%n( z^RAstx@xl@iRv~9qc&x|!KMQI`u6tix8MHjpZ#2wLT6m7Ze}U5-9rK)CDD|?!duz7 zG@8DMwNgqsOU?=KQnb-O)EYm?d0Dc8#H>b!K_tDr+_r6F#<pp#o>FGPdRueKkyO6j zZmPO%#SNi|`|;yP5&8J>V=1N9$}H=$68Ua5NUcKYA-ZnX^_C<F3v(8(@KSb-?%!I? zTwh<mSF0i{BKP~9h~mhR7dNx}{q2h{z6fwvbR7qb#|>tc1-JEO$%{Mg+g&6rOJ?Sr z#gRI)fcAZlamXpxqAU%5Gg!w(gq*f&!V5?v4PQ!$UgDUX(e$hP8<DT;OG><LcffOI zW-0rws!<0H$>Mcgmt}c*xv7?4{o}8G@c{8a4!^U1^RIsLlmF*G{>Se>eS(vO$Juc; z4y7ZG99ngc<mB^gf9JiNzkT|e&@jX?8~L08eL@{aG&#!8<K)qIS0AFd?nys%%T8Kl znC<K&tBX!<@el-KS`x^6hot#IOKk6iYBVick7Lx#NO!4Q)@{0-2^@7DAtt({lc&R8 zW8H^ueKK6fbC@J&pPlj@da#yB=|zJXJ4%z?elN_9GPU=P!a41D+{kky+#cxYY#(fe zb0j>?-h;yJ{g~hTV?v$aTbFFk56D=DyEEX&2X1Km$InjDq4_x0HDGofM#*|SdYo6l z9(W%7(fy21Dzr`=rat*SGvQocYKB`D84VANRu`i`y}~o(9>*0Pa4z)zeCmH3-Ts7m zmX3K9&UBBr=k9@tTYGXwho^|?c6#vK17-x#0OoIx;{%Pb_dHxfPw~QLHzz5E-94yp zVt0r2>{vIL-BWDrvt8*Lk~n2kwX!A2Q5dW0MGHWx-XqXJwDwG`v3t{>5lIFjM^Is* zbu*HKSje5MY9oRoHv^HSL}q5{%z#6y5;a^cIcH8uQmwU?y(fZ6s{)`DokSJ|!XzW? zhk=u@xtdqA+6kYN8?520Lf|*1mJbsxlAMZ}0~X<#sx~5GGAD}MwKV9PQbf{K-Kg`T zvAHD(v6ICmDY=umR<&Bm3T%hn$qgbTqOuUn+rB%w0NiLeBnVSDMix$_46Ah~VunQX zZA9dOmeU3WB9Mba>p>MEKS_;a4Bo&{-Z-KF2WjABtg#q_xV4U@&|nUlQ&+bN2Z7xT z<ZkNh6iW0!FitnOu~n1_3^zpaUde0S`-^}EEl#3Un^>*~zS=qqvcM6!g~0kn9!IV9 z`Vu_E{Fvj?YfLI~VPQ2h*On48QniS%+|{j8i^R2aXSh2td9bCBYxBAzmE#y4!iWwJ z3f43at!!?@<_sbw6XKjQLjiRZaA3;9h{3@T0DI%GbRJx6k^F*Bwv!`y(L2ayw`8`% z-6#$NHI^iwqpD%*2e;P=QrAPyz5>S6Z2X!Xxa2b;I&`FFv(&Bog^Ah+fMrmnV6xHF zE%l*s>pl}6cN;#%TO;&6<oQ5=b)v7a*NGfyg8u!W?S}=xPh8uU?dXg5W&12O^jL2| z?vG*W`M1sRUAoR54>}XB4&kh`12o))<KPynCJq;;opgfewW;@TX_s|zELV@9%D$F^ z!<vO0*_5cB4jNvtxk$$F+4=~_XlPYP0=RSQHMc(UF?wi}9lHzxH%3$HtEEU@ywtb* zoh2=Kjiy!)d3Pt(wyv~GXQo2J5^WpN3lZJ3r5GSd)|3(v<(z{skU4$v#lK*N(>)~y zgos7>!-tnoub-j=BuEsNyyTpNiqOnz(Ih#i)m>RYL_q=FdSJk+(NJWwya51H-|l<i znk9RteXpvv?ImiY!D!9G<_IdkU}*U8;luEFn8}nTaXbQ8wK9Y`NkU2_iAn8t`yff& zZHOO=NU1f3y~|4wfn!Ny=9ib3XmyTfVrt8>x`Bm<-d!+eQDCAW47d{DWiPdosx^8f zH*H$bw(on8c&qBZ@9v7m`{#f0mw)l&AOHAwfB*M6<@3B9USJE!&o1fH?NZMDy}v!V z%RUj+Ovdy?)I2QgxJY@IM5q0R&Z6qGZ~b(e;>J?~is+r_ca9hj^y8Bx;L|j~DEQD* z8b&{GzYz#I^*HcZ%zPxcX7BlWy>n~#qwSiOoQZ5~y7=cK_n0T9Zhu<9L+%dikHhE+ zbUCjghn?bn5B~5~-|;El=o*aSdd4RMIE5=uAN5%NN7b<@C5|WZ147@nF%7n@^M!UN z<{~5E(~f9#S*I1Gku{zXL+228-Z0Hu=)(l-GpCiATXiD3)bVsS9@jGky5q8O;k=-u z?(IG7Ji7gHNIbN_by$b@#`8U?=P`>$vb#6=W1PMJ6w^bWNo{BV`1!b`Ha=+G95f>Z z#^=+%hv?;JT)Ht_PcZhKzP>dWab5vYb8#cUO!u;@mL&({V+vyep(sqMx@wJ9VKZV# z;}dRNy9{BFxZA#0_a-450|GK4Vdf@jTa~Cr3=o1waB?vciCE71Mxew(j;6tDCL%fK z5J{@Ff)j{CBq`9Z%`t0=Le@cg1G*3i|27iTQwDpf`(8v4i>JGjGc(ny9s!bBEyYxc zLQ@BD@=9*n{j3N!&8oVYM?Eq?%z@hFM!y{DJEoy-gp{&K)><gYy+9xq$+Z?YH#o5Y z6rIKH5d*`?gCrSYvEV^&5+avGo>EGQYc1wP4n`uLhsaHhh-%%*0haKNQWAh_scOb7 z!W^zhkdKBiP~!suHHqC?8{OuzP#`K=x`a|{?K1$(s+p2UU!D*lXNjoN5fq*(l2q@( z3`!s~-S?e^hQbk9C^u*Xs6lxX49_i1)2P8~2(5bn)ZNU8$+^*3n`)#{%-!4+ouxTW z6G=dBC~{(m!GRP^(D5QM0AZq(kWxzC<)odQ;edw@NT(cUw<a!4#69JGprC24td9KJ z#MAlyD<ALnITbsWyvYt9#a{5#<}>BmS}w7t|9oB=`igM1!y`)XSKAq^C)?#6Q9HML zJd*@Ec9~XWnszzGx_(&8e(8UVh4uONg92dh93m&$L!#5T$G<~c?6l%uy}j{Ol(|4~ z;`fkpJ(GDJ(s#=&gDhouve%`0WIV>tA_n&J)eeAS2V(irmpI=kCNNv`07lUM<nlrf zJ*8EI!<szaY_RHyFpg>njp_%0s>*7dQt{gF%iF5ZQaW9`z8{c#uOkQ{7@%euP`6K? zK7IGQ-+lP-;cdGI6@{wipblj2wPJ_}b8s6JRm~|&l6~Kp*RXw9a!Nr32{kQyQKcXK z=%YKC*WOK0U*BFoe*8E%nVGp1Wk#(vr6Dkwh!o)HkL;|5A)^{R(n<spueEO5R!Rx^ zUm_}{Cdm?&U)4}|7~pMH{rK^tYL2Ki{<oA8OqHr--|L4DUycXDOgSf0+xJ~0XJL1} z-|uFg^Rg^C<cLZswH6KfD>P28oU@w~MN*b$%7;FGT-9pTl$pC+bKD4nfkXs1PYI>$ zpFX{^&@6`3J7ZlW1vzB+BLLlQ>yLi))wb_H{pnx)<zM~fKm5Z#OfLdPv2K{2^IRRE z1|J!?E&>v-i9R#vqkHqc@Ob|FYUx0a*xFP3+$9m%VZ_4_4-&fv*ZjRumg1BrZL>*u z<+^B1<*}HGqc8e$@Kf5W2eGX?5fhQ)MK!@Y7_wQ=f%iJ%K?Yw6+9#X%>>hv5oW&G) zoNnYXm>;(@kxF%o;|-05{-r-0_MNJ!M^XTn(d>Dsewz-z-pgDqe42WAdLx($eLcRq z&d0efI+3Qmzx{zM(Br0tuE7|zDfT-!pXV2|(`ll!cOIkNGrvALI?s9>rZiLRBG2w_ zR1c)J?vLvn?v%@fQ0P~P5ytCOl%{^hxvjcm!CGI#gb*epVyD2S{vK3PU0~&%$22_S zxV#Hk!-xb2h+w>EbCPZ*gq!UHPbs8P&mlUhBK^@|!jI7NB0*p8?VUUA2{=xi7lPz< zwXQS+jwhj}%q@KiVRrM{im2wKriF-!p*6gboPth5!+^52#vil_8$kpNue!&3YVKM+ zFWJphE0O1%+<o8o;5}|K^;*GH$-H*Z6E$@ovq<SGi<t9$-_YYRRU@)cZRM0;RBLT? zEsYtH%xh-xjy?BYERIRl6%EN8f%I=c7Yl735Dah;CKsr8bRD9~XR78-%;fCmO>2)C zfP-?*l9HL-@AuXPtwzqJDAeKRuEC(0(^{)`hCeWb*lR6RRfJ7FubGI<)H|_usXHT? zyVh#1s>w_fXHXO4Rt@PUadUt~#GIqA*j&AuwSqa^n_5q}WDx_Gve#O`lv2)lWgMK_ zIp;wL5<O)pEz6QRA(s&uGfd+#G2mbjxgqcd1RzO%+di3^a3VmhM%$m6wiLgysxli( zSD0prgGaerYt>RCP&ccL=o=@aIwXsa<rwB(<9=gy9j}Q;SP_<SqC4?ut&U1LaS(O{ zY(Rr`r5AO(tWprx05Qj4O3}?1JXkp3THO{kRT`esrh{haeM-M3v-<3<A2r_Lkp+05 zS>wT{h@+Rd+lo`y$yL6w$GwN`rRf^tXWG>(cw#fb*#Mqzq^+$_frJ-OjGq?tYisl$ zbNhi1XrPl=U^vD!XP3u6yWUeU;+%f@===IO_|=g-p};#C>_t<W=4Xl1?`iP6oDTYM z>glp+YAif%q@VnBoC~gO_`%nQ*QC7q<ppxZ%)q?leBVlU8jeX2FEhiUiWpSSmrd2o zDT>JLhT&~pJba#Z)yz%Uz2$?c@ps3M-Td|S^_Rc=&;Rnze*Ee6Q<rNpcMgMM(*{P> z!Y<Jx6eki9f}4_=N6t7(wM3*^%#=BSc;D}(R5Pm8!Xmfju$rl<Mh}OEfWf-n)HXNo z2|UhgUY5M?yVkJRR7zQHxt3aM8OnrC4yHgExog~VN;&5gV!W@fuPLQvN&8+@ZCREU zGbhPeLgX+Q|6}}vUY{BnW<_N{%U-~Izi-R3j9PK6Y6M9k<QoF<mU0G#lHQ1TLq5>} z$vM~Bya9p-06XVwR!K6GhPb2TWL9I^jHsaVW^0UOWPiKz0TcPhk6)CneEs#;KmF-X zzxd*dPv3u^xT8$ld}TlE-DTdkpu+tUJUqro<IQ@?$1s1(y*J^xjk~_9Bf<GdfpfxY zUJUp3kTc+8+QsQGwsTgi<(kg+-TP&XOzIFN>I~EuQ!^cs&Nkp;EyvLHk)D%-m+{~( zd*<hRd3xCS0v^Ab2k_}$^YC7d<~`FfKbR)ycu=67V5O(=c~}(sUt={G0}*Dem8s57 z#{Bm|BQ)R9<2EjaT13~b9M5(f$(MJNt?zvPdv3A&46dHHIXZpJqmO-`W{szO|L3=e z84el3r_1Hze~+iTZ1(Wa&va!Y<l>$k_VV9nw?j7=&pQ11Jm52L`S~a`1NCPMVAH@p zqSXe_k()}z@$H32`k$OO9TM;FQWbz8DRIiXn&d?tu4b;}wqzl)Y9J?5BbW%gM-16n zNZ=_6v$)krUI&e3)nb*%g;|&rfud)p>CLK33cQswGo{vgl~M{?EHf>o4)PIIB^W$f zq9ll&8Vzq%@`&XOELx2rosU;%s}R+c02n*zDDg2zofT>tp?$47IER_R!e%BA0<4;w zCgGG)TWyJ)Jg7rc604ng$t)xvhByV7gAZGhNY0XybT+9FA|gU929Q=~Hvxe-T%8y< zfLc)(6iPfH$s9yb4Z`LIh6tFYlv4KML^<cqge9R09eO-DEvm-CflVv5h@^1y%n1Fd zB}t(x5Jih1=5+T~{f3u)j|)@Pj^d6&E-|NdO+>EMM(HG_yevyZfcswdeHRI}jrK;E z`Bt}>0H*3K)C?EYO>MNWFsDESXf?1ly=78zC08&BAw+-MENECiwNB(|<{&jwa|0-v z#l{vPdb}*EZjBL)Ouf_!j)=EGBHdW4k{M_$$E`u#Y0%?0oHH}0BvDVApfMM+y4hsS zoP3{o<p=)sX{2_6w#80Qyq$N<+Js(t9+!UJI{6>4ro7jybzJ1xxf;mrKk@d10$^ro zBoJt%ZA3KH_q+dcx|1Q?JdzOBP*1Qk+r%>u5*~~XG#VGt9WNg!L7EQIrL^cwYjN35 zm4J)X#86(k_?PH=i~`rC%5S4H=bZ;>)9h@9_O`yf-Cya%10D@U!56`RNBgKhOz6;2 z286*{YvkjIOwD^Ua4Vcg37NU+-~qzSWFf+?weAis)&I*c|G&Tf+28!P-~1Zx0bnMA z2*;|KbB^{}2)WaTmzUe^C6>~hZ%HzkkW)^#CLc$(EX%qsWv~0btt%q#Rkf&924pv| zH~YRbi>jt10j64(MUpH_a-$x)!`(i7cu}nYF{D=O<gv7_w{CyctPrtTRZwDt4Dz}z z1G60k*qj?Z_3ieOQ+|DYtEB=YlGhcVKE1Jk8OxFZy5C>j`QyizZ7XiEP-RIe+K-10 zu!t13XbBeKec$f)w=cd}1K*|Qi)4V!RD^4FGyU-LVO<vy*|wd5yrlbfFJ;^JZCO^3 zs2T`~oycEaR&GR>772(5fNQO_mXvZR9fs-O_j@ckxApepAOHD}fBZlE{kOkK%i3mO zn?-yLERTQm3I;X3zBYTW{DFQV`Wt}K%WHB-s$PxbAmnkn_>_~C^vnF88XDWr$BX|N z=W@Q<)**AgeQOTgjKdsv(b^z-A~yO1r!e(wzUGKxT9%?4XBwZ*1jthra#$4~;@%H8 zGRTnZs1QCG_DNCp7}|rKv+et?CNmwM9~Hc#$+kfQTC_eDtlG2wta9w-dX8ZqCfXe% z<=Nq~e%-NY`Lt`FDa4+g*B=&Optp}Y%`5SYs2`l(KQQ2ZzV%eXoRYwFvWYDF$trow zme{5S_=luc|G~+Z>e=1*i`#9`W}NnWNP$Ne%KL@;$P-QN132C3Il4x0zP2Ybr>J5L zZ9!(wKTcNdxT(vH%#PR7fZwdOIyDc+>{OjVA2RB0dHW*rVz?Z?oz*>7=Re5D8x3FQ zJ8&XuNM&XrmTC@3nKQ%ylwColT7+K+GPphi;5xKnnNzG6(L}>NuWIUM0X_=d7mOr$ zK&}R3R$NahY8L7VDKFe#WrV(O)#{EQ-E!xFwpCSTwnmQ(RdXuN1fy2cG>fP#s@Nc? zs%l|jW(s_DYc%a`!(FFv%r3a~WyRW@thJ(%M+LOaf@!k4k@e<MfWbzUdQ(b-!3416 zv@B^^BqcC}#Mz@rXr`s?(Z=MaZaR3&<3`%B7_7-3cu$4X=$|4WQUmUUPz3f^&?P9R zzzlfsjK))Aj>@WZvjFBu7BnOsc?)0neeaF9kXC4SYwKn!tC}eequnGz16m)H(^1=q zFk5Tn5wtet-bi_bCW12$NHRov!U7N$5UVyAcIX>X@80c634_C2O;sBB(<52nbiC^w zfC&MIax-SxfX3^_PGnlO*9k-fHPDD5;{t}XltDD6b$|$SYY!7i!YRm~8?>7slDhBG zOx&5`ej>$tVriZ&PshLbY*CM2gg<YMkO&VuU)-nD3A<<Zn6Dp*nD>A)gL&cUSLX%g zge!dd`-^Jb<Ng1sBH<re0X}YQl+>GF%M$|1I>dZ*+DPAV;y^nnolc;pN%3zYgNZio zqc&@FkcEr{Hc^B_p(ApL@{O4>-^fU^jz0#WC3>A|+-4L2n^Fs*C3}2aOlxGS(@7o# zIU4}7(>OcTQrDLo|1QK>KnEe45ru@T)ml?p8O0u|<H0`=YP$Qr<wY3MxI-Y({NM8q zt&PDVHU<+2BxV~`bI)m6s`;<K`85kKOMZKMb;r8qS`XxNSd*{5`YNyd`g-5C-4wUm zi%53!@4kCYiEl3-m(0tu5LsRpBHH(&Rs&6wQWnm#<bUy_ua;$beSHm^7&-wTKYq3E zTd8*u&N%`2{`=qNyap9k6Np>+_4PY5O)19!FUykG8-WN`>%Q-AwQiCG6!iqlOGY*3 z+t6@NDSi3nm+t=h`Woh5tD2IkElUQmo9DEE$W8bCUdmmBnI-3>A;Zf#;@-E{H(hmE zmXVMak-csag{qc)zwc#Jt*@`I49R(YeSLG+s{0pTynOhu)~efnk0?$}nbWc?>n)eE zsg}lTrmkkCZu`FFB{4~?-`{-mP1LT<YD)a^<Cmbk@1<6~-O`em5PLA#ww15H{`wcc z_?!Rh@BWr3ckv;1hvQwY;Qr=#M>`Mh8J;qTePSQnt>fLFsC_&l=b+UX0r2sT92zGW z7Goxm8|=8~=A|z%{_ySdtzS=Lz4mS*dSpl;H!`<M&NM=H^yhfLFmwp?^YY+m8GWSY z8s@G}xl#}PBp(GIx6TDLhlP`MI-=Y#EYsDtVUO#S9<lR-wdBJ9(tGRQxZpXZIMZ$g zZf4fqB_ejhL<jwN)JN;x0XxTnqLVruou5wRE*;!skM{Xzv~$NcD;8en%w+a`j)A3r z`^VgHG<}`L5F>kldB9Ii<2Xk3JhmelMD%O~&Mu6PJjK+Sb)*mce5m76N5*P8@I|!N z`)W?dVc)HypQ^hjm;iP0zsqe5T1Tf2iR|O&k8KolxH}bOp3ltBs83NpPGfetFzZoI z2DPrP>w5j}Lzz&8Cod3>p9HsT0D74vWu#oH<@^FpOva)j38bKG*83E2y&CVGgc02{ zv#^+3v;w(N&I}eO?Quj8l0d<F)sSO-*v$;6wF2g~*5I&+uT(1|n4g2ODek!ylvp4l zYUUKZw4pJJ(YMtwvW{9UkZ~~}5j2`L{_S{}5l{9@1v4{&IWD&m97I$Z>_<*)u5JW3 zvL>Jx6IVD$xgvQHf{?^1ab7rOk)+jBtGU8k=%`wj^uln}qFTWSA>6p6U|cebNX)xT zZgKY{sReB2K_fz=dljL@D6M*7FmtWSnFkm+SW1En1;hmEf|uTdz#fUBb*`R8#fGHP zKsLFmb*vLf3SnL!wGcDYh=|GEp{7x(?&b6LDww&OF*}&2q=TCkb0;!B=PY6bI%e0+ zG`Lu(cO%4d=-zc>M)Eic^2P%cO$d77VAzgitqt-YQ%yO=69L0rhYEwW!qRxnnH=WM z<3mPE$Cw1C*K<qazqcJ8AC6|wJ_1wDY>J_A^k_{+Bu@JIX5-NS^04<wb?@;9ozdX> z)nkv?Fj?H;+_5>)$PkRlHwBWHqyA~O9~1zaDUmb#l;wO3FNfneEjIM%WWST1zy5#% z_0d<g*m!C*e>_5OL%J;O&klb5(C3HIQHV5G11^tz)G20hh-)Th^r*CdwJugFYRi&< z+=c#5z3jn_rn=|l1>kezP#YUFGpmvW_gE~=9YG@1)j0!xjUhwNjF8JQhlqg9&0N*Z zxBJ`gzWwI5E~>R^aiS#I49qgJnA^U6_vx;x!by^-SF-eWzXOz)7ZASx{`+-ZB+=_{ zKLwDOIh9&UDS26g^WgjMKQZ3SO@sqclh(AC-N{NRW(Z>Y4=*2T)or_%qN+yl+sj8Y z3+xJ=DOV%_03ZNKL_t&$fqmciYL;_WFQ$dT4*U4wV-Q~jB4}9_GtyeOeUEtix4-?Z znWfA*=OrcP6dC1OE0M4;Iprn4zV4C|3%RRN2p6+^W#J{S%d!M%Gc&7M+4neODQa%^ zRsmBBLW^iEc5}PkR(B^X!l>06IY(eBOiQuXS2eHq`zsjBl2cl0)>3rME&CW9NAC31 zS6@XhG;?Ccwr%7k<wc0A*1aI5ylvZF3Nya=;>(}?>%ac`M_<3azCol-X7Ew!#FMvj zvQn6)=#w{Rn(*)oxzy=(x%y#~(R2^V!Y3w$1`hD@>NdlDGR@Zp(W8Vo<v_cqi^p9$ z<a<PVem?R!Pk9{pG0`@4avt2*m&I#F?b>;XdMp`5lyZ<oPUCag<`3u2%!`TpCsVDL zd!POVehBIL2xT#K0>5kNuTfk?GV@*d^<wRuP3TkC`wjlSYv*)3M=1W@GGTrC4U+Re zR*HHm#a}m^TYul%@iEgsp?{ygtkhGnV@>Hy=6#<j$35EEXiimMjy{9;p5BhUKhgX= zi!NV&UV3dry>r_zO{C2OyD?Fi(9EX(G~J`Kp}Uq@ns<7btWk9GmI@!oxzuMqb1!2m zPD0a|lZmG{CHf@6A~{LQt`(44scO7&9Q21FXhi)&N3awY+mveUd}iRFy6gdrn^jYC z^3fgIX{%aqY%gwEllo<H@~RbTY9`jnx4_IPo{Kjz$*2cHwMKcFA*7@fNNjZZpH><r zf(0!nZ0OpIF%QXLY8a3JX1AD%TLjq)0HDTtt+kH{MNex`F;g=>5!6{?ayQc80A_*^ z86-g@nuOhaFFQcY5&w5x95W{kQvIF{8P`KjO3=}485gP6bQXhbH2Rp@2!Ml4IJ&GE zaHr5&nz~^@9s#fg*tl2hJxCc^?=FN{BC;L*>3!wuV$>jajmo^LwhSE_&u9#BFnb5} z6oC#s^_HY-3Y%`ET4RC<^Wc<?ZZ|N^3692L9qgn1b>^NYuucH(WL;afMVJ7E3N((l zGHU68essVi@Fz9`2dj1n7k5f7SZFvUQA5*P_7OWUIh&4@ulITEwN?tH13ZNd<1k-% zeDTk#kN1?iPs%t)JpgTzM{_T1cuo)g&}WDP0>|_jyZ6{=GqxvL$n(B_KIsH@J9#)= zCKhMVI8Oifr`vvD1-M}wBJ^!M6EiNZeKL^J(O@{L#245whfG2rqfUU~1AZLKiF9hJ zX_QA1hI*FT=M};MI{MI#y=EuXrt67Md2+4L+z4;e7i2z~+DAXYNCrE5;~hP*TaQ5_ zBC=i#X^iY#YJK_ek>zH3@BX3?@yq~ju7I<U`Jf|4KMR>!EhXoeZ5B#>fJD@)UK&9m z0h|C~ZV6qG0xayrL~d|r_qy%B`Y-?Z-~IPLuBnz%n$CS>Q5~wa6gRIPz(jKQs(L3+ z1Qp4R{gtfNeO*6R(RdI6|6yj;(ttWnL9Muz-4_y0?zNQNw3^ktEX=4yO9^@~&Y4AY z+jgy#(&}WcrZDCPt*K=LJA-O1s+Og?ITO3mR?EIsf{?pbM<Nhzx3$)?tZPb1m>Hy2 ziORNZX3K{UAJ_HfaLE!W12dS`tyF-vvS)XQn5nw4z@w?j-GRNR2y&K?2QXJaN-0F_ zrrWlw8WXEq;zWSEh%mvn?asmow*V%>X0B>(W#6^dY9&_YVj3VAbGN(%0i#Gt?pEtg zP%{U(R$uZeDW?}Wkk{qU|NJLE|LdRshrj(>W@+MpktqQY?7$edS|a=Weg&Vz+|mif zaFo5rz>S}1X2kLCM2<Jt90cN)H6rSj!yv#2o1mvt6VO<KLbjB<kKLJU$lwEFc;JdV za@CKDnPb#5+E<s<)wr9cgKB5Y_E8^(a|r#x(U;_5xH{GYN~8zY*15glQ!If9SAx%i zf+7n|WpuCvH&f&NNwr2tpd*vVTI*d*$o(*+$C`Qx^E&3GMdni{2<9E*liG6@{ZTqQ zY3me+aKr#@8TKn^ou>GKhLNAJzQM{#9K+sDH0i-QDK*b>=nhP=_xR(~czi(~;i%gm zwwim4_iQyexIHgk%Q1zV>{On8PK^0%!_$y*%>0>E`00*xzRmH;JQ-%SA?n8;8RZ^s zwdvaZl`*yhzHv-iJ|BwOMdGYGc>2k_UO&rOkAb{qkuD2;&s`lkth4_xyNs86!D!c- zTk<X!<9%!o^vB@QAPUQao+CSe-L1kJM8(&PPrt~~@O5%#=AWIhCvIm-_HoaRN}2_d z5(lDFecNiU`jHb{of#3W3QIJ1M2Hwmu$mL8yP8=NcvnUgVO2FN+aCIYI`>tEcwcu# z+Vz-eqm^nsR?&;wa`7UfN*0t-U}15pPHt9#@b1F$Ys6ec0c}%vU)Pn~tCr|g5s{WB zZLwI;GDTrC&~U8=7}2Iixs{0H`i{uC4OF0>nOT@Dc)OyitmahR8fWr&(qJaAn%APs zZ85U|6f=VbDM_t6d1W_d04&0_@s$KO3W6M~Njwm4x0^fN@ApuMAm_*qP-A%3u;pe} z>kbf7A|Pc!lVc6KFQ_7x#mJ{KbA+fd4(3{`C0RsrG}{M&K{dQQ0wYBt173UamtaJd zz_r@Q9!2|Du%fUy5rV6=Rwar%wdh!`s*Uz*M887?m@Ojzk>3m=Xa=k`Wdk1MUanfB z)*SWo$nL<|$pI3MoPf4?JQRzXr(z=<XeImrNpqv!0$?6gH!NUgo-}-7O^?u7sDrCJ zEPrGe?XjinVO6rJv^Kr+n5Eayt=2g8l&r*v$-5oKEVMhH)M!ozpG?Q+k;xb7^2>J4 zC!Rh(tKuDPZgaD-PpG|_cW`j&KeNMsf_V6kq62(saha2^J>rivhEIcay_W|rjWK)& z8%OlbOrG?yXmtenDRa=$KkcJ)sp)zJ)2h}zNlcH5&w)KrWS&l-dGFrm)E0<i0h`J< z-rd~hLpaFDs#;2G%B$9$e9){7e=zD{WNy(Jt9nhWH)%U+%&;IZxFbfQRY2iP5ONNr zlY5EfBlLbF#Ve-5X-WB4|MkEAt3Utgo-#Q^QcAfL6^RB3bJtS+_VSeosIf<wQ@!0* zMhXKLSyyJht+y~+NJJoJq?9AH5MgG9THsG=t!&Idbr(q>xHTatA|%NyWX?{M^CFz~ zvYW+0Lh8`p-rhtYf}r2n?wcEgvm_>#T0)OB_!}}a-)`&ut^yGxz%}RxnFJgZ8mrS@ zcS10YMSzH^7S2JfZyG`lOKxr^5TXv-wtZMXtn1oxpWetYa=tN>mZDk-Qme|6lcZ=u zCTIYJ0)`}sz3DUUAg<NiNlRJR8)$HHQYkwjF;hw+oYjgXDP;>u26x-GjafLERyDV; zzy7m-_wWAw|M7SKrx`goUbTn}5nV~g`!&i${neUPMyaQen&I<<<?VP`&gRkw;c5h{ zE!*DX--vz#RyQJ+Xa{J~I625QBm{9Jo}4D|#X!RONxWn>`WMH2gmy<1(L=Z49bYK- zPLU5e;nWpOXYaPjoBMzw4)Ew<xcZ@cRvxD-Ja}k(%?UVyXU7r3p~dR6;-62D@6%|^ zru(u$J}yNATi!*CTgcsA7bl|bc+Ot_v)<*?IAW}z?bf2r#1Ak|6EFnmOoA{1TAw_# z`PlQl%+AM{3}fkS0W+ph{0SM;iH`C8yZUEtk4N-}N$WjX^L+PF5;z}ly7%^37wwo| zzGL|t4(ar0TEStO`KOnupJGPVoqPnG=i78`=r3wpOJ@T4Q^Y&}F`?`_SaLkvXA$EO z7|#UG{rzrP03W#+zv7X7z6KvN<XjkTt%;WveA@AJ<Hzp~w_(1`BL?=t2G<QN5NKfz zF+xTnuca1daWx|6B(6J4+-)lf)>^eS0IRl+O_WlCM57nzn(1Q(xz}29UPQPPi0JFv zCnAzyV{$ce;SMTRCqb6vFjeccPflH}uvSy8XdFxGy_Qw$9wkH;$daSD7O@Zly$a8X z8D6%%=N-t+s;axC6a<sj7f`FEM4zUa*IFpZk(h$uw`v6u3r2%U&&Hd34Y?gthkFgq zq_G|mqRELMW~8S3zH6-{pu}L(vNNErWZKsZyWeZ1L^|NPGAtz_ay3=8m)nPZ--1gy z=$!%V+wNUlx@>Q?)^%On0)y5vFHIMN9fVR!u!=UFA&_~E8g)E7W?7c3H5#WWIL}(4 z$m?jfsHH>}Lm14^ieT<E)!-Xz@)ksHno{s@S-+Ud%p!=v5f%oMr0@{THHb@DgyE(& ztt*(L8{EvuJv#W%))H1%t<|);>GUFn5LZANF(}KZ$z#XmapWVSS2vOwQ3WC}K?ux} z0yxbOg0m1Ao0_VEhRI$|P5ZHY&>c3$$56UN(&MmaqU!pI$-UhQE>AB(r`l^=F5 zaOz!UmL}BC=nWm2;n@^llY@T#=i{0@#X(ni8coU5W5Mkw>S=3#YQAXdLY<88Ay;{} zk@H!eLeu^j%kB^F0q!2hk*k=p6i0z{%AHdOB%`w<;^LZIxWcE!v(3dG10O^1#6#(S zyvI>CCBj>CY!qxm3^4d@#`Od`^s<2U*dBxF@w_~@r#o0@E^F{n`bW<d6KGkNva!}W zx9|78Bm&f&b6ASwVp;`&-QZ3lxy!q?Has&EM&m62JDHhrlb-kJ6=6uzuvbfoUv9T= zzxl@8A_ygNNkQfeZJcKS$c-c?)oMxrr?jNB>|3c?GjcS<)>=dAmKiTEFREH<O)06W zhNK%27&&D#Q!4~Xyrh(gtQ2EL&TV&=NDErCdhmeagE<(d$)Pn`gId+JR!x$@5MfD; z>VXI;r<6pss#&edY;0y~wHDP%L@8x6H`A)Y%f-<G&D^4Kk(6X9r9_+4vMl?)$8U&8 zO;u}9Wd@0&YpV_kGbJ)pNgxL^B!Ri<88~T5OWA9!D#8Gp4vCQ<v_RQ5W?~7k2V#~; z45yS>gb1}-r!EWmN0eHZyvCd<rGB{G{-^)>-+uM=pMCSqw^6ik@2tkB_o!J+%$D?+ z()~A6wc~gJ51Gv)$JFDQ-i8Y8Kb;zhTO2-lvwj4m@t%4F&qKY*hc6IdD(U6P5k6ro zGXwH<0)kKv8jibQKMlzE_2d*E9jA^1wsba1KBQJ`x*4?0_Qf#yY$f{0O$Q<(v?2)x z#PN(rosx#l%wEnhUk^{+9Ag_s?{ak`FL_C3w}5r#XPUT(9#{8%9Va8q&#q?%4b4;T z9N8YyGM6&i(2{*rVjs!VGuG>A8`5b$pHG4j>iqCE`JF8Ole1pJuoI1E2eQtW*kx>~ zbH$z7p4)Mb_u|?@f9YE9`G}F@K3(l-lRmOJ(<}D0@H-WRyLu2G?wOy5V&p953jhv! z<bfB9BOkfu{>dW@Z{$8^NY`BAzFhF|LAzP>$E$tnd(6)3R0(O<IoC|)Lyf24M1?59 zg@`~(P$M%!T5`%OAUVOkf{e5pRS|NAs+BGHa#6j8$R7)*j9T4Pg;R*{sOo0by^3(v zLaqbs)0aPVGo>x78-73&lvNmoj7n8EuK-elnN_V39h*_DmBpP(sa3T$!831Z9W!Uo zY)r&Kfzsq$Y6(SJb28OMq}HlYw{;^ofZ$B79xP4fAQxc?qzoBRCZ`DggL27C0~t$3 z%to$c)kxbka1ZKCLNRA@CoirFt3)75WI{%gpjODq)$3NwYTdV#B5lt^Vn$jUA#)T# z<M{5RY9uXrT&)DgHp-WQBv-9bE*24Hq)aU2#Ad$lg^0AOB);8NW|UG0b-gW7UUpZl zTC0j=MzXGZrMff!|IEEzvn<PT9hNJzx_f5tbM6JeOIUzF!lXb_qD0De1Rdcg|78CI zKls66S`HhG&=bSqkZ6*kMFPaR=j=VxU6q-B$g1k<nb`+dxYrJKkb!&l%yf74M}Dqc zi?8cT?aBh7f8kzKi)}Gq?VGOvSWpLm9RSZ$0)(8@O400AB(bRw*!Q{X=$=P+UCCqg zc4uk~`P>-dPMpXnZ>y?WtGR>_aDACw&9hNqb|)hxB7~9iUd%Ex)u^1AIk|$|jF}}! zszbzz*@#Gu%mkdwlUib4)YxFcBm#oCk!ICRtpvZ1fyudB23OT!{0@B$zyKoy8OR)? zo2oDS$kWjs++cYI-h?K#gcdF37L+g@?2I;(RS{Ti=k+LXrW>zusK~!9zqEtMZfx54 z&ja*zKaJaP<=7-RWW^7?*cb;kV}5hCw*nBq;r1;P;5LiW7%pfpk=j1BGSmay2RGxi zH&@Z?0fTUS1dBWGRBI`FQ>&+T9X}(+xKq^J$AHwvd!`mb)vMfOhP|@6cn>AV__E>g z9K(Fhcs^}8=+kIE+~AIDqQ;cr+qN#tauq50jyIzMS|R~nDq_TMK?vqvvZiU?$`(_m zRPk6`DU|AHiGwS=r_%a6qbB*GK8iHWA3uJ2efcP-nVHu0GEI|{<*a5pP18J|0-75Y z1T#0o>GWjgua^%=()@mk9BkXRm_m`NB%JcLGM6Yn2L(m&WR$X*DQH<sP6_6uYRpMw z`taf7yLZpzD4KJ==3LzUd^-2(kto+O_;fm_DKY5cui+t{o}WM{CFfFtuwj}OkgwY{ z=giDzB%I8!uG^M3)lEc7@sv{J%uVz-coG8kBW^5#BWeR7L9H2NlBHxY%>4EB!b~g( z{Fpm|i5-!{tEwb+w_H?Brzxr8-Mi<nKYTKyd7dS)szoLoBFQBe&6M*Rqzz^c_%x+u zS(w2PRnJ=%k$GOsLe!e)nT2_gNtv}+ar)tp|LK4E&;H=U&wrkCVd56h8FsQFG@=P= z`dWK3y8lO|py9#ZbrXSF`}9^7+9_Y#{AwHY-AzS2vBW!gq?H$2=2me*j{OyA<4-)K zR@|V!J+DQxS=|hb*hs26fx87B2A;hM6Wxj%_xxv^kQ^OA3!uY23|N?+DBf)yMe+b1 zxtDxhDs?lCX?Y-fI|l}O@%8?E`WWp{l<iI$W8T>9c?V<;#_&)Z9zmfUw|qYw)ejU# z_^tD)Q^fUCu<yqml3^c8Eg1Pf#$0GDocF(twdaTWLwAqLeMJGo9)EM!d~<Pz`q5nj zea9%#eJy`n(Kv&1EYT9(&9qk8$pMYncjB#*(o6F9NQ(a58~8wb9Uc*`?2FwoQ~k__ z($(Rt+y5T|p?xiP92|Ft+c`nTTmLYw8dkBFdw4(b+ppd)eEePy5O1mv?Obr&6Lrq^ zp`_(T;Gqc&B1+R~T227DS;=`y0+{BUx6Bf5$Gx&YQDYc3ivqBjFrn%rQm87HQlbGD z=N@uFs@jTfL8ibRqQzl~fSk8pOL5YO0b+~7218o>VliLJ%oe0gTtyZcY9K(|VH%}b zQ_CE4pc?s=Sg=&L&5Bj+*(7G@qoiiRw-u;bcQ-~GCsl1|zE;El;FU*Bn8^{6IWc%f zjhC26`s6J$wj3D_yLkZ1T|08h8uhWoIn>EycGD^l73F&~W8r8(2Z2>Uh*L@cF-x1k z@<8xaPOKzB6;@?6SdyelBx26&DMf!cz-yr}Od?WB2}-ZHmtc4?Qw{4K3{{nuxp`@` zLXcjaa&toE4DY;Fjd3idd6i*m2BMfyGgI>5Wo^?j?%TG7@RC5He&<ersH&R*79_7` z`(TATiAa5a+|AUqNMiE}#A=SnX|Ix_{kK-!P!qEZ<hm278Qhs9Fy|hrGqot1Swa!4 zw$~f8w>CbvV-Qo%HU<rS@REB!_-HFya=VvR_wO~u*TXDvw;!X$>y!;+Ie!5DU_921 zA>+Fr4))61fpO?49L*h$fB3ZpWp8$Tls3Fcn{OQ4+Zo?~%Jv;3z}N@sZoFU*dD|aw zywiKceD6V94t)R7{U!d~c8`1;x7IY+Bb%!4+L<I95B_*QH)nDmeDtjaZS<B{)-F64 z*7oJ)<=xYBN@;CG`}<o!6cd1|xv@dq?aaxIaxSOSY0F!S01YC{Ab4|cwQ^%_jfa4w zO}a%wMMTff&!1i{fBUz8^VN@j$b#3)Wy#Atp8!NcTNM#7m7-=Q0#*C^>yPi>zyIp1 zuhw<FuGiSU{PN4N7p3UeUw=BCo|r{Td3ruG^Ywb2=XqHcA`@}uIi=;}*IOxmIxX|_ zGZ?D6EVG%B!>q9IIh{*UwPNNerPJxOEc4~{^6}$EBq$O6e0~a<rJVD&Zd<-eqAATE zKYm=6r_<>a#(LW})v|5Hoz^wGo5&Qd<$As5T$UxvoJuLnvZR!v<$GGrs(QIx(<JBf zl2V$c>3Y3(F8=fRbUH2T#Z#K!y?aVYzW(?jWCK!~Fu}>T?E=U&rFoh|Yo3T=|IEx_ zGh>H4U9X#noX;T{wGt@s+sv{o)9G{y8Kj&yQ(~6q=l40U>vaQ%IIy|-JcEUbS=N%= z-aS42*MIhBfBBbxSw4J_`dF}s6fjv0veA;j26t+&(yl=3==C`to>+iV#p3S7OUF`F z8_owt*5da15QJx<U`J5j@rR96unHkG`4iq>TTr;hHsM*de4C@#iIl62!ftGDpxtAo zmVnaU_v1(_yp9<8XO!`JK4W)>c<aj#zt9IV8!-XKnasmkHREQFEN4HT`*bdD?0skW z#;D%>_F!or>A2o+P6s3W@O;`@sVC=t-1&`y>+vbtMY--h=%E`weDrV|$)fN1pKqpe z`f2~he!4%RW3Y1kbUYUBe>;MWZ-z+U*5F0!E!;jZV;<Nm1@{#nJi6MS@sfwLy-Prk z7lB$uqZh$%hOr-P51)#g-PY8FU^uMzM&s@Fw<A5rVS8{^xchWq8ryGiWwU*-R~)<F z`y0(pu11iFIb|)mtVEiNZtJ>kSF@6)M5N?<)ILp<7R@D_MVE9}U2ch~mr_KMNL6hG z&}3sPG`H5unK;CBn1IR*94U$K+ELbF$!?&;EPa%gx?~O!$S70=RSTfZ$sOh%e&0+f zfvHL%_95Lk;Xqc4V6g5UN3Vd@YN*Mr&JDZO&@LvTJ!EFxIhZcpW46|<(4NuM(o-}J zSe)U^;_juWuzR49AzCtXWo`o4W4_tEb0?XayRk%`8K@1II&<QhZ+XXZcf2=|sAjHb z>7CCk=WNkA=IGdyYUSCk{9cI|APaysItg<nlqN6b+Oyx-R4t_hN{s?q-MqLndz<KH z!qm($y5Mu1mph0=MC!ONk-2HT=Jn|XVmh}z2F&aZGc%>&8Lgcg7{GmOp#qUbOx3MY zmIQ9xy|QYDBd)NxCRXIW*Iz>O+}+HIP-TH8n3<9hSP14mCYF)ZxAeCK;qDQ2+^gvh zR@(buR0k!+_Ap==Dyn{O4cc=Udn2t_n2~0~`7R!~G2jpPIsW%U_WPswu=ghD=k4%K z<M-yc-Jz5LKu5zld=shR-(>ri32-Z0-rk>4sp8RA#d{xKGN;yMxr-b=A4z<k@B6Li z>_N%Do8v0E_AtPp?yp)k<o4)~bb1H+pKdYw^BpE^UZ!bE!A#)Cu666F1o<{Ib7%P< z4r0M8K&|0EaO$G{c~Hr0@Z;(#8tr2#rKryH{Nclg-})y%e13X<eZ8#f>W(h+69T{Q z-k;vRdv9h%bC{&23un_bPiYRpq1Q|38}mFbL?k?=*}A?T5nZp>d7hr1-_7%+s@rPk z^OKpXs;d)GV5gaR;iS54TRxpmB2%Q$A3l7Dgx1`=<m+{d25d^{dc9VG1a~b?o|oku zg2tg#bUvT!T#b85U|}=8UaxVHr)fT)&%~@&8Z|UMou5)l%rd1#JvX`znx|P+r}+u+ zmzR&1%j@~{{SZ1fw|SmlUS3pnT~`LX)3TgH<!`)&07}t$p55rWUe?uOkR?PZmSuT* ze)1AFo!zl*TR+<XNV}o3LkHHKd0CdYw|Oh3YG$vO3$y(5KmNlXe)awB<F9OcWrA_4 zRGF<bTcs5C*KubJX`tVD^m{~O`x_Jdpv@gsBF8AY?g5vynj)GeMNRLR*p8<sBUo zAV~6|D|29$5X-yrC)yOSA6OlReo`N3@eVzzZKtlH9Wn}Zs8AlKdfu`>H-k5~+v6s% z4<A4HO^iQ{N%9+q#sTEr&%E&q-W%b!b~Uc$Gk)%{uKJU`!*(#j#|hOpT?WX(;%1MW z&3(+#<<1WmaVM@hoUOJP!ftnSpLQOu<fFPRbuV)_z4DuFdy8P_Iz4{cFUWncGGfVE z#^py=m;Jun<^T8$My?frcD(wC`F}V%KA!NgchUFht=ZT+n|_?{?QtX;Ozd`6_TlAw zP?b0?q<?3BIQwk=;c+><h!xau0BO13?)Jep(zAIhAN2EiYa1rZMh-u8;(KP930z7x z(@+7puGgG5z=ITu1>8(}?f!Yl>rkh>>V`R7dC2?<qvx?L=&w&yKvnC#a<Z!X8irBh zMTlQ@j$$K+WhVo1?_ov^K;&i>QfI!k%!s2jtXi0bsy2`hc&nPs241?2hxDeffn_g6 z#RR)qrIOyKh-)^~%WE|XZ67cizoFN$8y02(qxBnm?I3b;Bana?q+nuD&ZQkK;J{W? znL?bnURx0<MFaiBOduV_jauBujKr{DEQ?-lRVp$ff`H8^=u3htArkT!v}R_f5c0Lr zl@nYw4}+!Nq9$r$MMkLex8_df4G+hvIbd351_D(c>^SY{39EVBM72PwllXvpZQazG z@B^@_QdBWh?jR4TDs4nom1WJ%>Xb{c!O=)ka1cxPPSW9Z96F|gyEE#r8n3)%@htC% zEA*!SKI~KT@du+u)dn2o>kf9fh2;0PqIxTIUB*MuM7xJVn>Kw*=KX&AtZ!;?tw+Xd zU<vU-_hI)$51n|o!~Up7FrHFd#W=Erw|4s-Y~LyY?xKYtI%KQpwSoTWx%#9403ZNK zL_t*HU2uWX%N~DPC0lRzdi3<4?=9R6;oJwNV+Ey;E8p(6zQ8eN_=v)#%f0N6@nPfk z9v+ub>GiABcSC-`%}OaEl4{aeTF%-B<&C0mYuark#-|V=1fXup%*C{d$W?#NW`SQq zpiTBQy1SbQsxqH@DJ5^)l+wpfpK{jcFHR{f!C*X;zA#ObYFXDS7(r4v%8nCxN{RUi zAQljju*~y9gl)@E%NYQtlyX*64OCBehi1CvwUiwAtGGDf07T}LDm!Ihr(-QCrBgJD zNkSB~S2|Nls;ngw@$>U@gB2mtb!NV<7Z6EGA{^{iJrpprX_}@f70q$66t?BHWKC&d zt|*|On^LvBWiYWM5WA}xZCj37$uw11xRM5+c38iT67Ps{X1%Vj*Xwnfr)8PDHb5!G z-G#8OTd+6=byiAg+qQY0gE_3qMGyf{t@*r&1b1bc*a%x$fBOet{)>P9`}xCveEH=s zrzD%@%Cdm&0yUT#+dxWHrfbwt9oak+g}|Qq{`Luojoh04B=c^^V`Nl$H>~YNs&8jg zZzhmM61#s0a?&6N9!M9+$x-{!&Vkx)v1n7>Xs!c0l)65!W*`fhiyCgDF<MmEGY^8R zwAa4szbo<PUA8$uD?xXH_2bt@+cnz8o4^{wBK-KBagQwpIu0bYuXkkkeTIFo-goDD zFv16!)?@zLPU&IgajZrU8qtpy(!S5PR6~aY-Ng_GzM{AC{LhrS_iy$RVy$`J9K6>* z>rKJ&nta|>-7V$zs_*%v-^NKpueHKX9{zCr>w|9pgWJEu;2+*N4E1X}vSSSE@Y}~@ z$fyr>+jat6N!$j%@4EvX8wDM}Pt7DCq<8Kw-=hhF@d6IhNy7u<hZ}MK+j}+do9h!( z7<ODp?KBQIrGh~Y(bHZPx;t(a{A?JNYLLkQuuStw(v;02T~RHnC6HNO6%e7OF}oP2 z6n)XqJp`h~S~0^>-qjLgp8%@g>HZWD5EBub23Xo1=B4A2qf8&A{2>FW<c?+)W`&AD z)uA^)t(zB9l|+Dfakpr+#xomiNjntI0kG9pa6O`k6!+Re4KWOMQ+3t$t_BL)tVtoG zmCIU1HcGngd#q2DLy5tlp#Xqop3PLXW~$RPw~x%+R7<G;_6Iv?OoC?wK#~-Rx0w=I zB*0ZzQ8gOQX2b+Z6G%(3eg!HbJ-D_dMRh>c8VhQrYa%xmMuRK&G7~f04a`=e>0Nb? zq6zE{GgmWacPEk1fH2k2K#H;AnlMWfWs0`58<9J+IaNxQdbX9b(#>{~`2j@T$882K zZm((p5!RV2X)$l=)e#(fsR{0$l2MZ^1`teL^<j<#K62fPg|;q4k1A2pDKOCpT^ruJ zKj$E3mZn&7ux)n?0(X=XhcDk0BE3yMd<H<e#}&si-)Az$&d+rqtOoY+Os8=sdH+?9 zK(PPu{#f^L;5W39_noj;v5X!%+8t#0yWhTL2Ux=p5bjQK<V=1LM7>?|^iEmvMlIoX zlo!X}4w^~z^X@e}$Hq8P)r%AR&8|(WCQ4SB<j~=hH|Img=X=~f)40D`2zsIt99Pq{ zsA`lZ>u?J88BA3bnS>KjsTHPOM8w=Y=M4;3(-J&;wG?Lx0tJy{t6?<(Juh6D^eJBN zbzRf6tn2#n^7`cuzIr;pdwKaZO_QmTJBt8F)8wREzNVC-t_mQ8(ao$BEk%h!-#BOp zRkh6X$*ipFW>!wiImxuHIlN@atuP5AQlJh9Mbg+(b!U-jlAK=vbEi;U7ZDLj32Gop z2>ehhcn1uI9OjnN6nqkKtmsjfys_}asSj7j#Im~=ExvI|6=+&C=e#kCI|1E#2D`EY zvTj!`IVEAime*jg?5V~)&+EEIIe<t&2cJDn)4HziUdraAlB#I4waDgry_)L#=l5<! z-6YlYJ_-Q<h>V%%S=21p5hFuhmPJHBFed{QSMyTz^}qSo|3ZKH*MI--^ErWhU{)hn zb5k`V1`IWW44ybu^G1APPUf?@yQ{gnYX?@jSC&%SgG(Qqaa*vrdwciVH{s;O#rR-4 zK`p6=RThjJbaQ|8;A8Fpmq2L0*K4R$XL;*)s)W+sS8*6>R&5yPBfM)t4H^6RN_QCH z&{o}Zqg#cWaU1$tT{~*$M;OV0dReqzkk8oC&OP=htGsn@$Mf0wgzi6l*lg?v?TfV? zfL&|4HW=Ybgt~)r@eriFU!T2hf}5IV7X^6y!+vJRLZ}~&@WUjhC%u89$ABvvSlntd zW`jHUjkkN;T0gxT`tja3Xw{J2oz-Y~{OaSQVQ`E6hZr@G-(Jg}13y~D&fhlvN23FH zP?Fwv3x1<i;ctW!hXuYBS@PQl#haJi`<dT_iTga^+q>;U6JrsizYjRln2#6g*A`6< zH3hBI@0{kDC8;VAH`P`!b16B9g{H(^5;n3&RcEg4-n|lD2Yo#>7XSuFuN#r=0D<Ez zAv&X`wO|_Ko#gH+BD*$BI6kksyVE3Qg{XKf=GN;Fy~Kd8i3o+VU{P`wk!ecG#bH1Q z&ei-S95gdIb|iK@z!6Xd4{`wG1Y|`)*08eXwKi*}8X`!-k$P#g8cel*MCyjtL*&r& ziP{s3FcL>USSi#mnwTA_B4;I!+V>LlrLFNG^UOrPZJR}zxs$R-ie;q}h(<ILkH@wZ z^6XZuj>~#XXiE~QS#%ASn9%DTW|m9#Y$7tHxfj!!LBuJElL<v!)ES#72%i8>lA;VD zRa~<sr2&iwOH{X`7b3zzb>`+G$t@b*rFB-}WR;@2IqxyCY(#6}vu$`tIGnwznkrmt zJ3boJQ8)lauG%QHsFAk`K*5g{9Mt{Q3+OY|%0xwXm!i28vnt4v(j+{IqzdQ@ly-e? z_qTq0k&iEUe|ftZ+~1G4Oj7{0u@^v(p8-yM%ZM}@iU&E%Lo;&s5&9JM1HQn+F^*)t zJH_dP?ek`B;9j|Pb^m!Lzz0gn1D(U6IMKVT`!Ys;#eH|}KgM~sd+*|RKfLjOZ5FG~ z<Lz#~m$c(q=bd(I*liO4=sQG1Beb&fVId*j@Ms}^AlDhr)sGA8#S{b*m|3Q2x?bbR z){a~oDZ#)bGP9&cTNMmmeJ$9wbv~boqVTvwO04b*O>JCT&&}$H22rEcrBcc?Eg*XN z^ir}tKfn9sFMl!3GXd(A+ssU>ziCVZ!4y?TLCkW_A}Fe6xi&D9PSYI2LMd@A0am8s zm`Fj46BB%zrubAudS=+kDVSL#p|X5Yts+;sg<6yZIGV13D|Uw|Mb|fmh<e7JrX+%x z?=Ul9M{BtGwq;dFLO4rvg<)QnBn&2Z<ec4_G_FC_iIg-Vk7-T`%-goL#d5`L5vMel zvb9G5sd8EImJ2gYQ*x*4^#Wj;=D7R8aLGJ@NkjlHC4+gErgO^#b}QD3snqal5o82i z7!l~@)7QWM(;t8R`@eg-{A0?m&yz4}g|+L;M`&T_wBi9Gu+B4X<m!_fIhF8{?iw|B zQ!-+UVVVkh=*h9E`)bf8CGV~4-1Oy<1Fg2J5;y)4kojbNTzQ8F)mTd_Ur!_RX*AV) z=Hq6@UK9RZFsX)WZbXWDO0g3rVxy)h*hAUAS!b9S)2ty=tv|sr1psOfJET*6Fq<(K zt?i%Kkxs1}*_vrXb9gsDmAR}}7mhZn^EdKH?t}f%gCgsLgyf#1;bF?uv6_4|!aWC$ zL-24u<4H!e(^HgQVHj8BH#zwMM?mAi_E8_A@(F#WYJTHQdfaluB{p>P`~gttH`;D4 z@=bcyeaC%wy`S6o(Kmrj^|H0^6yFcdr&VFF)1`c~g*+nMK74xT5Dztu;dXqJwe<U5 zSxFz314fePNASh_wV?lyhp?gjvG$P1hxte;H@>Iz`L4*gkbZn7QncLL8;hW`fM?>Q z4lSf^>$<gO8dS;6olMODA#yV{w-WS1<RTLZo7Nh1oNWl|Zf3RiL>-J~)k>1gvrt9i zXplLznNn}su;gyc6LUx*umEPH>TQa+rq)hHE%Y5ojm*_ci7XBvvlvE|J_cr5TiGH1 zV-<8v!a`MImaM8UL|_$w+B*8l;T?mw*%Smfbt^Hw8(l=E@Db{!)mjN0>`riniKNLK zc`I2~npfe;t(Yspk}z|+zPtj$EQw}S1tfa8k<Es7?z-k_l9VRZQZxe`iEb%MPSGS+ zRUniQqdmiB#^jPDLCn;wh)gL>?$Dy86sM5bbs}g{wF;#ckq86=%;gR@(l(%7N@kjR zMhAA0q$S3_SVRH?wXR!AQ&+(afS#F`=-GH=wjPA1re?0H8xUzN+;v-5<|)8{A$k;k zKP8qFHEw4nvl47o?Iu?0t?0oBOJZ2@3R@tyI#_L1aqrw(V9{WJdq`4~n_HC>stIr{ zQzJyAoxzOc7Cqtkt#wEoIMg;+M7UW?>oU=UA3bI|-@p!!{s?p{g|jnwj?4>u^kQ%A zceJ!`(Oz`RW)E!FJ_K~kXbzeA{pwob7<{ztW6jzsp$Yxkg?yLWccKH_x3SE5Gxk<P z(|X<aNxDvr(?gb~Ci39+426b0xY?7G!=)dYY<6zRdjIxkw4!YeJF0`dJ8|Z5>}~v4 zM}xYxzC=Sy9$Z~)hj^l$LOrX>c?EjCyq-@BCkZfT&)K{01w$?HMF_$1wyHQ;5TRt7 z&&-?xUlQ*)aSODqavOSoyBr{8P6?#ix?xU9IElQzyyR_t|NggBE$4#M90rSET2@Ju z5)tV<Ez>*)1~|+gGfU$0X(^g>j^ZD?TQEf}%V|o<%vHBQmRzsvG|3`Mq#dP{d77sw zZQJ(g)2A=K_#)6#^=hgnk!eb$<aJwBjR@!Sd77tfv!c0ZVK9NtPv<Gkx#UhndA(kR znWZLr;f$tfu@I3Hnx>hEFPB$$=M*&e5aCJ}0Zx*(HH%D}<}?XF+m>lcl}-Yf=h;07 zHudTJG|jV_hui2qXHx~IWm(*dsunG#DmgtrJ(~qXb@*?-TwaNgraVt`5R<&TzRvTq zOjG#IZQG1U7)erej4zi<&URWBW)_(O_nymIieI+PnU~Wt$y~1M)A!!}_HY08-#?#U z|L*UT`^;_5g#+cq!U+sVycKoq$DL7o5Ah<*LE050rS-jXkc(5O&bQVS)!D0nt7Y>6 z5a~pwrshV`0rp_!XxVR_uyP_4OT_~7rtV4=xaA>km|+%^ZB`jin$}oPzsZzLTb0?( zU7g%a%xfxaWKLv8bruTbk@?3N49ZYWu&BH2f>3S8)gWnCStiE_S8|Gr>mciZs}_{A z*Rd;s+b#o$#$dS<=pV|k1Qf86vzxfJ^gh5;3<7m@H)yYP92%s<3ErCbUR`cBv1O#* ziw%dYqt6@jkT2cPiPP~Y9gy0`cddyS<M1`yx}HXM&{s3=vjGt>s#PBmwtIFxmNIYh z<hxq?H^`s9*%n2C-cRmxQ%wPZbdXQv=0M}qTKJ<73-li7v^VSl7(VWoHPxa4KS<*P z(5KOAXiULCez?5HZ3i#d{*bnpfvCX*dQBuw7;=cf(4xJ%6Mq!F^@a3v9*3Xp=#G!O zZSsLbUE}U{+(v|LS38*b4upU6sAE{>UR1Kf-X5-{%AWVfvWBPVcM2e8HD_UPBIjVt z2wKXqKhv_!n4%@k*}VX)rfSCEI{W0Nmdz9l;RI^)UoFCD-*Ivad0O!;+L=Ufmq4tB zMU68zBOq0#Xl7RjgxP=;=qmD@rYcnxWYSRwkEUQJF^NnmJa&}JnbDMuTj<DyN}Ci| zWR3Y}FcP>neVvTeRV^}G1PHdpfv)aa#eo=ztPgH#1a^oOw_?bOlLP~{7Ja>3=Vfxu z?uB9w$X&Gn7M`~h1vKc6JLEe&j20yhZWn7P+{nm8m?_ES^1{LlQZ1?ua0o%c;BZxC zCe;#EX;lY-CBl%PHP)EnihejV6Isq%2!BKip?3?ye!8oZ?)1pQE&NVSsIBPM?P$C) zU?e9si_s(lm>g;i4<CcS90;<Qovy`fk>qa7CFC$d5*byeBvY{7G{82shH!LwYirFx z?jZI$s7<C_h|~f)?(op>4dD_vH$HFcGv5&|vj{0_3#9u=CKeVJ1e-Q$mOiM0H41%d z^myI}E4mWWm`UEf@_W@gEWZ<CLY$o(X!=t1Cw=%)-u6DD(dz~rm2IKsrClMf<~;7r z!JzZ)9g26@!AJ1Bg#cq=aR?!He>CRRyq^zsV(|Z;wr|e@J!E}#3;RCQ4^Zb%x}Qd! z&5O1WH5VnVv~0&vuKG+CB4@8^S2x$u_WMU&aJeRqgGV1ng5wNB?M>QPLF9*p$epaV zN+tT4*4X?6gpf}Mh2hY63@Tcoha<NOiB0Q2JOU1hl4NUy`np}_^F&iXFu_Q5Y9C}Z zg$1ans|co<ik7|J<m}E);tsdOoQ!e<qAIh%Yi?rhRw`DidPM^B<fabwT0Y&Zl=Hk? zUq5~N_^W^N;~#zT<rmky`L<27%rjE*Wl82j&Qm&{&(F;A^78WZv=l3)<Y^-2C6`S# zgl#h;otCGNCOQWRGx6!Pq%`Hcscr;kwv?tM@3w6##m&gn&8_6}@#BY-lBunBQ7y|U zt?M=CoU;l~=kxog^E)KEtm}2#h-{kD^?KdP3Z!K|6WB?g-#wGlJkO=%ZCe4nzJ4Sk zPKy~z-hjL;XVrYUT-D1w%jvX${BpIbz+6-$m6A&~RRbg?(M*(BMBJ^yfv8A9-q?&U zudA6oJw2%vuQG84=H-;s*5#B`Ns8wjCEnzw!VCF&xxNzl)AKp!0z%$OA)2P;x_(qw z$7#)5$SLc#m69d#Jk5(t%u^C7g>udS-1WM?JiR+(Vvv_?Inyjp(=xqe|LP}y@V&qJ z+yC%ae|1viL@ds1VCQO*IWgB#r^jR6xf#9BH1(=>q=!Vrh?;R7N$yrJ6e!_BPG{Qy z4~3~(6@x}+n^STMP+XFfL?klMX!0wulTbuIs0vB$p#U80$PHc41Q^0JJHd&Y&UbxP zos1~PlTL1;W@>8W#3*W8QFkyWH`=z%tbjcjP0h)bRFU0EWlyD|q?+9{8Ui3%32re3 zrDkTXL>{3@DXtoo9o2Z&E4rM`SPAB}m+nqZYFgZjk(pC=_Qqfn$UP4l03sF63^AY7 z1XRe>$w)*N&_u$->>wg`NO(KcRN0PQy>7|FjWLlN@t-}<8Q@QK(quHk){y68bJZFL z?;smn;|L$-ue5qr^rAw~`cT`;Xc<M&xc1!dK|#5BbeCbCvwIWW-4>1Y_5OdIWTgiy z*4)rr>Df2i#>(try89tp^`H^8r|Z2E5drA%wKo&3{kPt~=8XfHjv%I;FXM(H>n3U$ zpN*jzg0WeFy>#Ne#yjk1&+}~`j2hHxe%+PqY3dj-jJxeEnw!?d8yh-!<VL*$jcNRT zw{M)<ZL)nVN!()fTXiN>hKPyS+kivdB#}hS>RyUkhesY*b86D!X2IqdO0zyZSElA3 z(!NFphmjKt5iz1dPgYc`!V%zBOr6=<{UeJ$Z}3G$QURD1uHDy2^T2>`3Vj_nt1^+D zX$53PuJEe7gD5J8-!yl)!C4|OLoFJD;pQ>OT1SO}&<*mY>{0U~B6oEPyq1RolL)uc zX!N9Gi2-wV@<29+9&M(gt_EU8k~C48wrw-lDTTQ+H7_N5)k)?$#Y!H&IGXU}#9@TV z$jvD9Z)++~iOE6(i2}La^>{sqslaiyM56Mmq2;S;%<O6+A}j%(VwPYxb~iwVd8<@W zT;QO-00cx9C;>MP-JcX9+bC)xQ)myhW&moxx=MFL&B(~y5D8~Z76Tw%VPjErH7oAH zhQ)CQt&QNC8OMCKE4fAzSgA+MT#YE$)NFuzMnRhEGs8lVkfBDc6hVYTeyMnEWW=Oz zC)?u+_y?+2+0oZ^2r;aq?=$TUphT5IZ76~{HA}viRv#KJKiZRle4*2;RYvl`dem-k zpT)T2alE%(f$s6q=8x%{57z#^$lHx4b{lqE`|W_K@sHhk4Q94inJevc^|sxWVf;1G z8`tgIZr^POIJPJ)gl~(I1K;HI4QYd>`uO>+-ls~IN4Hd>Z*MoasUxO(ZzJsEQf<a; zENt(ica4vy`BonW^Y#I-U%L=)PkR@T;M&N5yF<-bcwXi-O<D>LPm?y%9@b)*L{cJJ zz4m{iJ{!>_yj)XCZlze}G_jIf4x&7enHmT+qX-8MaRNAnrwO)3Cpw*$e7Su3`0@4S z)A@WZX45jC&&!-RDEXeB&Oj1LfaP3rz7kE-H1#QzZQB5ZOwlw=^R$?$JC(djN=at3 ze7S5f;~FH!IcGSn>l!rC!6!k4)9Kk%w=IJ(O%sT7&LBy`fSBp)>#M^*eE6tl=ksZv z<$BHTF2ccgwXW;wbP8Ri;AAkh(|KX$tX4`cYRm?l0DAw$`!umxS=TEwo}QlOd2Sj- zB8jIoMIBlL3J!O#02?A_;rH*~fBoU5lrqnAO6hXB#8V`R%{oUDwzUuiH?xb#wyhuz zI<%w(@Tc>;oVIn{2+W*R%lUi`8nYOqTISQTEJd@3Oi3mY;RJBdWCBjaGGUrTp^@&D zTrPew_}AC%i+At8_ro9I^!y)x@psS5Btjw-qVS11F^V~pMZ=U?L{b}#vsUaRaHk}x z{Yc?JtM)Qvt&0HyMBfwS%4BBThTJRU+TCHr$=nDKQ_VzCCXdA1jblh3=tqeU5O)4B znsR6g#$3NJ1dz56byos`Hio32pJXQTOil?9AyQX(0x-pFc1#hwkt!LSBmxDlO-KYo zjRBOM2vYe)Y5}{y*kYbMI5u4^K97-OW9LY3*^L`UyqIUR;zY&8YP1sItYT`xezOu4 zC(bHcQMZk7F@Mc|U46ZjUtC^a*3BTC2J3uCZ*FYYD1y2R)89*xf7S?h>;3sEZ*RT! zycAWK=fQYno1k|7H9^3BCcr*4+d*HS|K&}R*^`{_)Hg?sU`GMOIpQE*4W`=rZzqO9 z@t7*oAA5g)K<pn%@*S_hHOWN7F4QK*Fn&MASe<nAu<!#rI<=6?2gNZO*3!Ny<N{b5 z2&Zus!$UGOu5TC8`y156I2^%Fvcu7ji0(eUTm$DDj027brMvSP1IM;Y?}>fiRi`4a zo!C7WtuB|SNn~UH;O12tA21-k>=rnV2qM@?U@0YHDqhSBA?PZC=eZI2*UFHp<!!qX zLf*oI76=5V5|XD;wIp&FxtADm^7^W)=@ykuFq2n#q&5J>ZOFyiAW~cr14^B#v1oq@ z0JY+l87?fQh8Vr!VOGMOj4aA(?rx4Gk(>!TIXtFRqGT8~O|oEL3Y;@|BC0Emi|MYY zkUIi%DD;M$fKi(Z3PC5grW2`V#m%i0E17hIWhVzS(k#oF=VdEO0p+o%4qGY3N!=V# zy9u^O(j;sKRdXT+8JV-Wskh>zSpd1ow3rqa0kNACAV?4^w#Arq)mWmm<t_5LPy;4+ zHLXIs9ycrKUChn3!~+phMplZs8;ISajiaaov4|iuCURSo-<UZ%^lIA1>)3ZLN~>_l z@UZ|GH3A72Wp&yU4y#KJIG9R;mK-;ZfdFoy&Rn7CYFQno@~AvhgI#%}+9c)#W)gM= z88L`KU=ofI=>#IrS`;kYCabGSVNT4*B?~iPW;urHscKF%vspo(DNc|B8t*X-Z|-*m z<ZAQ=;(%S&dqj@dzydW|p-QMROapZpr<PTYWFM{khsWM&@B(N(fPsF0Z%-e*?N9=C z9RD&_$vb7&{YVS%J8v1{K9x4^&6}&oNcs2OZ{J}8+->-9Y5Wb%D{oH&b$RXEqQSUZ z>|{2!<EgqBG#zf)-3~gw(pv@Es)Rc=DdWZj+vy5}`>Kt7RqRmZt4E*g?RU4`*Zmys zQ}i3RI!gI@n{+24Hq*$0=4F1(c~p9+MPO$T2Ym%gB1k-u4uBNF-$1akB>|I?71H*| z#(J1JR^`SuAcujqlEPDeDs#!nl9_(``0-c&_{;ZSe(&o~pCZ1dG({G)<uxS=zQU4A z9n#Di4ej7w>ep6PSG(lArfE`BFD4=^DJr8ybzMzWL>NT#JbQEC@iH#+84N3`rNnfG zJEkc$<At0zBTUmQCgjLDI43D@Ip<Q#q9W_MuGclCv@9nE2OTu=mZlU_H0~uOo|lP0 zs>Pjh&eJs2ZxX2%X3k|L3VC{-m&skzG{u*5(Pf_8X_}|T)o(#A62f}qszxPOz>iw4 zihpV^*N@Y5A}3YNTLJufU768JGlnKN6<pTT7%$B{XSJeO5~h$tC{dkd0Xa%m2(hy? zN<?BX&wP?Ee)ywzU;XGW|Ih#H2Vb0)NfMK=3nK|97{CI9M*^HuipYtY;SIS17Y^o6 zGLM#Np#VUG0dI_y)F}R(oP<o+;Sp~&yepg$U4$GpDIi5<x@xq8*qXc&jL@UqfaicK z2Xw1<4Z7JLOjpEUZfKDj9x;<PR!l?!40ko}g<+EjunKjAp+s?7*uWtvR=Ks>w7&y1 zSv54Z%f=BNGlL1qNr;T4x;kfSB&!Ur_3thru(Lq{Bq@d!YPwU~K4cBSGCPTRc3fC4 zm}&Xqi|_yF`T2YQaDDyr|NZCx+t2^)FMjn=mUBzF+-pU0B*D6|UDgfhz_9RH4>cO$ zO7F=-3Gy?{Ph%I60}^&yZzk*?9j2ikxP<zre)PJxo|BJR?xPFP#RB$Y+3|4SqWxQ) z$esnEb8>n++g@_*gcQ)$kv@RFTlU+#xV;P7XTVDQM=M_ivO45{#VLV+{k}A;b#G<( z{T1HR)En;Smd3Yp=za2dq|pZ84{RM{_S=8k5zFl&#IDd7Jj-&$001BWNkl<Zf84<> ztlV+hhq0w0obo<M`^G{JWrg9>9W~Gh6Dvtxy@qWeL;HprqB2ke&K=plOK4V11bS@K z0PUftipU&-slJA;fJ2NXVTTtg#Ku*52u-ZC5{rS{y|`&~_<}<u3U*eMGz&RcfY8(_ z%<PoOHBwyFOmHS^V<eIM);1Z{k|S4b9yo*;U}s{uXN&NO1<vjhIg=Ge)TY^sX;EiL zqDYqDj=+?5eh7`h&S>blo7T#Iop3RhIizCMiaRlJz*^BRtdp6Wpkn)o;U>{fRWoxC zCJq}2CQ>J@2Zy=2<xJ%Y-=Y8{DPfw36C|Ccv@EA>+loRs2~#e?iK#+HW^M`=a(C*3 zR3LKmLT2tU$mZ*s$$**Np(T@L@)QKuuC*ae<Ws6R<ajK(CYeZ*7^JE&Wr&vG0Im6} zaBa)0x_hByAvF^AvyoS8eR3!o*X<rqaVKV&XD^LS5|L6{(<{-+sohG>@otq|A`+;x z<PffvkwWB*$|6FBKoAg<@Kn@Yi9sCW*iM#9MIDoe7?S&BS_IDI=-@IW;zR-y6HAOL zWX%=ODQ<zH(uheauUq8dfdB|_gqL77CugDrNG+Y#HarofK`k#pWKJCy>^J5DWH*h_ z(Y7?-$~`Y&+TpG?G!D6IHSL$UZ6kFN)w88Wp>p7@XhgFEqPEsR^-!n8u!<3=Tm4lX zr|MP6j;^UwTJ3AK>aknV4h`#u&WQv#1`^(D0l&7t_?v9sO#)nB=EJ2Q;($@}sy`R| zbHn@Hze5PbYX)u{6&Up2@u=#2cWQ&{>JvEJJoFe1945KFn%y4Y*XFI0WB0_(O~%Bq zW53^@xm9~9y*`nBh3zsT=giYI&Gzz$eFl-N^n|lH%F(=aq;JAwKfyljRNj?#n zz{N<~KnQ`Iq(T+JRJ~~^4FtPlu-k#ix4cb77_?qqKK$b^fATxO^SA%u?}8bz6oZ)w z1TJYRC5P>bf*&)R1yO!+UrNb2XAxPJWuB9hPSa9K2pUsLvcl6eX=4#!7IIE0t?L@P zyY4PBg%AQYZ>B|a(KIiC5n>T5wyk-Z79uMp2YG|4ma-*D%e>4}BBE)Ug1XQw#51_k z+Y7rRZ+Y8Zmt{%D?xZC`5DWcY1XD-N=R^L%+(jg<>$;p4ax!BxUDpi^ax|?%Q&nam zVmH@fsz$yN8JJXESW-$AB5Mkgob`HHB?)ku<~in7m?c=OV+m2h+_vp{T|w*$g_e>5 zY?ezdMNNcfnVH311svUbN8+e=NLn4|@Bj8!KmFNX{G0#v?_bvE(>x0$cw#U?V9YE~ zzyL5@a`ZQL^pJVWORGeIk$W^r*_orN9I+5JKpH?!f@l=)uSob^0y7*~iNGw;knM70 zfQy6oVZutVLA|Mp{w7EMJ0t*5M*$cZt$9QW1n+I?_VuBn%9K#quuD_PlG@EhCWI^* z58B>To4wuyj-zr=wb1IE8Icf7q;XeMG*<+~z=oQkRo#(p*1#k@QDrdzDjz9>7{U%0 z_>7b!U5Q_0e)prF{^Sq;^e4af$M2rLfAQ^K{i{EIKK~E@<Nx$Oe|=dwO|^LwLq~qc z0^L~^I+PuJ(0r!5Jfh!>J&zhK<O7`3;g_96kcRom-V?56&>m9QLAe)?&!&AA4}*4h z&{~=|v#)n+=^2{$a%wNJd?!U}-lLx}y{yeTy92O|-{|Fu;R_wHR*`0JU5(xb?<=|Q z>K_NX9&Fvu4q?_K1>;@23peoNeYJ0tMSOVn9+u1d;XVs7@X@V*ej%SdpPTN@<Asd- zyg$kfH_WgQx+z7CkxWo6>_gEEae@{tS&6i>69pMZN=ZZ*$aw>7o=#3$ijw;@i#uyB zfXgIqV2%j_5kVB@DiwqUY?X7)W@@J7#w=;7(+ZWHQbc4an%y<VVML^q+P`D7TKsDd zX5<P%V$94bD0a0_lfdm{OPp8|SGFtX&YWnClVMJYh>SEaL~t)<BO^w5pdf6P%79dZ zE{pzgmFSBG0a(BcCTCYyN6eLU022WOPV-V!+4MY5%d*V#TuKoM!N*{b4z7wqW)Us8 zbIG|8M~gM`31Jb2ySf*K>}?i=lLG@WJ_DwdQVg{Q`9(P8+QmUk%|YZ8+*17lmQq*{ zd3z!$g{LX-;aOEdG))r`t5SqI!2=qqOVOH-G%~c8gAyeIkE-G9OwLt1r3tCD?0^_# zZj2xq4Ho6ds2L=o)DeDP&9s=Z6A4S}J=;#-LAB=`@hTJ8scIKi(g*>#&J}izs5{_E z^_Zqss1Q-~a8c1`<Ys{!7$xOHavP`uRt-Qw?!7FFS_^w%g8B^6L!)<Nia)dUIOmc6 zPW{SFz3(kW_uip=%Qd{EWz(~;w=@n%XY`qE>|(yPeG{4V-*Eeu3GjYGF{JSz`>pkm z5n{C8y6#Z#6oy8rO!r~328S#5`3u*4#yCvX4m5!HcULzOqc_dRI+)Uc1$}9qnxX!} z$vdjyMmXVk#cr<8Q15SJCwbdam2CCaCutY35sTCSj4-8X)$1Pb)yNWRu1*ATN+lY2 z9Dr0dg2!m2Fj_oI?(Q0f1|B11l((y%M0hIO_VV?INq9<9)J!$!Vr0{lcp_9G91HvA zZeimBd)z4Fqljh9n5Kl5&J3apK3t|i!Jw29e3C)okh2kOs9}|v6{BEXa3U9SBEGKc z(gtHxTe;eOny2&m%z&!S^E}V<wr$tz6@;fVz#Mu#rP!8N({Rbu5dmF`sEY%;+cYJP z$rK~iVy0S3ciY>xfsrJ2J`!f0rWDePX4HhEDBNvmHMs}(wF1anxn9?4PT{;;135wp z4KGDa;ox$)OzAXDGjp_ed|lU2laD<U5fLY0_Y#@bmN#a}Mz)#EPe1ta@4WxvkN)nj z{#`*n2^Pi_9tM;IU;`P0fq=B#^t*f)@My%Fp$EvsZ1usdf<qBfA$qP<6WLmBLan3_ zgGo4p0F)?FptqMoiK4#A4umVJDG&$=R4;pFc8t<#n*`=afFlfQIdzc#Tkkknz~rQs zr{Y~y;i$tmeM|3##R%HF(j%gT0dBZaMob_F<P8=Ft=)-;9jFbtCT51OaE-~^PUzjG z)R}U#Rjsbe5+M*l30fc`%SVI!*7?8q>F@sGzy6c&ef2xE@t2(c`~U9G{_!7v@z?+N z-~5}u__rba;1$M?hfa0B-G>I?p+7t#JqHsvHYayqa3||<d&HKKwi5W~DxPoWGefo* zrM?<odVt#M6Wd6{@6LSu=RQf**7Dutz2gD7##;y83I}#-657#5V@m;z@%WxId6;LW zW9NJvV~(HiMWwgag`sJAzkp~{r?}2OJe%zr4$TE0a$4%(<WBCw)S*#z37s|bSW@XI zt?`t+Uxc^gus0Xd*TQZ5xL=>~Q>(R@eJr`1&v5VdXMRsvqthb8(nhrTjkeYey}S|{ z9Ni6MY9VYhAx)CN#6?T^TxJHNl+7G-I@ip>v}geVjGPM*5u0l<Q+IAX^SWEGfY^*w zD+ggPM4DO<PdeqM`x+=vDw-><&A=p8SJJtuHlUOoARBcG{~kG22>bwnpgHh(F|#Cz z9;$;HkBl^@<89OvM1h(%H%dtaT=EuuP9SC<5bB9lEGi(YZVu}L@zo+&F;i35;^a&a z@FW1a6?KZ<gZr{9CUU)ABa>9svTdpkq<G*Z)m#z4yet-7MW%U4?kQV#Ezy8xp2(?` z9BMsDAi`!|w34}ydSH>_4!avOrAgW_YUTUR`4Zif&aJ>q3?_zfB4VPlt+}^hf=oNA z^j!@r>L$V3Lr(6x=5^GOj=Y-4r)dJF;Al+AqaMvH?oca%i*_#rabmR+<J7fi;uP|n zaq=zpWB1ydsT$4>N=(HXepHwlGRriPsjI?`0Vi-0h(O?EC1(+FtK6h<@l-oY33cjn z0+@-}nVk)-uwu0dM+Ei?b*5nG)CvfX^R90>*GZh+_>5x_Z@luIP_Pfg;s)aS&^~?U z3!N-*+W)Xqcyz0)$GYbLw(4%zo6PE7kM6WsJp6pL!$Q#Jk9;qkKPakFTmGA?9Blr7 zW(hD3i|;p^+Fx#xUK&60hGV=7gS@-3p&K40pcpsV#Vv;)4v+vE)7tSA-gM^!41M=A zXr{N$@U)<3RCRB$9o;OpkJR5?gx+7cnIPH|et=6UMKf1ME|;UG<F2Y{N{-Vk+iDG9 zVcsxuZe&^u<*J@i9oq3=(;)&u6=1l-RmoN`TL49(cm~??s$1ejmi_h9$B)1I$M^4_ ze({T6t*bLjO2RDLwk9dlGy{nUp;@=CTghdb(rG!J&gau<(V|5a@KRJHT`m`fOw(*; zudlDs^~^c9e3+K`l+qHWcAn?ubXu?LG>Mr*;N+z!gwIbWEhTST&?<_g>-DviZJsA5 zFC|Cv94bm+STS?kw(WdA5m6~Q28q>ZI&pX}hMb;e5t-+C7kp#uroWV8hG}ZVOoW_m zU9ZcsTrL-Gse9!WmY~b$u(N4Os;0$h0uiPusg^WJ$U-&|JicCEiORZOUoWpyk$Fz4 z8rLUG_Vv1!l0$(YaNRktMB6mY!onOih>aPc0u>Jrvk<uG77ienby-fu{F3vW<ovy_ ze)Ri)`0xJeuQ|J!yCB#zq$;#A8hr)Az;&zy5yK!teddfS(OpDF@Bredx6*56)T%F5 z-EBl2AOMwXQJ{y~ZF5IxgTEbnQ-hy6(*}^6X;64H1?}jy0<gdp*MGJUtBna)C6DkR zB7q#M@Yf&|jgEG!gmp|w>_6IGu%>ogyW-{nGpIe<HqQgE<S*n*RsYb`%*{cbgqXk; zHpz*Tx9(M3E&+#*Wu>!mFa#dZNOt&@AmEQifAo7l`@KK;(=UJY<Cl*Yz4}x>p62CG z|LAA`?SJ(r|Hse&0<IN2>fJhxwrk8hM{(VwCG8~)8!g_LSdMki!%rVsOK$`Xts3cf z9`pfzbv*LD9>FnV@0#!rwlPUN{=MfmxW5$N(n)hola7t(Hn`keZD(o57-ofkYWZ^& z$nK*rgAiBUDOw`k(@r1Cs5dTbT;S;Ck5{HwoV{J%L+=+&wR@*X9XxfP;vLfXTi-n* zmhV&aacKFQT<zW%(Yud)Ki00{VJ*fP&&Qge*Zt0M_~%WW6SzUY$=h3RhlX0f?GLRY z#(lpQEGeL2QQ-}5Sdlmy3`tBx!pX!UsSAE)kt%fTuI9v?YJkHOY7Q`nFer+)mZpSW z`|E}i<Ypj95;W5Bz?;IvT>%MIh!FLuT+CcE+wf>ru(uj96x#!>3Zcqs(T!$-lWHU( z<Q6{{GYt;u7C?f?OUY3Ph~iu+TCHcL=&I?DNBYSQM-V{8)gF2Li8xYju))m1s=BV% z*ULptCo`Mp*;L(v?~BNk;3<iq1`jQ(WT(J>)4Jv8ouKtfLweYql8^|@imDSa3*4xv zq7oEWcM}ZEaeu3BaZ&e;ISEU2KqLS69hgJ`nKm`5?O8Y5RD+FjmxK<?TGS?rR)xa2 zCaSsDO6vpWAs{3%o)-2BATY;}b9gs*Y9!dv(^cAG=^_jkiE%kCrZLu6s}_WmxZ4nR z14~L!b<Qzg?nFoe7Gh$ed7c3Ty-N68RW}VzZ)%lsGP6d`V-y)U)k1hf9@iRuRFuq| z8C*F%dJ#eP_xJefA1Zyd(%f^0(I2(KS+{!_jNqZV+(u(ykL@t(YFY&uL!0+5O*{0f zyB$U~dV8U8w0oVgijKSO$7;5*e{>W-KK`&*Iqw!yc|E?7LH|$PzQY+{uT@DO{ZPBd z4|)Qvj`}!!sqbk^lDiW>+`_w#!OhLMxy>^E_IR*%d#KlGVuFYVu945gNxu$owV&IF zVS9W&F>fOx%Q8>%thwuaR==)p98}a+Y}3;`&*Y(8XO)L8hB3(Vg+-E^s<C+EHQ@wy zXVv0r1Oq$BTos;#1a*kYnJ|$<3oyYfua{r`;vfF$Pk(pau9r0z-I!=OEug6s2Rx-p zC-D6I9Huis)M`3SiyLk0rmFLj+-+U2UwrZ9^YgoDT5`_Ywh_^?ER`dQ<#alqPN(Ix ztn0Ou0`g^<ayBBI&hxxXRmei*db#AB1E2i$$FH}%Ez6uHu_mYf^z`(rU;XOSr%!p# zFkG%L%d)8El;qvJXCkcY_H=&t?#p*9oO3R@lv37peR+8aO!D=5Rog^na!M(=(U!Mu zqxbKh&D4x?ww!I5Q})8lk&({xyex|ut?RWEuZnT-k~L>dX#(iw^=l$}PERRGPi41l zODW}2)Hbsc8D#*TtFb09%lr4I>w0~?ygWZYiOBQwS=CjyBvVRD)Gkk_rIhme`Wm6e z>2xxXI&FCa^YinW7}x9da=l(zrsedrfBC0>{^$P-Q86p(t-l;}Ahn@N9GD|CP*S9M zOyW(y*N9YWDaDk?`#^5TMxX_6-bU!bA+QnbniTY=W*S0#EzYVYg;`p+(R*L74iHxd z9SolpLDf}2;-#)q3A9IXKyT$D=GmBHqL&bQ(UIEKa#-N_Di}Ht0Wlr4BRSeuV>^vY zM_>wV4>JmBkoJT4h`H%7GKf*ffQW)X1;>-7(6ngqHv$nfnAk$*&?n}}fTyRQ{Opgu z|AVhCFP}bryl$V?Q~r1Xo)doWCqMq)yLTV11u?yhqoPvJ9_s{Sg!`Y@>l?A7zBd>N zHwOG}J35YzPo^$+{IHdGgI@mZ7Ma!VN=BsjXKeV$>cLIx_5ZVNzx)qVO~3PeZ~b#< z77vYg9QHq!Hty92-?*keQbX_INvmiFH=cC#U~}?&A*(sT+m#Q;y+5D5IoE8+@dLc| zTs>IG&JgB(1vkeUyZz(yd~;LAe`2V8NBE34zS)Dqhosi`SD?R!2jZM&MImX9x00Dv zn=TDNPPuGmRknZ}rsnP<sRNoSHMA-bgsTvbFbB6D3&&J&l|&~*HrkV)0YAemyyv%- zI7mZ>j=3@BxyQ_EwBf>vH}=G;Ro5DTd&FEzkRo*&SfN@fVKrCE>r#pcIU9xGk$DV2 zk(m=|31MGHFk%pDXD^1`qlH{6HdV%++CpNMnM7cY##)15-ZoqFwxk&hW+rbU4+Kfc z%|x7uY7$=8;$RX%B)aA<Q7zu_WegxtS9#6-FGl9>l~yWVA@9C`d$Jxl<cdmfDQklz zR-7=iP}PWvx!2lw0Mg#|X)l<nR`ovb2d(Jy;IZ&Vkm>G~d&{dlZ?osoWOim7DWXC% z3(g%cU3t|IjL=@aVRie);5r+F#zhW5m`FMkf_JkAiUI%&6M6Ku<B@N5zuklPSFf?g z0l@*?LJn$=N>FXYiFs8?sxQJ$8GT<V+wJ3nVb5-KK4*1rbKssc-<1NJeegqp_7;i@ z?z!%RJPbGgJ6xjO;Xbfk4;!MtZu2n(yID)D!{5rDzs>gTA<$eWrw2}{*0a7R0qdI* zX(Kc{e!7<-dg@PY&tnMn@LI$dnnZ^Wa5Cy`{R7^ZcC<6<iB;A2)@35>;$3w6poA>P zqj;zjL}O4p?6-Ch2zj&+b5qSo(`h+<T3>1^&}IX6`gP0Z?yRR&6_>a=;EIx-5@aGL z+Om4NhOTgzl45IxWO56N11Y2lZ6wK=UA3%h;)$8Jb^U+-?r;C#U;g3w`CQ=SP_oN< zc{)E$)9G|Ni6k?1^4HhPJkPnPS#g&w<I~5>>HL(YWjO^KzAdMdD}DIzaz5$1_s>sH zPnXN3l*0cnZEw~jNphqI>S6945qVTqHvkSW0}f?K$}UOazu$f36JPm2imb?TWo5Zb z8E^)e0lKRzGb6&yRFw~^YHo34p?A=5X`rey<M2~WkMD518Y4429?xnGKw7Koc~ygN zK7CuJS*)(@Y+!^1O+~e~wyx{(czk<%Gi|j^ld?NQ)LQ@Whd;E|_WS+A;bGzlK&P2^ zyLnk=Gdvy7>w4br_UGeS0aV1mfjuxy(>%}fG!x<5@rPxZ5zB5llrq(|uI>Ez_-rP1 z6(%iIODX&P-V5NUVTfK|POgGzpoAn+=VhMf$+HT;$;^ncl*wfq5%G9DB4TT6leH8q zrTFZ(&z6tJw`F;#wK3D-uzz?s_}X_qRYVlk(@{F}$4NWh=sum#T0?Xaq&7iWg}ChZ zyILCn{o+@D`OVM&+2_Ce?-Oc>L?I9(ad_e-nJRPGBwi935k*@)=3|bH*WM8|NNR0Y zZ}3T{mzJo2=zV{Ug&Gx$q8fzail;{&9w>CP{6TdZcq&BsLKM$(&jsTJ2z`93$w-b_ zl&Lm1mUJeqI`A5N9*cy|gaZiuQ3v09m7BQI&Yy_qJJJH5Fr%gwlRCxM%=rjPIF`<v z=1_(_1cXAYHU>s#hgsMm2E5NZ@jgbU9Z∋n)B2!*1Hi@qGOLb^UTWeSWF+2jcmx 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­k1hk! zpC2oO#-(CCzQ$C?EYgq{P;10uZIn$teL-G88=siPS}Pks6KTNA6~WM@4S<1N5t#vm z!MZ?O(q#mUs#_#|HUVzFvxlSK2j0lfihj3C_I3np8;Q>zS|0v%bLn{=N%GEdeVb{- z40)f;!J}Z+58)t-6rf-v_r<;t<0mdB+#wkUp|9CK^MYhJf)50&u0CQr;;?~NV@<or zSgVmNDDJT`x!KfXcRNXF5}-(kK!VV?YOoz%L<DmptueSx3dAL;d1R>|+8^d{?g-ee zoC5$<O0N)l!qQ!*{-<>x3oC6G7#liURIFX@#z_?qOuOaVqUGk(>8>tEkcKFY8zN9a zu%-eLok_ssLXh5#WcMt6bYA@=KJLWPn;cw!i2z3NogsSQ&mpCLOmL?wn{=xi$Mpsc z^ZqH<32~Tc<7Tqe;MGL^4M7(q!^qBWclMjYv^E8<#1ayyk%%eC_SitD3F0{WMp2ca zFX<DuPYi%%bj?>E>DH;F(npV&w$+x`>CJi9F#59>!@dkp51%yNbUs43N)4R0!aQP2 z=2k$HS+}vTeSp|ux&^H~%OcVQr2#T7R`(z%h?5cmP1B5?bhGJe`sPsU3508{wJvZk z_t$q<T81b>6V201W!~*BcKgG;yDYm)n#(*<ndd@9NdQ`77LWo>J#G#{5G|FU7N2gf zKQvxCum^Gu>Fl;jIAscrRq(c9!8rp<-oA0!{C;J0GAB*EulzRCb*|5{y|2}&@qv>j zfe`y<+3eo`iQPdvGxi+xi=MOu0AXq<;$+K%Q}w_#uTv7^OIal;^{t)_p;t+^^dta4 zs}&BRRT@!%hQI=3agzlhsy-tO)f*70od6h`%PJYOCDZZ#Uc29@OsxqsAd!Ukfl$f} zLS>p5@YHykN?mF@fik`j0dP^0j;8&+h_zN^nur>=R;xD5i$JZlR)rC^R!<zVem1=k zka%g?Z8==*-@bkG_19nj{`bHChky9T-~H~N-n@Cc+wWUluCA`$y?gh^|MuVi<zN2% z?YG~)`{DbW+uP+-5oc6>Jfi*KLS&~6t{T`22&X)b0>sgaNoys59z0lkBu12CYeMz6 z9MlmKeTLyIjjvM=>;zq_HG4fMaAN`dEt}t+!NBNQVN~k0xC>?DK`7F{8D(J|dfJGj znHrjasYq+5+N3t(wr{{wq5a|F`Lm}lU%%QPF79g;M1qMl3{FX>an9m6P4Zb+MV}RW z)<cU$-0})yy?S@~mp^Mm@<P!071d4anL`FISL~T?zw_^&4LK5fLLlW7c<)|4#-f1U zz|wyS!Hu5|>#8Imn~w}~CH(@<-plqz{2@fErN#c@Rn~^YNMkULp}-#F-@{|cAc&#s zY%Gd9psZg_jBJw5LpLyGf>Hx0n8Wy+^$#s(HBice*0>q?8H8J7U`A-D0yU~&)Qq=T zpaD0jB%(FpX5nsMt^@wo;#Rsfd%SDr%<Rbje8gLOWU{Qjw(<cW{U)EwGrT<q59{x& za~A0{Z*4s@*i*Q8ZqKoK{`}=9OA_V4;lg5EJMu1kl0ic;zB9-%jX&o2qQ3%#CXPr1 zJD6RNWYgrno|j}59c>iWG<g&XRFDV|XE1_mL<(&vi#Wt8K;9|Rua5u)NY;<TCI%oD zt<E;c2r@uiCBi&>j|^Ftmhv8CoMtaElX5#5@<^$`YU9RITWibGj?1yt3c!R)lFWr< zDzr4E^r`@eg#cKg*;Z-p*@i8EKC2%MvmPL;=04(cJ~Urq*^2cs$ovo`64RMsi##*| zNBghV>o!Wf@(@$50m=E2c+-2|8#zK-eY>wfxRGVJWpQ+{*-nXCy?_8J33l^Ci~}h$ z;hRVHiQ6Xzz$x(n$*mEm1q&`^8`5l22eGckX8v4p_;L361W^*%fP*kG^-)L>L2(_0 zA#k(Ef<aUU$v=y3O!EabN82EpyM2@kEW#M5KZ9rJ8iPW{<)k5iS_(oa3@`yjIw|~7 zl7_$lg<)y}01X;P$)^X?h=?>1Ax*n^4<_)Z+JCBMFVdvd+Mpud-_tEoK`clUmNLys zt~F27G|#(vx0|LJ3hkysWd_(WGZ<D>>tjrSZ8?fm8-)nS4Pi3YY|KQXVUG2sOrGOW z2%=MQ8bUtSgJ7ceMW_>uMZy)FmOVWC<c}J+d&~v{B6^#?Ac;@foXfy;{7~uWMGVkt zC5pl<0hP~P(qPuz^FkGqGq;!fjmFKGvlQUfoFIsPpEf)$EBLFuj#Pbi%@khmmy!6i z^h8L2NFYUqMgSGt2m%Sc=ptwg4{=XPwgg72hLB|&M>{Vd01E($Bek^V+MgsAR6cA+ z<%>>Rpxf&^P)^FmTo)p2%m9J}NCZ$?1tMZ@f(rohNfXcnZ4qv*!kv;-iE?|W^kqYa zMWoh68Kk>AYLcDJ*&XxhRh~b8@$%Kn&wumwi!Z<U@{2FueE#OyvuB6H9ubbm)AjZ3 z|M`FY@%#VuKfnL*<JHy2ySuyl`{VuHaaoufS8fbM(+;s96-PUXD3>@EZ<%Bi5oidd zC|yFv`H!m?03c4|EWi-u6W1O{`Zq44WwuLkADN~|d0ArJ3`9M67LP2jF^<fvNM~x0 z>eV5JxJ$6_f~Gw5KW3$Jsz}ED(>vnal|(SQ1i~taRfq*hSeDz`j#HuC{!pGiq5bC< zPoC`$7xR8!rU?r!3<6DQco8xfRV}#lA%U+WOb+sj$`}C_P;Ck8FTk`{>u*G|(Odbc zIbcS2O&-rFJh+Kz_2I_v%6wEgDHUTku!v`~iY4uM?zFH<T!sSE5bjx4z6(~YXioE% zwFzPUHNlRITkk!Bbk<vB6(!kS_0_CTgmCkYz$F5^yApO)pG+8hgtSWe!NV=vq){YD zv)EJQ)|IZD@xV=tb3m*}Wef-nq-w`6Fgua1XqPWZRU9`ot?4#Uvj$DLNfqG6uz+eN zg@TBnb;|VV02^QOku6hp|7=Y2@IW39k}*w?mAk)<fq!z^oXd|4=Q?|w$1_upXTBcU z@u5imp{h*Y@4<Swbcxq9+fRi9XGFHGrPcxD4JLt#;H-zJOhrZMv^2&nQ}Kutjk~(* zArl7HS#N~2!^>OF&-8qH+`PK>;ARtGZvfKsHi$}BhhRjMOwa%caWe5ImvAm+F4JzB z7*Tk}Qi}3a?)SUr&z{`f-5!tE>MU7i4A2r$Vu2q*XygvBCP9VIr1nIr!>qO`R~)C< z=6&|BnPJhzNZki-EYIlFm`7RLb)^NHb(L4fKpq|K&4*aZ_Hy(z1<LVkaw_g3?#XUS z+;c~4ju8u>7eQM7yhdW5$(X&{Qj`3B+ouJ<oos_vk%qZ+5dd#pyFNb$A^71>QJ;ws zwaXtm3fGddVLrDe8)0qzMms3ZX14vj@7Oad*#Wh0Nq;E`ogdQjz|vqSzXYllyWQ&v zT6FlM7%#7meyk?;fr6xJs2DF!1e^>5xK-hWm4ZQYcq%wUrA$+qCZVE?(`BBfGEGy_ zGSyV5lp+B8i^J*u;&{v4s(TR}(q@T7v_E5?A!?O^9ywmlW|fNI3n2fW)0xRf4oLGV zH<lOazJjJ5H;PUD^f4Cu4<4(8f9y~e=@pN3-?{gL{PjKLSw_DDdIR%nq4nnZz`cT} zZz4N@D<^wp#fE!yu+wCsN8orrRen=id+^4d)Y|5uY(R0q)1Sku#IydC^teJ?VlH`O zK4)7Hp+%=1^RWUFl>*d+h_!NzK!ij^kO3A!Y;HhBHG<L0APwr$kculbDeI$Pb19K% zRqS*Yh=}uU_x$;@SFc`u_Ug0OuV24;{r2U{*H524-yL>kDk5?`9<Oh%|N8EStB+UL z*H_oqH`mv<H#f`e-R-g*mwIZgiU2|(np6>r3PB;K9tjc@z303FNnlEB$gZJNefjLd zyJ30kuLyV1N35g(&*K*9r_FGFAJgcz()c{lwGtlogAGpaWE-lifWEYO|G#QpG60Ao zzV*#|EKbUirY{M(A|G4hr9tC1W4nOU>laV|@gM)=i`Q?j>h$LydEQ?lO{xVYs7gpA zh6yJDcJ^kqoFNFoqa&CfFd`HIw8g$V1M&TBm)9U;c5d6MGW~+Bb5os5sU<5KmG<<V zVRURgn=L>t2kjfL=sYo@53tNQIiCJuU*CtN#L)B}lT^(ceZ$p~90fY>?$j<vrOq~_ z4KkXlsuRX~7B(&yv3Iz24rlMh9M3NOY5V`)-6H^QR3o}&fd(e4D%=)h!*vZK4}lw- ziZ3%XU`~yWn%iEGn}x}&g{@}TPHE5-GE@Z`irQH8?3G(P6__(KF!sPc;I;P8&Vz#< z-+oREd^Y$@FZ@BY)8j$u8Rybn<g;<<*;C|m{ledO*JDeyF#4bmbddF#yE(&ouVQ7E zR$s-@J%|QlUOgpDye6saBmz)%%ppRp&?7p#d^Ck&BEr&{>`;)93X$n7nk2IJ{<WZN zM@-x_!_|wpv+ZoD&PVI_ouV&w23RRXHBl7xPfrK|b88h5Yh~>OY;Cze-nQ0CL1qv! zOn9r68#h)ZTl7xe2yuseie%tVc6u%U6^jS@v(rx#(=x8ctv)_U#7CyUsT9pddmqko z$I`D9b0Vr5W0)SxAoh<|1Lz^Vr1+s3d&ZH{)7V@CWEdtzH?#i6d)+zt->o+=2E;q{ zDw~u32@C5(+b5D>1y6mj!p1-`Eo`sIp+`{q`QXrpFAmOV2Rai>v)34Cr0+YXSaAE! zazKT!dDW7iEPzXOi<aqAi@454)zuEo20;{IwHlU+il!pfMG)(xU{vt4t*%NnP)K84 zE&cVjytpJAE3D8C!QSb_nwFcOYq$Yo0V02bN--#&lWw)j!mKK4+Otfg^wQHbO+-|t zY2M9cngmIz5Y0#hYV}N$b3*F0H+23O&GsB%whLz(iIM}i!VKrH#46$uX6M(*04mL} ztTJk;fYUqBwgD%(Tf7R<J5_w#+QtbUZv-NGA8yv^G}ITFK*$@ISG!A}`F*t(@57Ar zj*%X9ix9i_K;DxA63m&(yT>kN5R~SgNc5VSL;^>KrWd#7(dMIRzjF|>j=V7ZEs4mc z9{>O#07*naRC<IKFE#QA?x49q95WzrBk1JUf`CHU$VE{7*xm}ngiZ^rjj=?D0E3mq zDI#wyWxv~9TwFYT_T<^Kr_Z0geE$5^v*%BrKY#k<>661@zuWERc_%{4X?g$t>iXv9 z<JHxV?|=OM-Mf!hA8&7NkH=H3%q&DxnN%^cpm7mrO12CmUtxp0h3PZp42Uk<17%v; zB1l)6T`%mfMb7i{4;vf9OxgHT&Ltn*XzEt|ctQTrX;M>iNP{<Jl5@amUp|ecmy}6L zOyF7n18&4e7ABxV_@v;={rtN(FaF1W`o|ZqzxdPlH{ag8qp7fnwsQjkSyYV(t}Pj! zU+}I0CVP_az0VOa7=`;?;cwyDiEq%a&0?G;=9y1_{+63{2XnWLFmsAGysm!j5Cb5J z($cL2Bu!%+N`DCjiet2#uBsQzBY78R<dI8x<?i=PZ(kvLSpx)ey**3j7(<VGNLuPe zoDe2Zg?1<)4UibIp#TUmqj|}Z)CmNhNvGOj^--*N$b%M0Ca>&@dm@IT79q{+h$^Cb zn99;1T6&Gh%2ZM#^c4n?23$p|v33|ZTF4ZS3>V!yAX(|7n^%Y;gXWJY+()6bvL#5u zL&0ET3K+ika{}A*oD?}#orhvftBsKFHvE$<@F5ME@w@42Gr<)O_wvZ?cb9KGnqLEs z_u?yK^nC<O0AR4G;mo7~)*A{omz2Yzfs*9h1rNqxj3?zRvf2xGLH;l4GR&~IaNc+X z%=(c66itW~BI)T_-_Su;g)-e3{3jx#YxnvwVo?NakUCSR%^I#frF2jX{!Brs<)noO zhJhD}=tG#<85*GxRc=tA2!aT<V{5GmCuVP^T#m?8h(Y4*x9Y34g*b`T6+>stEC%=Y zZUANkLM%oHt6q|xMfKj4a#~QN`9Wxe1RA_9hg5;b^zWy4s5)6rGlAy^Nu;pTf)eEL zqz{?xQqe2(5<G252HBnwh1&qgofAupnKw$9$O(HJ?4GJ9hlDbQtB+ZvpS%4UGDzZt z;KOhUh%BWw3?O@D);61cg&gr`SF*Foqd1?FzHFDwe((xSZ$=Qu{>E%ir8sU-329{f z4n!GY@I-BtkBA5W1xO>1fM6-Rd5>jMc6VkHY0bpJ6)Q-|UlO+_o<IsWPU-X6t@GF> zK?LZ@wi0WD@lD!7%c|VMELBd+DQ-nWVx)p)o+e~rXy6Y)lHV*_&)#w#!Q?O)VF#<6 zA2xYO8(vE1o0F2JqNIt9fWFR;@6@^d(fL|)0PKHD3`;n-qx<d|Nq8>9;(I;-dW5h+ zehBGdvHvbyQsd|f%6?UI>oAzU*2a+o8x{O><Kmxmdb}G-QYsgtO-}W6{5eQ;3W$qs zdVgIOUSHpD9M}sb5V5rlQw+{_j_d5>ia}9*el!GtrYl|wCbU9>h^i?Tua~HR0u4bB zVJc;}+wJ!I!{K7T-|r8Hi;E{upFMr?;>D}iFF*V2<;$0^pFexEJM3CpZf>qWynp|f z@Ba4Jzy9spzkK)O`}fz^cX!7VGaHWxQ7IFZ!@eMkuLK|>+?T(2kkR+yeDYCePYm0= zrOMo)Gvf-<1Ltw9b{HojqS<h?Z$hlNW;miw+n<+FJYtHP(C`nA+V-?Abw|YCv2o7( znw8P02punC>z^xLcp8vJkh!&1>*>Vx1X7g|t;neqn&;hNw|jY*KHJmVC%ey|T<oR^ zPRmkH)3gUH(HLg(uSCd2O*cjWY=bV`(CpJEgCHp}0pzgb9R6+6UcT;RI<b^aRRdnm zi9P(RZMEZhFF!t%{L58Q8rPZC!H%uqGceAvIACAYh5-rbfI}|3ubX3H=)rqfFR2~M zv-x&6Z`xF#zbm1<<ik-5Cg#eb#8g?)J|!<~y<wcD&zHP3nL;QFu(T$uJbR5>1yB%W zWg~P(C7)$!pc1IU!W!HHFu1g@N*tM?l?Ke!RD8L46k@Py5XPYyCxs^H*ZNSU5w^xA zKm7jlYT%#AzYS+j(5v-PR}tP8f%TJHp430Ji)?>-EWrNBqu?+mdlBZ`;l>kfpM5yJ ziI)NUFJYJqXKv)osaA~bkNkw|;V_Jud<_q~I_sazML_msGY<Nb(K)B9od>&WJqexa z69KUx&VEPWI#1wBX0aP3Yvxfuz*ilDaI98+qZ;RlW;&731nSYqm^pNbjccdV_J*8+ zU^eu=I`%UOtaF`t6v&vPgdPd|ka9?|0N`+_<aAkQa(YcE;^>JRU&kSIv!ho9hf4~4 zhk%?fX28G|*S$|woY0vbshOzdiZe3|tF6S(?ja1rOR$q=ir}ioBTkuuen$^I>%VvV zqyX4MDColy(#z}+@l}u$@VaQr*?NEyhYhDBtyXC-8Su~NN+oAoiTZ{3$kbHEa6KYv z_>ABdyDDd~tHza=7i?yh%fsQ#7hhdGd46?ucYlAkoR-t+*cSEtPC2m)V$Gsjy7Ma_ zfMUYo5pP1T&FPmK_p~J$IHf4d0TSX|5DS0+7iQ~(1cBC?QQK?w`qUO+lj_O#F=Cn? zj0}c4_p*<p-}@8YlH?Aja%OiK-=uXWBhhc@+b70W<;#~D+jbP0J;AMa&Fwm!u1 z540JqZX{yhjc<`V($A0c7%h&@6$#w27kxYrA~f_N4-3);|8Mu(xvBl&tPa&kTT_Sv z*Hrw?nKAVkSVRbzM3_y=E8Ym?<RUudXur%pZ39Ua!M`d)#RIo}#3VPhwL29`b#?M# zg+!&4sZ6Cz3hUqR_b*;PfAi+;>$hKi_1mvM|NQM|uU<WU`gAI#*3-w2AKv}&{WpL4 z?mzu6|MlO#`M3A)f4IKBTIzxTR7%lUmv+0|r7yt1qIDJWMWLxL8ei~-z#?pIxt{kO z&5>vEymKVMp0hGmj4to)M%hpv<^n>B<-!pdX99HJEv}dRdR8m1UW*_M?`Snt(GT4% zIU<k(W3+96K@5t_EZnLHw`Jj_inLanv<0LQ@LXV?Xjh0t<^ofZ1GP(R7lKcSpA;l% zvMj6&zdk)|0I;nyUhhqpy3z#2%$u~{5Tl<eJ5Xo7m~ww1yt#H}^W%TmhWw%}qVCaB z*;XDnQC?mt8I;vX*qjQYIsEK;>Q0zxvw31Pmu=4+JVvSHU#xEMXMl#x{j!1@8qi6M z6GZDu1ln5P(RAm111&HLDDeThL*fM2&Ypm3>r8e<S3Hh>-u{bLHDpz4E0Z$?$$)1N zb-Gmy7KAHv6Kw-lVh<(b=LQ=38qb_KhcLt1s;pjjkS%3+)FazNgY%qAmOt+8Z>}<! z>l~xeIk!E`M3wiqKY9Gk&)o5sd^&QGocqoh4sieGLvv*O&VY&gRc_?*eK!Sm*t+6* zr-yE2b;j)Aaq_O<EG@4&j^^BgtgVm5$AG8!x3gUV+W!+0*$Sh=6NsK<G`dU-#xst8 zn#mVY4vq*KNx>1^PWQ*-a;m}@gdK?ryURF@rZocN;RYet;8!nx7+0wYPB<(qVhg&Q zAk$+u5pP5npz++dJ|91+-m|JIM5|z~F`jwh3eQ=MXOBd4>-g$@8bH$AM>Ke*`)6qh zUb&)@K!rFodu8X)F&p+Yly$r-nZpC&`loH5&H@dV1R9i-6WpZ}9p(M{j_Z%`%uoLB zRatL+C94N}CLn=f9H+3MH+Qdhkq18UgCOEmicVkQ{0V>nP1D7b%jYj&PKPHn&#kt$ zRIZhm`_t)aS=!z0{pomIPD`x|a|K~*O7hH^#&TlZNOAi)c#AMg9H|8w;@U;%{3k@2 zCMu<rNmZzD_D%<6hNTK~6KO0hw>R6sP6;7@dogmGKcFst<=<3y<R@2%e!#%EjHWif z*ub_vl-hXM)AcNZdF|^9aQX8`x$MWYJQCLCc8EtRLaU|MkIsNOL6g7o6Fpj+rT6@0 z=gm}c0hFP!bFl$>Q>d1WsQ?zl$;&RLYsoCkRZs?&!S!Y2i%IibVX6r?ib@HnSPyDM z$PBIZgX>?r-Sqs$^WS{&#g||F_Uo^|{@vHV`~36IUw-!T;;?VbS9hl$et7@wx8MHr zAO85wH-Gv5`*$CH{Nd*AhJ^tqfPE>1h`aq^cR1v7nLr6ZxMSTgW_y1F+nW>%wa$bh zkbr_2&D!_e?6FS5tl;{_j+vLR$anNqN<`7?GsGngS-$a5tBR;@-K*9SVULKAh(ttM zS!%7PrB)U|qOzOki~R++wj59Qx7XTDG!qa?L6`|9<VjjVm=R}?S(aJgQ0Axma+qlm zZgpWKpkmr><Kx8vB)NStTYieO+cr?e%}jAd0LxKEA|r#qf6YZYK@70Bz~wChHstlE zGV+&zi<$RU*bWw2KOA&&+HJS9c_WH~3mWi%R{C?>_FYTPAe<E!iD!5=4Avck8Bqj; z$YB?tU1TVzM2RGVLr&v?pi!)it6}G2@Mj{z#$l&zy)4`WOee)y_qbU(m|0qF+@vum z%at%-^X_0}=41a)n|Zw&ELBOo^sCz9YyUY*pR>O*oG~Bawq{YB$9R&*7wS~lXTERU z0p8f3KFG-e)GUk)SnJRX{W)vtux(i<ACJw_)%MY~{eEKnKC|Q2K17{15rX`ptv{dE zW8j}_A6C7TtB)R<MEU6@ka=3c9td<dq0WQXlVkY7<38t7VX{I_tvY<#UyAgMv7|SG z21zr@TX9Zka_C~$ebRpcB9ZanfXAzSJp?ReKHc42Utizf-?b(RLMEb~Wk%69=7@e> zm$A1%j<IoM987O){cyd-MnHl|RIQ7(aS4jFkUmz2ib?@sngo&4EdT(t7C{1bhF~+r zFvMYJ`loFCh;R-@JFS#sW>*7DLp&>}2Ll9lN>1;F8r{6!il_@v8K|fIiGz@!093DC zvE;Z>V0%5k%J%6j(2r!)()F+3!NV3!w8cC=-+ryFquqYcw1T3bdj^Rs+yIKc?q^Nc zmXA5gOs&Z1`;}@chzeN)UZ$J@1c1hHJk{I#`<wd{oK8AWh^QP6mlqQNKJz?pYjs(U z%js@ePW5!G%Tkxxl+oQ|2eD2!b~qLR0g`q>uq{*&L)=$><*a5At_@p=p}XBs_B`56 z1*s^NF0;<YCLZGG9m(b)0DwpjfMF9HupuKj$oHeMQ2L}@Ek6ih@*vIp!PkG(on3eT zj<lj?3T1<Me0;f%1z;7(DQZ1i?Z^$0`veb7T{PF>ygr4C&HRkzABU2z<fpg!X1^D= zfa_X;LUy@xQm7?WY8fpw20BBzF2K?>2~8bzjy56F({*F3PYK0(o_oWuh%IkTT5UYf zhvzSzzIyfQ&6_uGUcdU{t1n-D_VW4jmzS4Mrg_IrZf|cte*Ex%{PQ2)zkmP!{rl_d ztDC#~`}@=Bw49b@In}1Fs#dv60V*jgoC|i2;MVk<*t#oVC|T?O*|66-zy}>p++Rw6 zrazIk=tB#`a2dU=%Hr7*Qp|;zU%HB61fujOO6mNN<dwu~%`8NHSwfGm0VwbgF~AUo zto$n~H&KQ8WQs2Z%e>z|`|RcA<&%rcC%fHlH_uO=Jo)hBkAMEZ|9JcUZ@XzKNCmh6 z6p#sI1}FdpCITXWf-)1%6U;j*6W+CUY!z@4D5=ZW$w#1vopGJ(0QtOHp&1#^hvoMr zKKI6Kx=zLp=2xH!`Z}+5Fp^EW;nRx1JsX<Mh*Ny!KJ&9)>?-HGU5L+akBn6szqZna zdgM;Cd3^k8&xR<gUt~u*x_KwkZg7VirsTo)sQqGsY*hSSQ1y6y^>avb6O|NHRH8QN zwrU=$_5iCBYn58XLfgKe8D@vnfGGEsN*PrX^W~OF7~Dd#rW+njeEK-gZsSiReR4GQ z@G;@+`#L+cem=1I@iYE?^X2ie_xN{KC;iC~@fTgsFMTYJKLJeN`N=8&P?Pa5+UU_i z^7s};y5pm}Kuh!$(wOC!yqu*g_vr}WxMy3SGb-4Hh*c5=;Bawa=S3tc0C;tEb9Z~! z+Ja!@Kee`uD{iUA+X<%?bb{XMf~)7O|E=Q)4>!=rfk0GXZnH=UBIqhiq;NDu6eJ-U zitEyYMth1_!Uy2h80ZX|efPk4{e)`qcIyzL!N`n1Z@vN2X$Z~_>oeil>f!wSEZ8sG zK9L1FQgo|{2R-d!0nF;IB3+GVB8~yNv-+634+LwbO6eGWCDY=Re-f|n6~CUmU^MsY zxAdN#1Qiz#971zJ6e0u>q=13+WkV}hjd^KJSO835t)a4TAVR@Xuwa>i_D}XuMVg`p zTWzg2ZgsKkwA6*`BFi0vXOB2qo0ERItB3hxS2vmgidbWTbRrUHN+CneQlQsPgu%hX zjIKgH<f1IAfGs_<6%ZyzjIKLs5h;nG9T>XWkc6m-CxClE)ytA&!&@fJw?Wc}C8l|& zf0i?F$GF-7#xl-fi289%MdfMZG;gCz&_ht6F&f{T_mR<VSx-1G`Yn-t_w2x6mGaZu z4C#0^=&qs?g8@3Q6-8|PU@z>4B)Ue!TKe*?Oh`)`fZFl=9s+Y~uvlgQn5JpJyDVj@ zwJysMKz94x<;4>!6EIvpz4)j9;XnTV_y6J9vzHf#%fsPfnkJTZyuZ7>yZz?dcUM<` zy1Kf$xxKx)xxT%<ySux+ySqIekFC|pP3t!Zh03H^o>B-<kVvdM^{lsH677IZOu3F# zGDie(9G2t0)I+F%viB`ooF8~8lHLfa*<mZSiKtvq^sXn1x)Oj*2UjBi4xb!Lrwq+V zqBi+NgO4JPUH#UL1l($?Rg+{0WuE8VJnwe<!(o58nCB<^!-Wd45gAKj*<bFT)OmMM zJ;o3>oB$_~38f$)6q14f1!XFL#5AEyP=zZnmOVouGN_qG=sAC##@Xt@mTa)cS0bY+ zSh*w-UPcd+&TO_;>1b5x4O3*F{@oF;WFs@)nm}?{GEGLn;Z{55JCfm0<0;QYN>S^e z1eR0(M!NLc2po--zMm>(XZo}9=V&*KZpHGVlrFdv(YwZq=03P-*AZr&35tY|u~RCv zWkq?o@=!hDooEj-xCNL+s_F&We<H%bBGL@r3?SU95ms@?i7LUBvtB94*<xU;@d`JP zs=dChPm{pc{elf)iRs;M-XlWZY5NUX-Mf#d-pGA+&k(a6y>N-->AEQ?pEEU4j;PBA z(h}*U>CVo6;Y?`v(2e9|$fHkhZ3%xy#F(3e`;LM9+ICa^<c);e_Q-9Xy}XP{`}sFA zPR%nfB_lfHM$T;KuE*u>2TlSvL`u#BD6)nar15-?n++@;juUt1Tz~edK!w5*_&58m zzBqQD)`}ul+=|7#n;<}g7~}w0?WAH<dy8#v4>amTyB4yZp{OA{oo!#d6tNjRd>h-9 zXF3kIG<-Sw`H~$*_Rwr?5=F~VLsXS5Fr+qAFM4^_+1*HS#Ue_$(WJ8&oun%<0&M_B z$|KirD8Bjct^&MTYqPJEtQU@h9=8ANBPsh^<IA(pT{P(d1?OxWyaUv$qxrkxE_A=s z*wH+xl#F#ojSN2uSR3NzqU~(lSQro|#44H%@~%of14_txDu!bsDrG`bIuex=tWCGN zwB-c#wk@?*ZdF~;*0^%3qO?8TVL}MJ9;$1eG}+aMv&NPNfGpK!BXuG_o7ncJh>(x; zAhwYZ_ZkQ()5;D0eGrgLzpN2gj{vbhRU<7sQ=D{nX@q<APgaph%11<FV`vxUI%L1v zbcFu?N55?iN6lyVZ}xP|<11)hQpO1-EMX?r$fXE(Iv_AjIl;avL;rRE0f*nMvO1cY z?Ympn(<zbyI2p-A^Mp)X#0%+xO-d`l>XHxyiKcmXKw6esnH!ce?RQg|TI0jT<yXJ` z{cpei2N60R>-Rr=yuH1>y87_r`|sbsfB)gb_0`qw&F$^7EG*6R7D$B(=V>CJUIi7M zD`M-45B}ijTE7qHCqrSY@Bxm4ZR0SB>+Xc*UZpcrfSN5k+WGv;k$Xnz)@fMJdP}ER z52Ih9y)sTelR!FQIwy+q<D$W~gku5rXM$RlVpo&WtXn}WrR?_mY2MBI{qEv0@An!5 zPrE(RWht}4xVS0P2pww^qB4aXlIj0aJT;4Cio#lmkZ3AMgp5#uv^Cue>yX(;66OlW zF}51~>sOs*sJ7EYyatZ3hWUFun@&nb<C9pRM{9uaz!iq2q9F#h9m8^laNPrV5FE#I zis<{?w~wQ|5S;ug&g#{1bNC`&JW%)#x{vL%3=N7bXKr)k{z!@uB3_%4;LK;WR5sc5 zC=%@*31oo)g8qT7*=*Te|H&{cO7X+m8C0381DrL6)%K4Hz}yy_NY3XBT%8cBii#RB zL<Ly5YDx*Dfv^I*q7x1w7u&mQERqMwxj^OoYLnNm{tZn7I-n)GM#C<pCAfnlI#Sdw z=qJ!dc}QR|Z~I31pWfuPzV>s#tcT*XM?QW0qikt^a>>>k<MiFLhxNJn*zvY8<to&9 z_^@ZTRkZN<jpTdDBWKh4@e6Kbwe=ls<qMl*nM4QFgzwl7(}tFW^`~LJvIWlJXSb3r zDx_mIq#3FE%XwS-S>Z#5ya<>}W8gTnZX*;#!T{D;zl>5n6A}SQ5RgXZ&BI`GqT-EU zxO{!|k8@MVLl{cW0X8M5WNACe{|aWy<2yGZpoA#QWqH3vf0g5l7f`QBTt&I3y0k_a zM{}BJ@N~c6%2WCOd;3HZtl?kXykchGNo=jDH7H|+)7Zs$f9nQFAJJX+(z8n9RvY_l zaWR;F*l-sxPOqM)tYU}0;)a_VI!5uQxuF86ZEmYE;HwvNQzVu4yM-^JHACg5a)1O1 zumCrKW~}n08fAbq&C`Bg3L*-(0w-=<m$oc*In~qYepya+IdWa3RcV#=oJyyWn3N1o zIS|{V>Yd#$gX{I60OBMnDdXD0TDtaIV2LBzRCTTh@#d303{b|`u2{m}H80KrKY)I1 zhX`K%f^`mMK1}l7hRC9U^WeE)V?R`QNBJy4{*GyK8%ngN_HtEO0*Dy8AfB}`{<<`_ zhJl?gJJrdD3Kn)UW(mV>PIl@Nj&REosy@*I<KXE}tM}q?Y9-aS8@EhqEH#PQQC5*a z@QsFKfnSWZ&Z1d=1xB!RS{(#0_$=H2@3fn)E=%JIcOoo=$RbN!{_w~D{{Q^H-~8~y zhmRkxZ?13e?{AmoL`49BXf9<YqItLTWQ|j7DSM27vSoxb+$$BXP%x~a{&>+}69aaW z+@CeL!9l~7bRnYb5P7z_hZUGU1b-v;-h$#{_yXi>lQe%U1aJf{VsO<${OpumD1vM? zU;~I@z6(SYR8R&gD;`J#pw_d1f{3)6rg`4&4u}2a;qvmylc$G^%Q8(s$kHk=+(cOp z3{+s$B~xtzSW1}-6krBoZ_yGVP@OIUDbNZa;>@@wqCJ&80ti(umKoOmd>?ZHq;}KO zSdnhuYEzwcF*AvAc;~Lf9yqaFVpW<YU37YXY$9p|%S`-zuxIC1bif!!wB}Bj1Pm(V zov0(<BxTA>CC;PPVJxk#EshgoZ-sU93?_tv*Z)V`n=Q$X?AW0IoDn(gU8nV;E4%vt zf0F4@k1}h?`nGP@-WhZ(Jz#W_ku@HkQ&pLf4AMt9hJ^)5lCxDREWHUn1#R}Hv`R~e zEaKce4D_lBXx1+rO@k)yXb=rm^P&pTPNK|Uaegjqw_5H)K8MrR<@onx&&{<6aQqJ- z1y6R<mmZ#~7n!`I0)^^Mv}5jy=?3sLK4&FN)gAf(CUknLFPKzGALO(>;DzjpQsrzq zj1XxQCOwaNuR!~h`zo*ragK0KK};pDJd3^FRaPY_vo>YXA$)gU4TX(b^*RZG-D;5f zYM0ROFZb_i?bOwz@$pYxo<6fGf2Z2r(>_<Y+0)0Kt=#^!OCwC1X!^nizU=1j#EUlJ zMh6e|<s13Sjy(IWyW#TSUr#iOQ~R<b^Xi$r-qVqHdCX>CA{4-RK&X+P5XNDtGH2AS z`ItB}^|aTLWHvRu!C;ug)MIgb+cTDpvWpqT)NtG*L97*U3|=9@uC%VM&#D6|{W-@` zTn<NyT8UU@)0EXbWGxumN}NReJmUEU6u8>#IHVlL=+v=mbrw^Q<q3Omfd133zi0qA zRlO_O=yq=cM7d_mC#gGQvfN82KUjxjaXfR$M`V%jbja~?oIB93nOd}NhA16Y`X#3j zF&%fpQO9`#F_9>Qc$4jBYf}~)WDo&!>O-*;rho=n#KV$#0%F>#2!ui_kv48ciHJV; zncGsv6dB`wzrAjEk?+hRr22R~e(XPgoxlG0{PFYi=jY?+WA3|Z7FuXlr8C>6!60s` zsB+fzh8G)RB8U>8?rs;5GJ!=|jI&yTfFNKGP{mFbF>(z@khJ*+Z-et~rW<m`TsOL% zvd~e#LnHeu!!>SW7MpbFRi(@wsXkV>F`Acz!ewCkC>L&|37PP2a(_!-T}YbN^<6=z zL)|BW2Jp@dnHip!&@+sOK-QC$^SL&I(zaEu=WZdiz&Lm2gV|Q2-DS3GJOBKhGuuL? z;39~`C878+wiDzg6+ns7pZn(zOjVuxgNXK@pa1^jCy~mKUw{1iumAhsS#H~Qzu#ZR z7~B2j_HqYyum&nP#Zm50vyetGwS-OS>K!5gSziq~ZA_JeLk$b}B*)4RT_N1bocU46 zd0*O7@o>soYmKkfQ~P@HRdNa+TF#6xKLT0J#<D|7VnhV)<0kFrF<TUy=A;QCp)q)4 z2rH90q^(d32qebWGbibMD1Ly3$hh5KU*A98KHfjReSG`JFZb6M8Lz|}l=gl8cql&A z$s1X%+H`};dD|5jV;kefG)Pqjv8W0r6AS4W!U6*GzR?hVQF6$2cK`q&07*naRDLDk zh4_VtCx1?J6nluw+=~cvULZ~pRQdKMh8u72a&g;z=@ON;i8N|i+kzkMq&Kp3BHD|8 zyHat{3;X>E8@Rw`OyLc27*EKYgUVLK7O`5IGpg`rt40#@(tgO#Q;xWDk1|JT9p081 zcyx~Ss~?Cah7Kes_GNSb+sYP4jZ}9cAKp9x4zsh>Hk1Y{147Jzem;I~KYyrhtb-KF zbFzX(Z2PbhTfRDxMWL(|xgyZXVFNp#BzO`q6`!8dYsT?Z1;GvA2a$oWc1KPd$aym9 zRP3q`EA|`b6%&+o_c`~YQNv~B;y(s?#WmD204)+CO$=FQ_PD%Gi~v4CMJ>y;_#Ie- zg1gp;HwE3;I4NwWD-I8#?uF;}1z$*+7?odpvWrhYwpTYd0S=#Ejou$txVwnv<6oA? z%KFjsz8t^!^<%&8<{#?FH3IzVv7LYG@S?9;i@xlZ?{&L+9aOrw`^&e)N2e6jSZ_qE z;fp_@RL&O%%YA3?Mn<Mw+YS50ytqtEBFxGXK55U%;L@<xHRC#~U~Nw@3UPCqSN}o| zTc9;n<;62azC~MRXoHq$p`DBSMkxv+IOSC-jc7`XWR=8qQe33M83;=giKW`@?G}ow z4vv0`EkS_aU@8BT*I$G{*LCC&L$e1$k+d6gLDC^t3eH9wzaNg%j)ib&L^+cEKMMtM zKN*_#-%;<N9-pqO%^Xp1MJ8`~K0mmlMdI}<Qr{R-X#z8hbAV^Ow~!dIN_ye!)u-yN zDPu*aIrn|vE5n2)3&!C4>)Y+^-IYIu&iVNK{QUXj$B+NmKR+LzKljJyzCU!%wo7am zGZbJ}3?VOH$`lv|SJQ2P)nkohteB)UiS{I>k4kP%F3%(p7A7wq0jp=62D!%4hnGC{ z!8nM|zMWddmk25<`L1h;A-OKfy!rA9A6TOhdva%f-U+}u+AtT=ff@Vo1Gfcm1_}27 z6i$juzYbqX_)v=u(RpEKUsC93b1m!DWBV2L&6!X4Tx1ny$-Wg|VJC(}iks0?Kw(KW z<95HjyuOPJ<`EGL5N$--S+&Sf*1emvc@qxK@=H~{5t7wV_l(~K0u-xqb+4SS@Jz$- zndDJKZ!$cW`lKN><p$H;Yjgme+E;e=v<-<fqhy_LJtj6l5`&?PA%k}sAeSWjzCZQ} z(6-(0FYh1U{_*YGfByLR{`UUu<^4l$HxL_+^T%W2=YLo{*cO;b8oXw;w93Kh8WG&K zak~whevv^mO(-x}Xb9h!D05YYkO+?<#I)<23Iof~kyW-d+RpVArw_GJ>g{P!vUH+z zszePPcU~e4cl;y1%V-fx*M$Cb4lq))1eOdS^wlfNp~Y3E{)oC?hN{Q9<IkLF@JWQh zzD407{LueaZn26Ov^OoZogv{1!{5<{k$>cvo$O0=geq|+!VU3}M1}?v50Tpoj~AVj zMEN#8AM=0x>%ac{uMd*jO>RQM!+br)9Gg|V&>UvWYPy~VaHRbM#l8a*cmT!uY+hxx zB7&NcUQhpx624Y-ZU=U&Y-HK>NMGTi-g@;k`)J9Ms3mP>Ub-og_F*ciVM?{xicwXf z;2S)xkXU;?`6cI0R{_=5W6$sIIpIfzwHF1nAG%CV%{U+53~Tgz4sAP_Ooxr1quU)r zUl3Au3%U33aP`lxhw|$F^8r+o@@0F{&wgmnv*z*oqAzUkj{5EmyAmKo>&@p$`Jz2h zq3CjKIUUf4X7)SR@E~_PqJ5Hr#F!%Dwm=QpZ%R5t)j4P^$B=uyGK%drQ`aMKRri4- z5@JjQ?qd)7PlPR;#}l`tjM@V0dH^3Mv`)ah^K12{g9rPz?P*!Vw?-2b$W+1HXy>zc z$yCL<>!&#yT51>piexFwC5`E}cauEbzh%<7@&T_p`RA^`7y&+P-G08VKNpSfY)h?0 z`SEP$9F)%4A}5*2X$F~IrHb@Y(S;%_#ln@gb!0iufKcg(;oK|U+F&bZ0<$EntBU|@ z&kpS1Nvy{D!#eE@4#G*PGcX{^PpllZ&?=J(4<d$6b?w<{Cw14Kq(meZ#bS}${pEIh z`S>7^(NyZ(ACLX<`T6;H%>D6re9p%{_el_w3&FfZxyUS&l1YhnN+Trde8)MXe!P;0 z*f>;EYU!Y343~EtV`ynmz8$PHOQp3~Z0o5XDi_l4;pMmt*@BqIBgpxLKwgbT?)j7b zNIq`2P7LGu5FGqs+|F!Q-FhWD>VGn|hFl>C2O(>-+|nH=wfNmtcId?tkoB88f5}tQ zkz~Va-#R&Ap6pOw{RNyz#r~mHbxVA5!9!?J8BiP|(GYhcGH$o+e!tBLRkaC?ntzwf zVA*lF(O5vx^O=3>2$%>R({$3kmek7C)qHfMwUC{4Zf~^bsCi$MHfl?&*AK|k9n7P! z16HF2L{JVyu5CtlqOmaZ5EdH5P6@61{PoALKj%JyvB~ZJ^6~wb_xF#N*SD9~xBLBV zjBOhvV*}Anf;~6r01M0X9kQB4fy+2rjuysbfowyzZ9YEJ?PrwSOe6WyL10e-rZI*R zeX4%W$vpf#Mk-QqY=9K(6q>=O(6;Si9p`CcB-$E-nUm;*aD18<pAqi#CnxWzZ~t=v z$=`Vucm&h|2<gL>_<zcu8Gi~aN%fRl7`)>?GSxF7qoE`*2mZ~7`XijZcwRa(@O*Xo zqiu-nMb@4u<AE*2U2WTlp{MLFA*15&RaGGw_w7Ib*Z=n)|MJV@$AA3%{P9qoP!`cS z1=x+B8BB?{t4Xe$Cab1kdC3UObx0TjCese`OkGDXE32|jQvC#WC}@(xLCOF?lQ3y2 zFbR`X*=i+N-o4i~OtBxNJ7ie10K6AC+;sWWo7Kf^DZasa$mi_P@}i0tkvh*;c|h7@ z?P>PdQ=q`5bdo%s+mn~9Ewn$5whntsntfI9_%4C-6=&L{Tw^m9eAgBNiuiQV_QJUh z0!DNiv_o*^YdiKzO8oX0`(L{*-LS0JM|mHF{P_#Z|B#P;o|G@{?_Ye@&Fss$J!f<J z^hHF8=_AOckAM5b2T8nSgNLAO;>Cj-Y!=sC_;l-}2u-BQ4A?<8m^LDbJRuH%n|(u> zl~}u!MLpTsE4ikUTg$B_DX7gFobmjz4tpA_eNN9ip|77lVqEP(Vn#+Z7qR7YbLINy znCP*-f{QGyPM=W+6I1I5N6BJOSPQh2=c_Pn*_TMG?snoKw)8hx!G9wOR$gcCd-`|m z{^=vmEAhtqz%pFW4sT8xF?0<W;a^Ub^oYkUTxfsAsXs0u7l4Fm-EIa~zN*2aR0u|` zj@nK3V`Rx<!aN)l=&iDH;m-yU9l{0&y-nk^cF3Yv373|U0~lc?u~#x>Xw=LWBI3bJ zL$>?N3*8BCa}oinbMCs&xnq9*cszd2$7A0gbKi~ak|Nr{l(BcB&gYhTXd~Y<(-bIu zG2_6@$a>%waiAf-AKGQ$^ZZsZgY;oZa*$A8OiSi+xSSX2dC_+J&CA}L)QBhMQxG-B ziK{2mv1aGUn_rYO@dMgeR>G=KF38GX#<4l+vVjmlPJw<tllZD5seP7q*arKHAZLSn zxB$&`==ShpFg>%LAS!Z6tK`IiH5C?O)>uW}@(vC-c4QHhX+|EW<Kl_|%t>g}GyYo6 zq)<K_Du=hU*JT9Q>CMxpMrA{G#WI=MJWs~`ZGN2lIyWa#W-R4#D3oRSD6$y{b2sSb zoO9}=A!EC}zP){W{rL9r{p0ohb-Ufh*mw+)!Mw#Q$5d6DU-x7QjK-NEEDqZ&DUh+x z!_u<y&={MH+qOT_qih6R!YU-j&dnlZ&u3;CLzy4I4)R3qqYO_W>XuV;r1ZUZxQa50 znH+Vppt(F<`V<7#(2A1g<Zz1cG73$Bx?FJ=7jkuFvRvQco!zQj0HszU_y`sqtGimd zSj&5Q9-uL%9@|w^%-QV&&Jb-oAjX-`ns-=pgf^9#r{|Gpa-*u!FuWNkN@rDKqWjz1 z?Y8OsQ0NYtIz1r6aU9xtY3)jqDkK(3K_E@YbKF1(PpnlDgxzND7DErh8)UV5k*-r@ zz?KKOAW38w6Ehdvg2Z=BEAQ~&qHN%P+BzIQWHr)#a7hjwi-Zll#;J;(SKew?@%qD> zJbakVWpVap*$qpo7IO0~mZR!Om;9um;a2R9-JW~Y<WZuTvTB`q@#?TUUI+W?5PVzT zxU}z2__?}KaXzLGu2nrX=AsdYAzHtC=w`cZfhK=}GJDn$dNTE2_vNriV&sonMxTyL z>aXUuXbJ)y#FI%5HfWD94GxnlUlbzF$RNdOgg9x;Z5w70f{1K#5XO>lhEFQAo9aRD zd#KQ*HgwfUmTzT8E)F%O)6#3%f^jEz4@LK+aMS1e>T2ggX|{cS<uoHpj5^M{T-fOx zkFj<DY?iN**trMAaRz#v(-4Sv;0YQ2AG`iG2sBal52s(xQOyO-aC%5VTUTabk39Of zmJxA;`m&<Y_fHp)7cqer6F$-zH{&fWvAhvP7{ha4ZHsw2w71o=i8Mk7_C<AQmt`-X zO*_6YHsb66%8HJ3bXy;0Oov8o&u7&chIVF|iipUdAuI@m7nr2;L+4}8$9z2IW7j!# zS}CTVs-LRR-82fSo$HEAVnOS??4j3WjCS2IfOn1;3GwHk(%3(iO4Y`{cso<j<$q&V zLM5-+PbGlYqAzHQT}J-mPc7HjUxDR#h_c^lGIA`!%ZSrq<;3SW!e1LKZ%Ldv0`+k| zs}AnW<T<)*&vK!&H?3z=%h^tU(_w>`A8O$VTUwSJ;e}Ib=7FrX#v<_nOjTDRL8oDC z9jgoz&SD2o_;|axzclO<A9*-l+L?3Oqz9})y$UtmPa2aH%ZJjz6d(o!gO-<bs|~~w z5Eu^km>QPEg2R~evHv8Rs&n6W0=<2F`~HuQeZ2khpZ?P?|MD-l`yHgJG|f(RF=i&| zK%QQ1R0}<4@}OmcIKpUZTKpJeY&UpZ8f{!`ESa54z&yjkV}NA>O2Q(c0MxMetcXym z55>J{o#?JQF!f_;sh1d5^kKeE?h0N6-EmB^uEw(!dvyiOyLy@%GMqa&cmaCs;u2Pn zB%c?Sb0x8tG<)XoieCVUKz6?ulyY5Igp{!J7+q@ip+A*YhkP;zj3tyJj<+%cjEH|i z6%Zl5Z88j5C?lam=x0tQ+4@6Oox~~<es@HAPP?pFn_?nZt#(p%dPjva6hnq$8Z!p5 zf=FNq$rx_cidqmD>Qt*O!{1!$#vm&`M{IcwDO7#Lx|@_KV>^7Dh>NwB(8N>R^=vd& znTFMt?CuQEX<6E%&bCeZbg~FyZ{=}=<>EOku(mhD2jl~lT$}mWUX!Vmw0Z%r5y-`^ z=+8M0EPAgI_7LR<msii2Jzr?|T<QPEpAUn^Pri7mgdZN*?8bHUo-~y&R@(7({5u}o zkeJK2pUq~~3?^I!<ST*YG<xgIhCaxI!91ey&@%PTTon)-4o)9KJo|Yj?#p&hXsW+{ z0!dh{>-j_tal>(2jcwGH<8A~0X6@yLmHO0o+i_ci*&clQQ52OBh_*JB?q0tX;E4b_ z7`m}e%2ll^Ch;<hFVEsLAm5>&TvBEow7-1)bpyCob`ua?2!@pDlLSR2GM&3oE2ae* zW$`nGRkeQaz~tVE)PiQ_N=aSN%ME&z9Ww@+;P2@&QHdcU%&A%klh$l1*~yv@blVls zir!?Y7%uzyVnA|Wx)uhsVm=vGo^3KpcQp|L%sFXJ$8a;Tun04F+_u}x?aq+{49tD* zkH_49)yL2MF&~dP_i3rTI;Zh7Vb0E&v@TW<G^;CzZmKbVY46P#Udtc$d@bkD%Tp#u zJ2kB-fJjo$iA!T-VpaHm6Gc{_fYL=EZS@$M?XcxgBzT<SJ_XI{!Z=J^-wTwYK}s&i zf^JI-nHzIfpu<yoIN17a9msuXPkxtAH(!Rn58pi<X-)J!J0Qa{N_yKS{+V0g5P3TX zKtLxly?h;tt_mFba)lRII+9PYP2F9j-D`I4Na|HzC~#OB!1*5ztMy<enE_mCaeAHO zCeHJ`;X+M*h+5WRxR;2Sc)Yya^z-xA|MPzyKYpEax1$}Z+t_Zm?c?M9-+np*cvqcs z5+|*cJ$xkPS~F5fm>B|ike``6yjHW>f0lxMh>Y89+%~X7pKajTKs0I1TagIs*ceK@ zgOo?qKW?exm0OX7X2+$~X2EAIB&7$94~t~QXk@7ePjBJqV1SaEO?-jX{Bu_`GE;#& z97!E}T<avUFio{u0@N+xIeJUs77Qh(v7R3SBzZ0Q)#n<OJxrYkZfda=B8@MtA}jBw ziUYS{aT>ZfJs6DXN1l<wNgP3OK!jJ5Gt<Vh^E}|o=4K`AM(=D<VK?SrReu#zKvwn0 zD*D=?H+5Q_ItkV*<FWFfGr^09k@IFvOs{@OFls|}WziFZtwR(5u|0eNbXZk&tX&Yp z@cDMswu$J~*LdC4C@71?^Ay_h;;+BhRtuyhH=f$KJSG8IdvuAzPn{}R%6Uo3^k@%y z<%LCuq}(ipLR!%x2Rp5`wm9Jn6xt81#e<7H<#Y9Zt*mz$_3V14C!hZs&AHNb<BJE# z_ZM&J66QA>`8yw5=;G2JlKr^!iFJjaF;>ZIfW8ds+gERI$u~y>7+K6P$Q=-jnrQ$t z*dZJp<&%+2<g#B{9(s)%x9VZf8idqBDKK;)|4+SM6GNzoMUDgBwp+n2nnR&(3#+?N zN*ySd0z4Dtno(8;f7NAQ9>ql%uqbl1U+Zb@2K8OtRMX3-#h<wTk^!ump2ZV73tad; zqQg=PwuvuxH44~69Neu^bir|sF5{R>0a8LUC?7PlnU2vkVjgXVG-la7F;?54S;BRp z&wDjKmYUhk4#c84r&j=rJfVDy72#wr$eGeNiO9pc?4p56Ot(DOh<vTekE69RGq52r z?fr8?0qmc)^=*$c^ESrq{ryee*)x;@(A*!NkI$b!et!P^sr%>t`8gjCRVS>UYY7nH zjGZ<v#7IBrC5tMPKs5$GD216s2D6MYm<FO8g!OjLsTv&JfYRPNmwU-!#bvdYpCNE5 z=;|^WLCLC^E&|KxxVS5<7gwC$oKXlNHo(G)*InLr*j$GPS_7Ke!N~_JN8Zlk73l&s z8mVzE%zim3C(F}ZfLR-$lV%-OX)35E*l<0LgFtSQ=gJ5RiHOLJd7K(>=t$dlZ1qBl zeR}c6=9k(ahcl(pt+Q6g)jQ|<lzw%M2%+GHdzE|g46ZEsbayrz7?Ws(<J8Jr4cpoi zn5vJ5V(L^SK(=vzd;fTUefjwKFaPEL`Tzd)fBujE{@;H6{EsN>Z6>UU@MG?ukGanW zpq_Xm!;2=lt=EG^8nP!G6F6X^dQa+jHkDC?0A=uyZEQD%CZT_nZ!#(cS3Q_in3!n{ zQSf78T2dut9Bf&cTm~UdbC!3uP*oh>Oqn8^Ft*duqO@|^!Pd5zHH)Kiz~`P`e<Txl zQM((afV-M-LLXd2p|9V0{P6HQFP1##*rAPUNyXI-*Il=(M=}lV>SI5$p0%>qHKh2Y z@Y5h77WHfZCWuoyCmJAiP_{~20|nXVh<;m=P$KdoOv<WYRaPb1HfO6-r+_A4=!9Zo zQ+&GhYff^n3~W4Dc4AJl%1Em2=>mava~v7>GlhfQiWVaxHc*CDP^hyY;AI_J66+;= z8OJMkWxJvKQ2MA}PDfL1FI4SZ1<&--XNTir85XKO?b&4!^ZKqY9{aRC9q8AE$*Cjf z@1|rvS@LyrZ3O>oG5=m2UdI7{5+3`?>iqK0e<n!w3<cdz*xz{98LIu;EnS~-I;yWb z(#ckc)*s6z<A&XP%CJi*Fw^LbxNg}mg)Pco>I^!y`~W^H?Y%3Ry*<afpRBHKHzEw# z<;ZgfAg4iacv^cb*K-c-SvJar0M94zv*FBb+&5h#4Q-uRX6*2UGkn;;_J^1D)%BMn z!07cSQXdU>GNmSTX3Vndz@yy;H_OjZ18iWS=RFRBWpiQJkD!Co=;;=WAjWhemJFoY zy5wmGQ`_O~o!qe&Xv@kZpk>NIL31j*ns-piHH_=T*qN7DeS)y8jN?K)o=3?4Flk^X zIbW1^HFKQ(=AdR}VP??;YXkG~`0@E^bpqpJ885fn>&rL4M|9Wy@%a4w`SaJ$&(F`t zV}CsMeb+f@(v0Z$5bk{-5Gou2VAa^Tw^?oUjF_58SW;yjW;&0tWg02)u-vZnSC~=( z^mxVD{Lqq*j4(&mp@v#bln5lG_4TawVD+b2v$T4Pk{sf6#&EC*ET;JRvHb%C56Tz3 z6lJ2s>pG`SCk}b0vUJNld|ub3R`OB0Qr;h)+4rXB;Y4ZQ4JuP7dm8ZSNn32$1F+eI z+a;w(zERii$U04DRZ_cHYp?E4j{erU1)`C~UFbrhhqX)+iJzRgYT*^vITfmp$B#J; z;UQzY-QItB{r>v>AOHCF%lEgB_w9CPp-KAv+qWP8|G$B!N5%60&a+M8wF<42`Id=I zQLCwjf)9*zs}NogD@@Cbgw}0|lQPD3+n^wZRaSHFy%B0keaE;B#uyX&Ip?n7897Y~ zb8-jzpHADhujicQ+<>`A&evg^aC^w%`byLMgFINddU5snQ*=h-_FDsS+y~)uJ9B{= z>_3a?D($m0T%)34Ca~eW2U7u1R|*zYl~=gd+N7^A<3=E1)-6L}F&PcsY&U&t_?DEM z&<DXHObqR9mhffToho4CARxX$0iA^5&$jeoU|=Y22s|`qTEFm83wG|<AKcAsM(`$9 zA0f)#dzRa@T3^CEp~*{aT~(Jq8U$%9ZL+O19p#j9z+T~VSsCp*j`)g(Xv2S6MF)uS zI+e*3cnLOM09oO}P6EiD&XE5$FWq6apBDDB_Rvze;i6vm^DnOBvE0xM>8=Lnorf;e z1_vFt{3#|`U%J47tvk28)nCn~$7SdbT$eG%3%M7X?PWl+I&w1huB^NEcc#NgW=Ec} zlu_V)BkRrRVJzWb!QuO)xZl^KzU-O371~X}5fMA{zwkJ9r0L}A07Trg5^k@ZJI@AT z`BOJcsYt%M-O=a>z8YKe|MG!}DIc{6@Z~Q{=J3(m`Me9w@97(m*~7>kf=5UBlLdeN z?&~kIK%0Wzvn*QZaj8lY%`e(CyV9y@k9871)IGinxO{{zIx>qRenq-H%xH}>qh&Hy zQ{6=7dLy(VLJKZ*2{ik^%RK=a$@89r5W+~=yvvTz60>>OY6#gaj;%0uxnA-Sed!@g z<u#zuL^kT5zMV4onbub{-l(StWV}?Z@Ib(5*tG{Mpr%Sn%sY9^7R)@9n2BFr-d<nc z!hJC3zCRxO=cj)D*dO}%oR7z@bHd*dgpg(1rJso7+@8FwefyhcJz<bPCz$D(rWn4> z0$r<4#=$u4)F)WZfTZVb2W_4?i+8izFiHgWVzAEm6)U5?x};NvTkXSx?Cx_NtN^JC zaxSWaE`B&#(n#yBr9+VU@SGU_MJ3f(P-la-Re9mVvD`&%=W@8jW7oGFQ$&quy-p*j z1ztdnk;3C3?HEZ3Q#-HzUvEBJ;JM$@p3i-7kYJt4>!L69+GH=RmrZuB9I^*3*Z{Un z0W%fZgGo@Gy3bv80z@o)yWd~GzrDV{zrBCFzkR&CzTfWONQA{Gw(vP8CY0v=^XJc> zpZjAckT}1%TQA^2G=z1GF=Q|^sWJqqrXuNoK~WfI6-L|_-fD1K;MY<>qkMsHFOhAt zvf{(pX#_mrJQoZP=+TD##zV%ogQqH!^9&j0I#9cb(c+cK`O^QA9{zZe9V<NYD=kpt z2Sf6f+dbwSNTtJP?g9aHS{Q#g0{l#Yxb!alo-clpPPPCyju5AeF;FD|t<E*y4sIAT zuO5eI4gI1$c&^lvhD1F;RM~g=!YkO0<4lrgimDDw!E{58IEmpEVKV9r%RHYT9?UWb zev{d-0#zCr=e2xcuhpQITf8e!Ok7i))=>dW#ohV0>@4yivy~%!5Gj-}nZO394jXtf zru*HI%Qo~LsDlBN8;@-i9xn;?g)wuvz|fE{=j$?K{4kqee;1LF6jN7<^1)G?F3UgH zp7p-p2a|~FH#>4LO0_lk^5J1F{z>irS+w?de)ri9<*PqkvWv?)zh8@>-)zhm?Rh?% zEyVSlZNX1-lvh_-NWuXdxmK`xXiLsgJKZ?E^8Qdn`H$<qtluJw%$dr2DgAzP^bSE3 zZju>ogHZessOA&mwY~F;h4=M5J{91g3>AL;gdPn_a*D2?(z@&aDHibG!2*qg7blId z<VwwAP?Dy|7kdvW;}C`kqb;@b{zSIKDH6?;HOrj6a+1dz(b)5y+gZTc7E>w#5yQzM zz#hqth##1h2EYUnHMU4UY<#Wn6s$DNgY-d6Je5dM*{5!t2C0%pTqKq|(iHKk5~wbh z1s!o+gulSY6D1?M_eH}phQq*!Go7loZs>bpGVaS5W_PCBq)cSKZe&7;kjNO@c7I|0 z4zTXJ?>gtyx$AuF`_H+5&VAQ8p%b}~0#OVirfG&ZQ<^YHdk(>fR6T_-2qcK*mR3F) zpD+tEK{ON_cbSAzvg|*2ZPmWY`oe>+rDW$03Wr*kSr!7hLl{_0BWrLzGXTxZxmFFB zjf0ELp0H{F-S9h7#xL_u26@HdPhlt`q1r)VPrV=$qH70{jm9E|&@Fle7Yaq~tPPY* zPtc>qS%@c#>g<Gps~oI~(EWH=qp!u$Vg*F)c+0S%Rrv;$JBYo)7Z*C(vLu*9y<efb zB-F_X?MgU=xH5b%pgS!bZ{&%v2p6pCjycuIYnAy}r{MqqAOJ~3K~!0UZ@2sX_2c&P zc6)ibzuaHmUdQb|w%hG?AGh0(o6wDj6be<v)EG=abywXfJd7duM0jk(8)zE&vS%T3 z&pU;r5dtbF_@djz6fW)t4kBVn^D#_sWs$MnglGdcFq06*<e@Z%vG%e|W{})yzcXZv z9WtkiRevLQ6>yvM2>S^wYonhO(Nr`+QY$&3=IE9lQD6DYksrk_qCt%by!i^hhJpN^ zD>gOvE|9mUPNMS{b^T&@3H4gy8OzOUfl(Y4NCtx~_6Re;P;$TpZ1SAL7jx|5ne90} zR_cITFXR{FvE52h&$4qbXr2}Z*%6vCOR_K?2f4IA+&!oqbR0Y?gd#)|^4hZXK<XU{ zgOW+jSHt3<10^Vnve86?#4&GzAi)d*1UN`q6*`qHu<T_O&FKXN@eQO<HUrqazC=ox zAd5A3UP-sM2}(4Dc7QQUO%FM2>?B$2_pnaDrVVnJ>Um2_)Jr#0uTOKD&m%IZdtI5< zUCZfFUF^h^@LEZ~_1Hhq9_Iexc^7@r5xPP?H?M1G4efqV?H60x&BM-GJLnj}qxSsb z897<&2LM$6S|oS$c+c|1udhqHdQJZ(j`V?k&VJDmemb_NNjXJFe{(kTp2O-&mwHO| z88y**DRM&(!hFz7Af84pkqjQ~;0~oUH0pI;X4uU+*B<CJ5fx|ud4vwDt9K-RHD#Pr zPdjK(Sw}Z*V{M1U@v)K9Uh84)NGAH8Pa^URpdNkft>?LZ<<yrHGMxG9js1SH%v+({ ze}W18*9>4>ijsboG*|BVmin#xFq(E1WK6DI`x8!@eVphFBeO}MuhD*lS%PGli=_`^ zYgEWwa|ya<WznR=4mA5j0Me+u0Y>tNFbSNq#~GtY5L(;>P2x4XJ#CyaA@YclW|Jrt zmt~VUQI0QZ>yFYc&$#*)f`+Cd@J*aI;t6UF_cS+~x@jX|kyVFri^ueY$Jm5P#>Ruh zj0EUD^>gl@csx`m=A6^2Fkw!e)2K*1BPw_WtN?6Jk!KfG-VS8^I-(X4C$`ub!TGez zClF3JW`Kl1JYtZ1u|U;*{h(Ndp*<X=s)ft8+aSWeKN<+#v?Z4#0nO~EODc<1@TO9; zQ^Pz*S!*{PBx(m=ovx-6UOn)%Py2eHR)}Mfn|TOHBt#reT<b;C1M0Cp)K&V5mdqLp z(o9d`<MkYBkLpl}mLXWLXaC=dz&ZAo{rlnu8>a^@54xsUpsEvvp_e*hmd8ZnssVfv zO87LOyIRJ(l@zBTavS&C>vq47+x_<X^7`_AzrWvJ-?#f+HrZ}BC7KEaCeZ|V?o7q~ zYe@}O`3y=%z+5DMUW$7I$<)pZ7+!EQXn08~WhyA_mG)HAg>-$iiDBpbAQ@x3zc33c z4Hgh93s_+CQdM~<4Px0CgCS%4oV4!<i5gDH?so@QAg{Og+&DUHz3@7*Z}SjoVRum? z;8N<<(u%Fz1mi-3_h)V3QiTss=*1@vMndUE?bSK6>wdm4JC{K2aeUUZ@bt830Q%1+ zu)oj^&e}}1xrP6Z7S~DeHMB_ig}EjqA07eH_QoLMKmyjNaZ)6Xp4H1W)F`vZB%J9~ zsMr}PSl>8&0T##&gFOy<wf`BK$ufk!z>@voo-Ae9CUxW1pwtk``hZbQBC0wO?Ls?1 zP!}>DSSBT!(7le5=9+Z9+6O^HT676{iazDM`wx8)F01QmC)64%>i&${_cQ8b@?3G! zp7+b)*S-|jWP#-?ZNG5daBlv=9=J03c=61)Cm%crzEbO1=l(7~bnd9m<{j$orO9y; zCI`gI$s^Xjwc1DPUpYZFL@Rs1GT`|^*BuY9<HM3@CrXtJjCL>je+OEHtM;INEko~K zdCoFgRxvn}d|j_jsb5-0ArtdN=mx?n`B8jMQLQk#)7E(N9iO+G>kn;sQroGfG^K5Y z^%XVDSq?YpT3}KNVIK`(tcsjO1JC&FF0l{OdU!8d8R2#ty0q^CKNR|Zg6V75UnIeL zR>GUo&aj`krZ8M$O%?4^d;T%D7bocS*-PPURb0V}O0Q{n<|c29d=<Jp_DUi&K~w)| zmBZ$Zu*WP4E$`S>A508P<Y^=adXIdmZLW0Fc08DSJ<B~%C}^+HYp3Pa@WifY-OsZp z@(-Jo^5dZED`!P&IVdPNotY)SxkGn-n57^*EJ;@e%XXLhZ6g}S-Z}Tj{=lyL{`mZS z?E8+n>l~hF1$JhUW3)*<xr~G1*}C8Pme{3EXdux)&*%tLiwtIik=E7gV))W+A<O`) zyTT@8-0!c<&d3#`odfIqM(fH7<aSB%BuPeBA)7jo=&zGVNaL2}^w)#FVkx_Fs#;-B zNM5Uy)z5T#K0cp9P!=0br~Y3SP*X3;{H-!JU=N{l5+~RX;@J=cqUq$uX!RbeBi$8x ziRC`^WnnmzSkg5DM+GoceJ6f5a69#MI|p&VB1DE5pa4A*sS=aO*ks6kjF*qMm$$dq zkB_(akNfM}_VOw`EZuQJ=bVp+S+(va5u;2G?K2?$hBsmJBOQ7zOd?{XT_^xx!US$U z-E(SOn_@odpmBp2UaOgnd>Ak@lvu`gyTNlTQ!zy3`Rjm`D#9YN?UNsqhz8T(R(qr+ z2io*>i}$cxFFSJj#QzmjPZhe)e)#PU!*BeSep3Hl;N=%r+Fh|1>|@Wx3cp(r*b=QV zrBd08chDNf{ZKd?0Mb@|4;e+xty=Zc_t646uHnRa9M-)3>{NeOG6u!iI*cU>1=X?M zm95Y#om@~X{+gwjs{k8YDK(9VXboYgSiY=UZ33fzgIH1x*6v7H`d+5e{nWuW?d~ih zr4jPYkW`-23$nUn@de}7G85OU5~~{kv9Bj+lB!q%3A2=Kc0H>{iFTr$U>GxwM@@o) zcGAr)?R4Y#EQ8ZpP9>jwQ^UX-Mo0mzVT11!>B{QK4sgd3QovFyRAQrn?EWk+A>0+U z5<3?$qO+O0sz4W3+}S+NHP+$x=O>3}GoKUSdxEw{^#f)7?x6uphn*6iH`R*{#!Q@# zM?qKn=uED8CA1UU*pB04PE!aLbm35^WLQi%eXBQ^+G9~`BQ4Wj^^8J#Q7pflg?w1M zIm}~O(FDnSqoH7#8(f%&^DVN`Z46?uDrB5V0}=a;<Hm9Tqi!h$X9{<qnFMpz6^#gT ziD$E^N?Jr*$DvFKsNqO==T-H{Y9?ioN?%=`i|4k_fvY_bK$TKgTuUJHbdQjSx%Sc? z5zaMS`>$L%fg<bZKW-1{RiM4Iptk$CA2AlO@NoSB{dc|G{`mD5bAT^(;w%HT*syI0 zC;#)ZtRt6r)l<7-(M{&%r__YBq-V9w!}MOSp4!;LE7t{wV}G<~Iw6k7CP7OOfChw_ z2GQ_9Vo9Y?Ua%`3Lc^5bBrskeC2jyjA7wh)2LU~WZ+1{q9SQ+rkOMLI@YRgikEttq z{IrP@ti4Z%x+OMuvW>hcT!3*@1-}Ook;s5KE(C_@HBc)6{q#De!}VzzBIEWdFXPVi z?yExQ{`0Z#pFcn6=e~dL`{!e-lFkUqs!`P=C8_fWo4FlPZsdripRAa2%)rhL39Cq{ z{$q@78wL?42Jt6g?>8kz%QPlt9z$*{y6|43RA)n(2WV~O>U0pL8II<o29t0lqxL1= zd6<@Gxaffp%V9Z3B4;a_SM1GHPeZD?QQIjk4SsUSq4kBcNaI<_K7K95ZU@h=%qxT4 z+@(nSj3ddQM63bv2oaHz0D1N(u~2cWec?@HOXZKv-HicX-#zx6I>@lWG)GO__y)6A zsA58~gA|zioKpcBA}{y1k8j^TzWwt3AK%};eZ0KA-0nAGQP8fKsy`ltIhok&g7J+2 zVN)FKu$8D?z-crQ5u4dOO%YzsKN83w&=lgqLnQs*5;5v}-1S6P9bl?c0J%+e&T+2N z-wcAVjP1@O>Snq<R5@t+IN7RgKW(=Op31~GGtzVVva*`nABTzbHLJ9EH0tj@-B|pd z#q()kX-rgB{9^q?NIamoD;h1kd>EqNmkI3t^^3C=eb)qWeK$>!xX^yKp0(t5NJX@= z>nqGrH`prql)hr_r##Tt!@4$KYRPB1vQp2w1n85}8mxIp=c5whlqZheoFO9(+#`EM zO^&1hUC1>kjIA1K8+NXya%$)!=Cv#Fb*9z`uu#~;miOcYa8=NrgazPqXGC7UW0;xB z{zc~bsDhxFpq-$yOBfv%Zk7lDL-7DT$O|e70Rjc>zyxiiadfK1zB$<j2;d3O3`5SW zc_t08I-3GBL*B+=3MO{G0C!M{Siqs;N&WO`7G_#cZHK1eebDbx2TPiWRji%1N<OUF z)*VV6tEiTQH2Bi<YjG8|H=be4<+Yh{K;_!*%3IT5&u{0oJ2fm>`==dh%kuuMjOA(` zEge558}`vVi<7R9d^ssge-AA&iPR^hkIb{6SH30nWO8+sW)w7npD82^c3am=1zKez zX+=6I4<GQz;BUNz5pd!-;KI;FR0PPHwUMsKnc!`L<v@0H7>CL=3mi=2v2UxF4im&& zuBDb<3gRg7aQ)KOg#uS1S{v?c_jxHn!nBhm|1Ptpsjr;HRoa@g^5ZOO=Q<eGRws5n zYBGPv_1EhFpRPEPsAlC*+xmbUu&Wn6+SbPzj4ltwLuO_l$_9n+3WVE_jq$Y%69gq? zYkZA-8K|XIEJmvuDW$NeBk`Dd^&$duP97;=JgWy?=y+?xkEN4%#;!hCO8%5KjC~Bx zYAZ@}MQx101-Jh4slN`oHaE=*U06hIc-i}sS1W6%$`i%_mQP?J62)#Z2q2yKoICUr z0f1o!i){DTkJk@l+k-;)xqp7{kA439IUk?<{&+k-bv{rUsG(TO7u#1}0NKuPDc_I= zR7hNd1LO>2DI{Z$z|^?ihG|Z7nipR{^6Rg^s?OAXo!I&qOk08;=##Pn%TJU0Tg2}* zBhU2gv-mg%tPT?P_gr0PJ;=NM^Z9|bnDgq&sM+)Cu8O*kNQg7t<?<l;;@4-QGs9&y zHcKA@3E4iNa4pAzVTJ?=j;dzTyY2*{+xzS5+qduU-@gCy?U!HP-@m=ReQe`}h$r-+ z`vddy=LAhJdB=lk&=~He;%b)DNt;&9LFBj^X~2<t-;)8zG69rDWDL)ZN2ec4QE)l1 zOBK!dB(>p#e<4jl28d;B_ZQhV9!YbEVtk;%&7P2P<8j|7?UPBiWm$f?HiMqsR?L}T zrmt{eKC6j+{cETLP5PB0d%07d>3M(nYPwb{poOvK0B6|Q?mX9MdB%8TkM+dSaMc~a zBitkH)w>Al5%=1{DO#neYwMN%Tq@h?BrCdNltts7Mb}q*i6=2uL#qk?lhI;W1TF^Y zE|Kg!k#v$af=D|Nqt~^-yw@y3%3}~PI!%uAOLGKyxFvpg5O%oRVN7ywsSwCHwP+9x zQsq(9-0-k7s_KFJfCUZ=hhhLbNW;`s%Nh=g(p}RuBF&rB(Q3*NH-NoTQ%0>F_s&lJ zP~L$IBf?1+L_<k75tj5kINNCDC26`yY`Oa2U|L-*vv7SJjtCUKqdn;I9J$=u8Vl^% zSK7@7tTpTNGwaD4ZNH>(Sgj4MIP2fy@HM8d+->PeoJ(QwFRlZGg!L+?>3Ls}QB#zb zStHTv-=4bJJW^{9T;U6E0xb5BJ3Vn^9u)v)WX`MU-mYhMvT-jZVr2-<MCkVK1eipF zIf6`_c4I(8!m##cE&Vt=+*16C1Le8ml;=+ehq_NB1Xnl>dkPPom*0r?3p~$ULg8;v zxR|C)ett61BOY$UA}hq;QZ+?1pllNdAuebA?^j3v*!349z{^;K`i_Gwm2rUjW(Sv} z+j0(MDzl(v1`_e=ZA$;IA4Ntg6IjZ4JGCUAq`GCqIpIt{rF>_4mH*04c3tbN-mk!% z#G>06%9%H}<XLGzX{SyQjIPxku}5RR5p0%SwB|f`06h-6buD_uljHEF!dmt!Su%3I z*#whSTBdYcq~OjP*@$s>-n@XkR`aUt!D24N=M@*K7ufe9BPIz7!qj~l$MWvcKah;= zw%uOdUJW^|a|ccAx<4NK{@5QoR3G~fElfvOKP*<i>T}#21gnNrxHTeDQWp>jLT>Ug zB3EOx!YWmT32G}X2~;WVf%QU|%uGacPLcAKWpotFiGE<+2qQ6<Z!ID2>p4094~aWI z6I}cAyvJK>^BWXe@4>C`?CL7JZ`GbYv}6FoptDOs<|e}PSZau@ytRXnSM7O8zo_%J z;9TvCsgXgUPKOjb9TtOT)(L_>rtZ4WX(<JAyWd~l-d|r|-#^~JeZ0%dFSnPM?RK-E zE3^EZ_?!>Rn4d%-X*Jcv)021@rG#U>*x{H=AQCWf(6^^DZL7=k40{r+g?ELmGH;yy zG3-uTkQ`GItiOHInMy6g`gyZkDvsI<nGlPN+eX_>u|tSi5NK$oDZx0x%p_xsjaVK# z9tv2Aq^d37BKjFNLG7vLN9v`mj;)o<dR}y$R2`N|5B0}ob?5JWfpUM~Z}_c#*LA46 zd|5lN#|Ktv{~M3ZcvK4Q-pR|2oD6vdU7<?axGqH-e>yzya5nW1dx$%``OJG|Q}Bon zvH@vzth#6VC`kk17`EGTe4pJw9wJ}PN^hsE8Pig@t_mAgK1cRFH#RJ0!-JT>)6;j< z>XsQD#-Jo<4;Q>Dh*XS605>KfPw(f%Qp3<75&LzxwWlOn+K{mdXpnJDFEIsInw-Cb zCQ)+<xD7nXt!=l*Q$B;H(1Vgleo2+rI+c#sd7{^_<X2v;K5Lf?rZY>OP2}^<`S3mN z>{VN?7fEY&|M~ZSu>nCBHtF-0kG`}s^!f4IJC1drzP`@Wp<lK?FJAXZj}4`T^JO>r z@+}c2b!5JuUG1e!dbhX^0`lO6C)z-HVsL}rw~Bi9?-9D*VQF#uSCS+4hzmXONR)-i zk{wA=Y}(Nmo(yZiS}b-k+T{YtMd9c)S58>nN!m#jQs%a3b5iswk2jy3Hd+_#SZ_FA zYZ+alc7l9ST=Q?Z{-OcAqzrZQuMy5<%4#=&JDXA3Aqm_n$3_RZI;BhnW77>5nGc-C zFIp%fninQ-Kj<9^RH>o?`t2zzn57#ZYzFlbvy?>^mI3k?C(gEvlJvaxjnuqxNl0^{ zLHR;mC6{aD5*`{<5C=_X3ZiPFfDC8LTDUYS?b(1AUfla!T2Gi{9x;X&OiuBQ)HU2% z%TPO~6M|xW7yE&?5s_2H=~6Q~95JE-p>Y%1_(t37E2#zErt0UM``q_A=L}jc(-T@k zXp0hqh?IlBBnBYeD4`}Jm#ZFNiXbD_=kU2jnxF^-;)+qysIo!tJw~T>B-9pK)bYj4 zGlB+CP47{;Zw7x8k=z#8RpwrGB+Dc|yZXNFa%zQNUVr7FrW~|w_c0aNHRC6?hN3VM zWjq$;sa=h=V-nO8J0!gl)Y6r48d&lpEKq|Js*|7-3eZ&5ZHR35mzVe3?d9$5{eHjS zUtYG`?S8-C?zh`*Q+YK*&Xvh5Wa6u*W_&r7$wf#Uyv?|)p($;TW1ti>sST1;%?>{i z0Z4?bkfAwe61;WDr>%|e0x6?{8m&E=G~Ui`Ho7Z`c^h)u=1-u`<`B!&I%v_^F?Q$- zd2^Y2oCT3W4xM75J#yrCMRp1Il&xI79-(3iCQoo1ikN}&z8`=a#iAF**ywB(e{sdP z5i<T@h}!9u>I&x&+HZ~9^QnRgELEc-5vCb*<y^=IH9o9`XHHY`YH_EahK}c`>XppN zu*spdtqbTfu=k-oq?Ukv&@GK~`zcgg3L3@a#ms1SO7<$kx8PH%g}JE4iJHODOmGA> z)l%`pdZGK{fKUPiQCDUHmS6B~f=Zp?q>$l<3ps1nAQ05^>qZe~O<1Oe7hcM=WKRTE zeVE5FFxyo*Ee6T4oybMxiqG^4ZxLYg;|WBVC8i)Q_QD3{ay{g%Hta?zYKy6mbG$C@ zj$g2&S_;6q+?Mj8Pv0{In=9U%=jjo>e2GoCIzz8vz?b`?`Ml7xvJX<96L{X%KOIC( ztlNml^#ksAnH5(;<mm5y0?<GQl~l;O8J1O?`?{MKeW|%-Hs!oW7joS4D=}7_XINzV ztS40vvUnb!#nVEM%F2|UmYbOCdSkqX$cYTv{zj-|hw;e;Ihi%W;M`QfXOohAkm<EV z8?K}1U!vLRkK@$6HQZMH*v=M|C67y>{-G}&fz@v~TDkd})eb5T0tY^(H|X!Y{(1yB zhdxcy=7$E+^$ts#Y-vVNj1H0jBMF=%VH#e0rVJS7NJ^2+S3y6^{h{g(yj(CYZULnv zv#`g8+g4-B8xTtmb6}Nl&baPW>%|KAS>mWj9Vm=cyjEob5v$4P9CdeHm-o7ukZzk+ z&J@!8)0bi|%RD;GgIlXsoY>DSv?rTzaL*9u*B$30A?y~8!wPA-8W4#D$og1aI=e2y zOzci?Ca|hbBe$iJV1rq1!`^zMoB7366^c1`tEP&5!g4Ehsy-a$6;cfZbrv6=k<`mT zy#@)TWDL!|GH_HSMPBB$R$ir877B-c!0sFgzj-0z`s{~V&m<zu`~aHd%D4M_6{Vj! zQFeHd)Wvqi^QphZUxgX%Kdmlw=@v`NInO|tg*ZJ@FZ8#hYI_R)l;)~*fU;vUAM?iu zOf*6)uN_%cjm7!Kp;d5?Wl;lj>Ong-urU;v3VuL&DiLooZrgpk-EZ6det)^&U*2x_ zx7+>Y?e+b3+gRKq0${4{VAbHIuo??2W@3dERic1{*^61>l^cSMhQij(#Dg;0J(-7@ zROiHW_P=s=GqVVf-8@NR((|OdfCG%6jRh)g>~L>&{Av+CY@so<JQLq0JZ{^#-{w#6 z8&l?s1Rb0gR3jP8!iFFx8GJ<cc9Sw}6v(1sm<HSp70z<sT04lEQD=S=*Ihyf?WefU z-5FMJl&Hlcyh;T6`U-g)ZGNhlr>WfD<^lnWF4zu*)r|G__pN$-)n#4HQ*L~FP3^g* z3r9C@!v(BsuYT;WZXJnlUAu;x#|DKyNLvZvxbz|G4{o#<rw((3YPm$TuRL_Wlyoy2 zfyiV6NWiVRO}ZOuEof#fxXf_LU>`|9uKd9TtM&;@Xs&vl3aix!x4%tLC`~_SBFby( zz2zzrVd@rz{hZ>$*HQ%?44b8;mpI#oa+=FY_~oYcl!zsGtRM#vL7fnWZw!ipl%3MI zLLeY=nw2=!nzYQl%<I%9gz7x*7i%tl?Wal7H?C&q#a9kel#ef}b#b_@-q==_hnJp! zW~=W{dU5W^`bNI`%kuCp*{(x77mq#vtwyYm##Lg)bzeeLUTi1BDNEh{tRuM`Lah?9 za(h;3GS8f)WjIbsxJ|ucuy!-|I4+01x>|1GZ#}Fo*FPdO7a#Fq9I97MhzD-D{rxOC z3-3Z@$+t-<H&gp=j(VLYu`&<A|4`TKOyGL$aviCE`;hzkXaszOay#N=2mL-yjo-Nb zS`Khph{-wTYu%RYY=Yx}L`Tj9D57G0l{=ruY|n&y5FNHOiJUK}3BJJy*B}n3qk@;} zf+*o`;!@ZQV75{O)(eX-<rh=!j?1LFDrd>i+RSh&aYS`M^;)w9=tLs|;kGNPsBgTd z4cwtjBK4c%9EuaMeF>>CWE@HQuAw@X+WA`2Ak}N5u;Q@mxGF=k2FS$AP_dJdPy@PZ zs0^t<Cr5nc4w2K++DWHL>1#;~ewZeqnCe5B=d^o-cV-qDW89hL&ZL0q#8f<XJRWm@ zO#RfkYZYB`v~8$KJy34sRp5dTwbMEmXQ#tiH9__|$zTDCh<W?PYDjV{L64p{>gl8? zOV_}-Z8GQn*!P(4OWCgxgh!(C3)Tx|-l7oL#kpZ#38n$i^88Yi4<~CrBzY0~$~>O` zF|3&z({F^2aKz;-K<>mas2rc5hdF>GyWr>avW4PLjct<KSG3MNcM#ZuVD+gMn-p@4 z1C4FFkC)ra`~B_x_2c9H<J;~1b=<Zgccz<XM(8y5tBn09`>b2n+S2z!rP7&vn^@gW zHX##Ou;xO_si+uQY$PVt37v7YAZRUxd9ZAlimKghlun+pR0cyR2Hdls{bWwGRo)*? z8Qv_mR?tbyt$-4-jBUH!KGX4(bufbiD{&(-1~Kn*PMtiq2CqFRXU((CJs5b-FH9e~ zn&++nEY1XxdC&;^r9#W6jq)43FKbRaUGrL9T!)Ip2Q&Cmqg`KpXzZeZc4$N2I2~f$ zzu9xh8~UJj?rH!Z6qIUMfTSv}m2s7`nuPkwrJ~JU|I2WYcf?p{aJ)aY6mFk%5i0At zYTwS@BzURbo~X-Xx=QNYiH%yxAkd|2I4tuX3o>Q?u(*$X?Nq)F(SG*Y=4MfY!ig6R z9;NR<0f=EQG>f&_VdRzVSy5V2I2^p@aDbgDN)1}@In@s!xVxbODL{k5qXj;_JD`i6 zQc1{;5i6LOJLS1mc=1R{=__fP)FxW>WF{A?<pOIf4}GJ>{2Gm7BZ*pPp|9Jn{az%3 zU2d_qH*14)sS{ss`TFY>Z-2%`yS>zq5l7_I*@AUtrPQ8_b$ISwM>U?(3Qohm{^@)j zAx_NU|D~3Se;!-U@yR2&?hqkXL4dmY&TaiV7<g%gft#6jy1eE^$81zT+d>bAeq&5n z_|*>O9$O5yfp-X<UarjCJ`QUf`>+N=MqQ|a$4{OZoChdSq9*-2&mX&LiKW+Y^xgH% z=bp*G;rfepfcLN#`VujAj275L*KIiUP`|VAz`6jTc}9jzY)h0cAY&9g{>8?uh<@S{ zElOjw0nSJqS;yKe1d0PJ!fTI2sFMHyAOJ~3K~!iRNpKfABpaqDx8>E8Dtn|FYj6e> z?Cn}h$9d{nBcq#cVsg=v*Je1Zp(JmN%^tEee&qx&QA`_CG5go!>+Jy#!}N?_%pfXA z7$i59-42i?=?*<pUvr4F&RCxz1QUR{kF`x5gL%%(JTX>jk6p0@Iw0(ACG0z3<U?NQ zh?r@+-){F8vV<s7#hm-T@47!Q_c<RA)g8);*&HY-W#ZQwbdHIiIVQ~rOT4Z-(;0-B zL2paPw473p?G6zcn@-(lGNRYTLvAlGJ9gebnFw<^j}rap))FSO2em_JatyV$6u1m^ zcIlbGch@=!!d^@<nWvYm@3}B-#z$MC2PJ;d8=@JDjpd(!h^Bc2h)K<L8yl3en05qp z<24;um)027NYrs_r8R@T)wjDsr&<VARl(qKyWL;k-rhdm-@m_q|M=zY<NNL9oyTUH z=BGa9+#l12-M3-E7nzuc%RK~yUL1eOT>;`4__R8c7J;35r>c^|y)(XTq9QIJEK{R0 z3cKCz(JC1-HhnxGMhPuM%n+rPWKbGFAfq|r?aL%~0&rd{m$+v%q^H$85s`7*UVd1S zQcBx^L81&I6~Z70FysarkEwH^9}DTnlJW}9lYgNAwXb}wLAKMOtmvb`nZ?6X#un7# zc=M@JVgN?2nsK<&29AWT!b+sMRf8N~I>(@{AIp)vQfeVuEahT|@-%UWh}|D{SMOq1 zr4v$*7PL&bX+S^D+_`>EVA&L>2HE&T_`g<T_-&A;@`9$}mOZ%4-4abYvMi<K%)W3z z)erMt-*MYh5m@Ha*qVgYrU1gz@v4zT-0FA}1>P!(rnrI>{xr*yahCiA{vhxSsbF$e zYHYQ_wn@uG9+`v~g_<HJgl-oTz{XMShoHJPXZ4c+rjY~%9EB_*Oe}sl+OZYojzLOL zxI$sNS>(7nXPIl6UcoWF_Ku>BbcutHmC^`2O>Qn)k_K!s0cG_9BYgKX?$iXhkNr8L z_4M6R0Mk8}&Ke3#;&p3Je`<e42($$WrP-IJKt8uEl7b5f&3$U5)=QT+c21)M!*=fo zodG^;GYW0QB~Ox(xEox2_+~y-6ZP+Qv1C~8yf-8NrNc8bQX1Z_!XWl<9#X@Wp0q3y z^-b)EBnwAB%dL&UOj_&AK|F{rx|&Udmg){NDX<&s`jzEC;S$c5>o(^)x*U&%rY&=7 zOx0}csX7uHyeW-e9A$ss^_LCcW%Q)|%8}%$Q8V5^q*iF8_rJ#%Y{89|6`k)IMC|oH zg0%=~-4PSfq(@(6W{G+AS3n$n>S4FU)<nolU`8BKdNRyRj?yS$pTojLo4rFV=d(&$ zWm(;{1a_k7Oj;f~%~Cz7pbH-}i&~nruckubui9q@jsR9^V}hQ^Ow<MzO<}q`B=Y}J zkjXINnQ{<EArVN<W%syco9ObVMvfNpYo#6qfsJr#HqC-(*umbT$xh%Y;nTu!N(9yb zT-nVE5a~{=6a0xJV=#m6MuTtLZK$$-l6vN_VW*)`r@d5iY_Ml0L_l;jWpvSo`M8E9 z-6Z*|y8l{teMGLI0L-*C^(e&z#x}N>``B*`>_7J4@pmOpm7rqfHmIP0J;Gy;nql!G zZNHo$_L5hoO@;@=BmW2!h<!PwGYBBw)=c1@@q5r^b9HGRX2BCi&hrd`gOqF|asZw) zE%Q`KJIc*RAkQsPKQ|@L0JHJHR#y`|p#)VZ?VnH(V;82|?e_ld<Nf<T-oO3w_VNAo z{rkARkPKx~@C5IZu-iGI;e~YwL$9h!EKFO{do)i(EEA;V=)+}*$jX6+wC8igVx|rJ z&|tA)iPKmI-yZW<+Rc|_+u#8b=3$<ei3jl@<CXP2m`r9cvhx_j9%mb?xb9LYbT_Un z5rkI)yg_WOZLhB%|E5C$Wff1;y%F6eO{F=AH?Sx+c~!dYI@K6`FfuoRIQ`91gIRe2 z)Fe;l^!7GeHAq>P<+I8Shb#XotL(DZO=2*~@3M2BUI%kJU_-QUXDs%l{|Q*EyMsyA zZL{!ix{&O<a_M*(k0m8Ia->rlAWE-aD(el`5O!l|!&h+|3L1iyb-mrd<rpGjY1lCg zKR_xcFmfdOfTTmSYk1y}^bsH5i;yPGgJ5YIozNui%D4L|w(@DG?prD70n~5}cQAPl zh`C3zNr)<ZM8ja5D3vLsA1}@w0}?Y6(FPZVyK#UAqS?AMKxTGwN+@_Ogz0&a&8DaW zMlF$H2Te~l)^NF+5sR>Ckr808_(wDWAq;4m$!44@&q4VsMIv)3Vgn$Ws(Z^4cIX_3 z>0GO&&1d7DJ}y7*&ac{qY5tA4y9W{u%f&syZnTpSDI*2!!GV=uIb1*${XQ6thhwxo z;d-;I-*X$730sq;&!km)x238HE+k$Dr`xJbCYpvL<o>)Phg{h{COxq=e#{6k7`Nz` zJs=kY5%p7)V65gYf3o0E8n9U0nw&;vO096NAgjcUKC-LM-))oXNwiQ28ntI~YiB9r zKDLK1`yf|1mm}A}hbkkzDQY-+7dgY|Vdp(Y<2WhIeNryh#wy$Mv50~i>CO4-B<<&E zc~sH<`KMlgXC2_~eM-HP9JSJx8JQ2VHVhg}i0XLoIgZ3sgU)6&fT><nM|hq;lm!kW z-U(G$;RiPsJLP)X3QeMgji*@+wLLxx2%AqPLSS%A1tQ{Vqh!@_!X(Jzy7?xG#P=MN z9vW@wM!pGWGXQeeSr=AL396%-h^Q#_`}ztpN6ghyY9!4F1rY}~UPp1(vWO-*W@?Ge z#2z;#Ciu04(vKT%HbB?MhCRa$+43-b<?(s~v(ioxM2@z?bW;y7ld4WQ@eo6aX{tha zvJqM`^I#eGgvpZvI=$SYCIXCrNeYsn07nE8qrgVs^%@W*#wP|>JQtw&3{v>2M}e3L zR<>sFE~=n8&1J}vpdfRTav)_jMyQvsbS+J1%&;FP=|CkGFq&h<CyiHKzb}9`#@vb% zCYqH}k52%|B08A|TY<hc@h{RrJx9(DBG;dUXtq?Fwz}4sj3LfjnhQHA>TW#AbLu3b zF}7`c`S|{Ne|dd--Co~bUS3|e`<>-RV*`(e>f`g1SV$<AYw{bx3DgiT;9Bxf1?@y4 z*VGX{6H=fzZMt&QtoFV~;!~g}BEIYn1q;mxkqD;l*0r{yE%Vsif>U^Nr+{mCEltZ` zgi<V4rQ{-~?u?}4p7p3?a0Hf@*Ea+NEICVzJTp&VVcBjQh<4o-(_xR0rr)fV>JjdU zXh3eUOqWWK^;r+gk$iUQ_obyABNf{!+C}`=+}CFv_fS>npmO!ASHe5|aDJ>wMJfG> zIw9wm%?oTxd~y!h9two!ZQ5=~L%mzqr3Dw0<}yLLq6_<b4^Bp;`Bz<b!JSwP6GXl6 zEZR;uyyfsoAFIQpq&>_{zo)vV#8f%XN`)%qeEr+s!WA;A>|DzKWHa)l?tTQ#0J6(# zCJ0<UT7;n5z{vvbEDYp1Ng!#41F=Vb3?X8rM?Iy$r^_>=%<H8AYz}9Nd8>&q4PR}5 z4h$Kt24wFLyna@5ou*)evv#3+I@v?ku9Ycj`*=(>@~2YJ^?*RnL2K$|SwWX-eL+YL zisX9FVvoi>p4%0_M>5LsI$N9Pt$MI4&i8!5;(O}L*K+K_jK35e=MT?OaXk6FKjF}r zj^@1#HZoa}KiBiXwOQ;S?M%5iJ>0JDKQ(6$3T#l4`HKOk)1Ug>`H~GWcpj+yuAC<K zY$W$zdHFA@<iSarb*AP1imRv9yYkKsQ0l_`*?{!791gXZ9$cZE{t4ILX#m@2<o1n_ z8l|{_4MHHArROl(q&`ZM)t(W=&X#=XV=|-GOtTD|twq#MootwS5Y3J*Af&WE<w<wk z0P!3Kwk3lwUkZV%bwPtgY^Z1>onqdtP65>2pO#V*P~b0?`!nT+LhT5>AtM8I<~K#O zIf{sgF#OcvUgN~^MbWBU!D)o|_BcfIfO$PFiP9f{9x>unF&%44=K2Dxh$x|{JjcYR zdNM|Hvbu9GhDg|oVSp+K+(~YXr_v1I*lQy2ViIc*gQLtL3lna!C_Enqs?N0w0?k0r zA;$r6Rx;=5nd{lC#K8y}2AfvqL@ro`9qQ(2iP>J5DzhXk&M8R|;!TMZuEb<i@Pi_$ z-c7dz%vSE0+3<^Lu`JRaAq=hvPLO=IynmjLs{Vu{lcAj6UQbe`AWSaIp($n3p4OzP zX&_b(JRDH!p?u@w9>VuAw)^dE+{W#GyWQ^FcHg%9ZM$!S#!ajY&m>mGbj&<6vkZ^^ zaYS5MNL<PDOxj=su=Q@9S52}`Yo#AY>0@qdqz&>OLzQq+T~Z7XYdeM|Fe*Crp)fCr z`4HUO%}l_APD=_P!h-5sYP!1m*kW<dK(^5yj(m;ULAC}B*(fCA<@J@N5}yKQXC-<4 zMKZ?i_CiGa+;{9Gy^2Ps4o-Z2?0~LS6gW1zc3hTcR;sR)$f>g}SjTPy2h!Eg{wf0b zC$A+uwUV6(yOx|t9Gk2WR*thAHEQeCoqBw1YAvOsVA1vt&bV$usLSd^!Ig<Bp0*l0 zw%%O1veNpMZIBq=k#=zVa%!BBv|2`{1&t$xA^s5CLmOS3i$!+0uLdXW%_W}0DU6L- z$ZLX41COskImJ4{$qmCSP%AVtowtDU(97<ia{nBplzTaF<27sLbYKvPP%87?9%E%I z9qd?%U?Gjl!@(t4k1fPFQ>?C(C)5BzLNa6VB%!xQ1z09QEvL8*yZdt^(4a&k+?PSs zWksz6RE;gzF8~5>V<XiF2>Zt(0x;18?L=GfZ)qI3N`MSzjc*YF%ASH|t7bGsC7Fke z!e>Uh^&n_?=n~U>(1@1f4@nK^*+R9&Lfy^SGV^i>k{?&Ome{B$6HI&XA|)l~iB}!D zVKep2^{eIJW~HNQbtv$8C<)&7ct$BYJj6UQ1%4K48!&F_H>6l_I7Y8mUwWb&sa~@; zg+@<vXl7ES48-_a*-K$C*Xd$QBz!QOp-}^cNu(lX_GN~$(g`oQLl+A?o%?6MKq$Oz zK%{xO4#iL@#<qWD)GLzCinR!U{ZP<QAhT|c*3)X+B7%jDzK5)WLn525Ts$en`dsH! zlAS)9xkA++>frE2ZOcs*u_Dd*4ZEXF0@bn%)H653AG-bt25{~!NJ{#qKT(qie(cqA zD(BXI<$`i%{49_ab)MCkJpx~o$}&7xGO3|z!YE`h7&yohK*LfM16C1*)s_xo_bi5= zckzfw0DeG$zv3&rR9~?}X+gZG9g3)qL}q`yHN%4kl?7*gv?3Bq%7Gh-Y5eyFS5P}a zJIBX13pQ<FYN5P!AyiX=HFD@TrgJ*fR;&En<|U8M(_=%+*O9BJVw~1T-reDW6Jr_7 ztoCyn9M-HiNBb)anBW<VTb2e5wO5&#EYlJa9u+QjHO*XfE`1JNe55Y#HXgeX+bz8? zjH{HK$Y5Jk{U`}TDsU0O+!yIvRTRfdy}Ev25;xYK8bG6fl%8y_=;!unQXGGnJpS3H z@RuT-Unub&E&){vU}{iaH*f8eH*%wc=uR0`wFKBXJz@~4KEk)#eQev<UdQ&n-L~6Z zw%gdYZQC|x0a$nd`$O?LCuk}W@d$n-W+v9jFpgGX66aF(i4k(@8pH|Bd3ltTse57# zJ_s;^n%hrq^kXTH885)Q`s+~WZy%LOG@-i_dK;vRyp)neeX(kFjwfX=c#&pph2^?E zZuy$85jJ%bv#icf&T_lIjxjv2<1S4WR~`&T#Uf+7-4*nhbGqZu-HWZnYj+VRr^tbO zgquLiYB%vk?$R<h!jgV+l!Ogi+XS-o=d@}-fBfowqAuQ7_dMFHp?wwu-o{|f+zS=a znjOD4#bQzJyGNi$ZZ(8b++zqO&NxGNMyyXhoO+Gpv*EegcqEXr)WOmad%n|Y2sxbF zE?@f)H0cU&G;=sAJ6xIbZQ&>4KD=?K0$L?l0y4JnULD8bP>CwXA*_q#Bx;>&RtY<d zxVsoU2${!B+{ta()cA0F8j?w?B##L_i37+0DP^tuD?w4ABmGci%)`qZB=@ZA08Jyx z_^_oK`J4=Fq!VtGdhsT>({tcZiNTdUB{Dpgg&dTvuoIXdQR&fhl5^RSad;&(psBBv zY9y6ga{&(aNhuRI6%Plka2HBvbSU!@4#DC=Y^Gg~Ij>9Myu23tD%R%GVZW5El^?C5 zlG~RS!Cp#7k%TNS?H@|$0QDCtQQ7;lMn@BioB!eUu8WVjxEs9(;l)6lPK}-aG%Sap zWl>!)5nS4%WZ*I$haHdQfs1%gahjR@{mOg#S+JOz>lCiu-s1%2w+^Rgb1ScpJ3s1h zHmuMmIsNI}mz8;|?HND9>*m;($t>s#>Cc|3&#%8|0G})+O4lQMeW3#W)$pMPJ(Ke5 zp{uErAIBM~$cS1zwy7*}sH9=U%UVg)7H6o=l1{k^AY?Px`4X3-cWtZHqh%5IA(b3# zzF{lKW9?z(Qq=m6ZF?Tt1tJ>CaT&}$2IPv!mBA1OXZOi<m5oxUU#K8Yer+db4p@I$ zRvhWl*Uu8A=9hwd<vJN8a$->0M)+3P-SqY-C*44uOTyEnF*Fxj4P|>8LMXWfhNYT( z@10qY6YWs6Ac09zp&>LZTZ)Zb)9l}A@!_(#3s%m)NS8(B+7~mk7JfBWNW+~OpD>)8 z*v(qX7_^!G5){9#*0>@lJQAg8ibZlE^al1xT>|^dT1dM(8RHzZ9A1LdHF<eL6WNMP znzU$q)7}_akun#aoAq3qJQ&wa51Oj`u2aP&%ot<aZrgU-Znw9$xBKhMxV=GMJ#QMj z0zaoIOvE%<Qbi>qA_)#IGnsS`Z@ra@Wr^Z}Y%w~nqP5PlES6O31#*KQ*m)+H4N@q? zWk&_?i$&&x4m$nXEr0-?8V)jxTPY@>RR_4`c9^+t)wnpRO^fQxSJBDQariY>LmD5h zFlo_MFXF(#3$`e>+f8IZKaBvEvp?{;cBOlahw45tQLH0Zr}AQm9pz97D?C>jb4lj8 zzXTuauO%|O96p>2{G^qC;!2Z^L)BRGoc+?X%25#&S5FJ{Sk|4-@*%4w^%0YGnY<%q zp@o9(WZ*~e&iSCE)lPN9yQ4)auc1Q<TWfswW*UcUQ*CJo@uj($#40nZ?sZF;!Y5_< z1t4Npj-;(hwW*=Y<uO9p<3QLJ)^cSzIS$78oNbB96v5=CR+q!VZke7g3~u@r6A3c@ zLp=`3?Vj@$346)4c3#5VT9H50CSYUT^0c$VS6zO_sU9Y;OQmwdmfzThPQVrjwftdL z?YthjNl|97j~ye+Q)*}k?CeJbw(^Ie{5cAZB7MZjxXe9Xe<1=$qR2&gE7G<A`|3&< zb+_U)SVsFX8lu<tv>q{2X0G&l#W<w<o&3=Y0o55`_-sLPHJh?DpvU=}-18V|yr|=5 zFSdN!EE#%9z>d=DCA>i5umhm-(Cp7_)>l=V%ScqViUqy~GH&L|lEh|@BtdsOg#A`2 zn^^jS%%F*#wM3y#3KCJ@hF1cr_vmuItmQj7AKTfCj6Ch-!)1N0@A7YX1~O+1If-rX z)VIPtABRs*zFc7Wi5c5ozK4)0nK<6O)ag9Pn!ow_YX&fNJ1t=hh8CKs)jZLg)9PO> zClK?VzxiD*t~B7ARlg^Z3}o4yId*RU020pPbNoC6Ap_uZ*eVsXL#EUE7>izbq5<61 z90{woEY-{m6Yh))1(O?KFVd?rafSJ?u$zyhjK;NV{?rg&Vb#PB$><oj(jf?bH1!Du zfH{@)&^TaF`#6ATT_a7WFFa<IMog>C7!6|4a9>0sE(gvTdqeSQEdx7Nha--b1XveZ z?O5`OC`y%J5kCsqf~U5DH|qj{gbXLISOq2*%_5FHbtG<-Ibw185fF5OtDIM^$?$uu z?uHb{nb{iAztGXLvu%Pn&n=~>&>j|%NYtBj@2m?_0dX*x<|Bav4G)r8!4Y@GI#cn5 zjz7GR$Q(e4)Y?1YMfMv|ks&g~_LM3Z6Qo|Gh;>e#6Qm-L+t_ZeukRmk@9+1Q*D*FX zL7C^&&&NLLhmqwlch4e6c3B=*Qq1SRsxs&&c_74>g$-ED2qNb^I%P;=r=$Fkb1)mA zeJ}~UA`ykvp~NJ-p(rBeTD^>RQ#&Q?KUX*Be5mf>r1M=U#sR(Ew(TJzA)7O&y$Os) zQ?Q=RSba(<#tBaOe$G~MsHB3JWV^i(iDA(_ojOZEW!4D^$@bXkp->VfufCWdh(%vO zLS|%@TOls5?NK;{wXB=m1zg*tb%e<^hBS!a@dWVV?)lp+;PCr2#iE!Xy4H2Z%N&G2 z8Ni_?_C)0?I$2v%R&J0^9$268MBl}?E?(W9xj1neP41F}e0Y@oc2(EPPc*LXbS%Gn z3&M9$H6{#3(Z!1=o*>yevw`iDY<hOChp>QYM8&!CqCAm!z2Y<<{*wCcc`jWR`GaQ_ z@H&o|v{ZR5HNjPj<}7kRovWchw^%f5*N2&Tb#aP<jDwZmGj}})fk8|EVP|x4;eo_} zyO1^Z3^vrXT2Pu*TageIM50jBF|*XLp{$t{|ChRVTb3lrk;I^|I47%TrgxVY;r{<m z@dNlop)8j|?sB^;GaTRppa9I=Pj=N*4TW^6&d!Voceg7H7llGD)^$pQR-F*&wwx2v z&!SMJkswFWqD<Z8qtsJxOef49y}~`Gc(IiFn4=1)Oc}YCqVZlsl^RfciW2a7UPeW~ zb9t0g#s=tPns#N}R`Z<GloacvI3g!jdDHNP4eY!zTNf6WVlJ;u*P7n;(spv|fh$Hl z&fi&lv29?8!Xu~Vo!F<^kt}fvDxf5y+s#A4tvit}&sewLz-~YDd?p<ua5K1u*W(E- zQl=?)G>(RP+vLeX#pnXQwj0xfU)(OEAj^=8yYVlalvp`;%dtS<Pr|=~f*`9dMhIPa z!t^nxJ)ZZe`17tm#sV#e%eLIH(e|ekEAN}kOb49qu!p_=LPEk2Wa?gJTB?L>lylXQ z{HekS(pL7KHc39adf}|D!M;RHX|`%EhzRdq<wQhrKG5M&QC>p|5x3yiMe4Fen9Q)& zmctAY$VC(<jpQ#w8D1nABOG1PHfPnM`}%ZI-^XYFUIw=CgucUO!tF6UkV-0!%7WFi zTq^Ai-e5xMg9OVSbWC2{2=8oc{lvZZkDnq@vg7^6K$_ICS5C(rjU!a5nguJ}y+-Bx zN=no`?Nyg&`noQK2+UaHB&r?S0C<H#WtE-{V97Y%Yy90kUE|O5C1rPdA3sU&c_lC` zg<u~yGtR)*@2mZtjcidhh0|3~uQZ>`+AuIGnzxm!Dz6vb?>GZcua5R8!d;tW#qRRs z$B*~>ZT|l8eqZjuTI;1)AHV$a`T6<z?c>|GkM&xYzTydQ^SAw&0^J27S03oj*X15j zdgX&raWR(eiFL;`P<LUKF`24hRA)N?{CJz{0#=Z|thJzi#roDLpQ~WDUdE8C=3)6Y zAZFKqXlBf%0xA*aFmt~mfIRs5f`$3@@$vcj@%_hoeTJuIY?Iza!;d9?Ksh^_S4(Bl z4P??%Z(yoZ)r3PoKELV5hhHge0Ta34fW|*lPOjItAD6sMEnM}}S$D2;`W~OJpBzKs z5-KVRp10T!feqhfE!dy%Hh=i~EvNm1qx}{$Y{R6qs3(Q_zKe(Tl0!5F;1}0%B0Q<W zkz#OS@Vt|n9{Sm##@<iI5Y>X|9r5&}oUKxA4-d}FLuo}Y#D%OVPcoFk+8<;na1_`T zbt7!oZ~%~cBVM7mVW%HwsP#uXN5{G4=hc?eTqM+<A6D1FWUiI&IGxe@fa(v&s|zB) z35O4>W@`3TVk$EZ;E**Es@**c6Nn;|w>Y!jB3CY54>6E*<8WVDsb1p5l&Joenw@0= zk{HCq0#`!tnOtcor``~t=PTXv6rlliMMPDy;^2=g2$2k1<Rx{8TdKP*;#x!@`x<H6 zwbPMg4AsLvo2vB*w{+kpfObRfye2a7t8e*NuYGr{r5PwbOrv`=54U@5U-qNfW4!W1 z)c=()xfEdKj#IjmF`QGOG?cQ^9iiW&{AH~Z?g8mk{#zl*<U#Ds?EK9y;3pi$=TV=6 z>&`y7Z{e(?ZsV5w(+(+dpOn+kKf=AE7mtGUv10H%GG=)Ei{CJi_SBwv9(`#Q{)yKg zhCqAOH;TShfQZEm>KxtXY)A1ORtoCI4h&YPmZ4E$aIsu3X)=v!r7eiviRqfzr_J1I z;MrWJ2YuBf5a#skW*S8NvP;P)IfJd$A$OQT<RyM_&jfXri@ca+35s3@GnubD3LfW) z;!<m3SHYD&(k8PhA1!BOvtD}C-L~;Lrh2FaH*E)R=GcT&P^+vkO98E9MzKlAnG$UP zn7m&Hm+MNSI%^sYFT(+wXU0_uw;~~KXI(G5sy>z8f!UcXvX%11uIUYB3acxfFO}B; zgN|tx5_?2@O}thYjrqh4C}7ZQNf>xM-`(Rx=RA;1)q5j^(%|yGr$lDw5>-B_!jUB+ zz3{X&O;bN~kwF`FUj`6W7g4b_ltqi$LSB6%O`40CS=Ec;&awe9auG3qzYUjX37Jr6 z09@Dm`>(%7`78J3Q9Rb&%mQ=q@$K{5$7{VlU$0Nq7et{VDnHDB{CG$1C^lK_)Ws{* z2l}1%tb4`-Ay*`+Cf;7$T?=du=F{fWa}8Gofr1mq?l#L%*%HBZnV7Mfr90lhO45#a zzq%qI>sm52vUoR1y39l!>Ivd<T!}Z~elf`MR3!jistdqci)hJ;Xw*GbEQBj(TL>1E zIn+pMBgB^C-t0_wU31F-03ZNKL_t&#qiBVwuJ!Tl+h2bC9qp5Ja~QHpZNU52dVOA( zzb`Rgo+d$H#c$yaKNjuogB#h5=Qa_RRmtiAmEZtkE9_RzS`&p-ly7{{4$}MAUPH=` zPfy$9>9$7IrnQxct1f_F)9;y;Fv`BUH+e{79+xBHI6^dWQa=($pEKfa?ve2XmbQJ2 z>-xBT>PEhQ@^o#Zcl=&SwEF~=-ta_KN`$l#8IGV5a@y=q&@k+O^rsp_Apm@Zs*|Ig z0|Jq#d$h*jw=VmSG{H#}a$bYFQixci7KM4j%KYT372Vp`86(;UwJ`#H3>A%293SCl z%)<?lT|z)nTG%RN%+%)P;0u^g66!@3Lw7T|0@f@%J;h!9-5E)Vflg$mIx83vFdcA4 zyugB(S7;=JZG+{GtrCQzPs%sIUF1iia8u4AO>Vg)3g&tF5?J88Hee%C54#caFv$&3 zYwdHYRZ^l%_s`4ZK<_-FI~xX3e|fNQ#$2B(VVGg3WaAs$$)qrX!)Wrbb^&KcH*vRr z%YT4)jgU1Bd~Z&cFWU2!m3{|yw6|;j*)Dld6;^M4jt&IkCUs|pb|vP0ldD@>{(+Tv zKTv!dul>g?OSuK-$2s_9Cs&2?dpEaX`N|8k!!!S1x&Dv=+#Cx+%hT`st@NikB28>t z8JuOO`L(lh7rIqQ=`5_Svl%$(T-ni#gui%AcOO@t8h@FI&Z;EZ7F>98r%^q(O#%)t zL0RRYAXZR1^o_8BI&erA+YMmk$;QFwXDSHK$cm{>(KgmrciPXx(jju)j^w%7`mqDF z8h2F5sDfIaJi_AS7apK=jz9UOy~a5v<>H}kTiiROKCbk}&O&E>U=L|tGnnQr%JXqt zTPSI>em89|G&A#!w-CZIQLPJ(zT{u5S9-V{;w*IU8#5SBEtTuOI3DOn@o^S)Gl`(j z9DC0GmIo<RImfwGYd~25%r*k{V+0;f&3r#8aBC+Nq>u%O`#ygyyk1LH%>w;hS=L@l z#jp3<%`Lq|fVh~tsM&J)koEoT?@KMp*g{_~Red>t59kZJ7HwviORg)>h;CW*l9@ey zx+5@B;nhluD+BnDjCTl0o&hL|?KX8HLe^2fTXdI%X?TMwE>3olOI&H_(r1^G8VKrF zAuwsEJ8(@_M$I^BZe_*gs*+5JfQVn0e5g0eJN@F(4HGe0x|S|?zpl57n5Egy#twt0 zt%1`ii#op{wFn0)VOv54x>a2tpP#=%3CpK|POA)nFTGwb{LSn~_&Q`H0~C^H%S0V- zY}I6*srSo||4(HLrFn#GPsIgQ7P~sjeYS6tKM2^W74;Y=JhY0hp3u!et@5VcDDg#B zRi`DNq?5yn)+Kbji91yH{Fk30P)3_8G1O}I<RH8p9du`Ip4S1SeBB{<J6_~I^$Ka{ zR4fV%`ZTARQQa^mU&OdH4IzTbBxN_%ZcXZvqQmK77=z;k#V3&|Xxc=^6BI5Qyb%O% zwl>`OaGt1RLYtCDW~erKe|ktGzoqnkctt7r2}+%P+&+9L=Y`9Lu1`w5A!Da<u;r{C z%K}_g3D^Y8;`DS4!n~Ts*aC&(&(tL<dqlPm3o{v`;l!TQ%(!W~p;1XvE|-gyjS6vz zYKXbe!0>XU!#F9#(@cg#B4%BRQ2Q$4M+<(jK1fF$JrX<l<MiUygt{g0uTFVP=pS)5 zQc>v2=dZf-w__bb`jTQl@>WTOr5juCICUt1*n|hOsf?wWA*_R;(7(8`-Bs<87H)Z# z=;Lm3)~F9*t)tklGwv(QAlqux@0V3KZ(gM-+quHsrg#~W2m3!uXzwfkbP`cd&0?Pz zX2Cc*Ya4Z1?9rF_=N&L|{AND3!pIMfj0w5jPm1`vb)8E-mZ~^`@n<)AV~5Zmt8jrj zBp%ku7e2T@e*HlMctQw9u~`B|L5K*CwIYy=A(*DoPEg!z2i&)mP;~crQ*aG?!$WY$ zyg6%-<Qq$uEqzzuS%!1V?9XbSR&ocj6+&<k<C88?Bu8n^U7tzOB-mR8?i95m@Ky28 zGPXs;eKq|;{^jD6W>}^wP<LU#Y=M_EdnSH>W$9%+q|dOH*P{vo<Cb$X)VNZ8&mXYp zLJED1QRol>m6Fnm=+}@+$zv9ldt1vO^|VtOZqt{KMIHbv5cpIDN+Yb|PXwBFe@0OX z9~GO2kBp+|I&XA$S=kEYi4vlj`M)u^@01fzo_3%Zu4$q%3U^#83r#MSD06jH*KA`J z+$tUy&+JpFtjMMw>3R3klBWJzn(?T!lD(|GxpL_im!psjx$Ph3e8I%7kJsy;|LOIy zmYH4GWf$C50moUmHe5rBk5^U%R(~!0<u9Lq{p-K{^I!k{|MI{7=l}ix{%&qiT}u{3 zbXkyjUUpqSE`Pg=uGB{(qs?#?ri~gJn1x%qtfwlP0Wn1s?9DAt+A+^4Hw2Ew)0a!b z%L_0I)02QqB8N@5#rRbyD0$!~OBsZW1>zN{_K4q7I#G|-PzhAuGoS@gzx?|zpa0kY z@qhgI`>#RH5^)iMimuD-Z-4vyKmGDg>z7|#?EU_g%Nvj-y5bD;PzRw^j9Ems%rSUi z`>W_N&Fnh$i%=)lg)f(vyDC0DKMZQJN-r?zD+_9i<NeZKKR)blX5W25{KX1kOa+N* zb1rHFHJ#$3l_#%qcP#`6$u}NXYd0ZUHWnuWL;Y`II&~j!XTFm%68vBj{*K_V%W$|< zz<DZ0U->cnYyO22Z2A!Uu_*gsAZtS6TtVqKWWv3b594<GXRATp1G}*?oX_<Qb%{<G z_C6}7b|{iTLQDg1oE>=&W2))W7)D)?BlQ1<i!%YN3c0pelY$3*Z;E3fB_TovNkM0X z5b*_wI<9dOnUfu*L{;{}aJ;Ue7u`Gv9qR7^Of*bU2~;7gVXF;o7$V!I;F7L$bAmqH zJBxC2xpJyv30=cuK8&%%eVD+ZRfsXl3dN)7fZAGD4uU$W(x8P$A>deMiyC6lh|rN` zDx%4;iI@9jsm^6-VyW%n;ucnJaMxch7dawP<&IMd^7Qsv4IY5+fIqNIW~yiJ6jE6P zdSq`gsZ7h#e%fE@gLW0D%QlJd;y0?j7FKk*Xv^nSKK)9ddzN5lrs%y%UMZj@sY)%p zcByq2UrzZMtZZd)#wlzxS<C2(O`@5LUe%J)i{!cG{Xi(lxmM30=a80|VnmCyF9vqj zYS{?_YTXk3F5|;8s>8>ZVy!|T+S-0S3N#uq+J6pRi^Y3i_ZuUBJCHb2GdZpb?JRLg z(b0oYa@hCBQit!a{C4BBM{MiJv$g-{Uw_O1w&BeRtI3Ouq?tQCrD>e6S87o{4l3$M zT<gKX2(P#!%GFn+lLj!?Zm6jk(^f&kP7ckr%X~zdg#`#<G)8D>mFZ4z^k6-oVbZ`k zD48Q6L){QDkqdGuaCsd(%Ax{J&)Z~IYfhwi%tTn^34`fT%aJLT01tGHhbp64%T~(4 zFb<()2MPM4VuKjLJwFdNUaaR7WgCeIW$1~9Q0g;Aw*@OGmYtZC45Z;<ERHLK_5(U! zqJu1Da+geDFw<LjRiU=JXAmfE8+H3lSt1<Y-R>RBAXj)60JA*KO0IdOA4NA;<fw=& zqGj74&tAjRq1Fxd&Z7+%xp0osPfV8tW|nwSeROYU_Ca@iJ0{D!(VJ^5PS$4R2uAs$ z+y#tghF-AX-(L9ksp4Xnh-GnJg|4*%KjDhYT?Mc8dad<Ry!86~T>t%l_;>&DKmJdD z{rCUlfBW12{9k_jpV!-<;&PdbUCW^&rdRtujaCv87GMssI5@=-S;QW;Zko!T$Eu|o zA%SKqw33oN(gek2!dk55R|rkZm1Nd%)2zlSA_%CPY!HVmuN#?23Ngq<W0*%JXURm} z1+Z8c$&~C#9kukG;;{JbO;q*!-~RsN$F)9w;ruFIAD@5uXZ`s6aoK<Pm%qyE+vRp$ zSA@LGB#K7{yNcs7hlmHgJzWM_w26y}w7Q@oIQ9s}!O!CDF#-De{B*3~i3wIQ&pJqI zfXjR7kB<-k^>6k=0LaVD5dN2O#yigmkqFXrUZMx6LO8{VP$z3C^j-UOlWr}C%laPx zN2kV<GACaqowKuL&a)A}4;?*?qCT4r=G9$klW}s*XMm^G_8+N|T4VF^Nl7<`ndsWD z_||yClqz*3m4NNjcXZ1rb#^RVoo=UkG|j&;5!<hP%q+3A+oNUy?c2Q>Dc_F?YV?(Q zIPv#L)iIct=&m}APa*OIg(Kib@69p}q;ay<YeCmiGH^FDuzP8-!qdII<lbYS&jUq$ zGDvd*k2L!yg}7Zv1C=nb%>%gB`YYy^+qYN_kcak|Sm>gZuM_6JYdpD#((}cX&FUcs zW<bF>1W?ZzP=cdlmUVdWEzRK2<-#9fX)Sxwi3cZW8^Do9k=z_5>vOj(xCA#%uuC$7 z>4Mu(k=?`bn7XB_o8l@s>I`iPF<j!|lLe8zSz!d|@!9qx1KZm~OnZYycUf*fv8eVB z_kW&_mD`S<e{cT|*JAIyvGMv*Tb(DWvQzT0FWun7_TGa!(vHi+0Vk*Xpol*)rTP%> z-L>Y)Z|cNDfovKru3g#RI}?acigl3*-+P>tIxOffOaEi}J7$3737PCe1N7R+;}!E9 znYr#$hV|&($;tONKbXEZq4DQkf5-qf<KQNXD~+!>urt~jg^y>l9F3d~rf;q<mn<|g z;FOhDc5I}%!R~k}J$@)PotP`5cAbugOnIHfNGe^Dr(xk1ctlNj@}@A|6|AjIGUP=7 z5QmXhSx2*9UJI^*Z+uCd%UWWzoCOKhp4<B&^ig=Hf-WE<U{3$Bvzk$!GV{z9^DC1F z9Ia@S{@5(XV<0Pr#2-;(PPKSbyu9Mu6`d$4jxj!(j2ZJ~UKpWBn7*y3n+t!BGaLiO z)71v@x*JKDu~h6)3O@)b-Wt;4c>&ves1BnLYaQts|Fy<Q*Vgk2{XU&ZTl<fWlo6ZU zmEv=B8OCn4gV~tbpbVI|cL5@zW@eX*x#DV8JjiR|;}zDLxvuwhspv1?K0ZHQAM2&~ z@$u5X{^c+K{-6K)m%se;^)`D)4QH5}cu<1AQB~}_hhPR7n9iKT?RHURG(cUdc6?&+ z+>IH37dt^^#XU_k8PKwhJaBhs%9kcw>Z*mBz=Y0Za`FdDa&1El>Bp!g67FreDkhM6 zLZ-Oor?xpYqQ>)OqThb`r*EIIcT{(B#rpX6&wu@QfBpCW-CzFcUwnN63jyZzz#c~a zxdE4po4jL|BM=;Z7id6bHvKpt+1VN$&6tufHPKwc>*JeK<1@1ib{BP@tFG62eS5!y z-n-n%7m3iE`ht$?@S0ed;eMo<YD~nsZ-ICewj4;FQy@vYyF-?wbIZKVfZU8UQ@&!H z{_WRQN5*il@|fGGVw(%T|6_qJo@-Uu>=GD3F;nrHSk}!Pt*y=1wX#?#ypjdOX>#Yf zt<;QG!dgiq#%E%0y<Z&}7Dh2xCkN$rwuM8q9qUm)VjP@@b$u%0X;yMHWDMXI!b%I% zDJ^5cf#{xwNE?04F-S^e^)!adMH>pfB}?#}Y8GmjA<C)#qu#mmbya(-sFn8MP|F$$ zOdXUH(p)VyvW_rf<1BWNOlHkWvW=As$D=?o%zhjKAq%j19j_o=ML^FrF<jaKXKze| zOCLp>=~f*8)`+~t3evhGN*yIBi3`zZrc#B7F3*FyVlzsy?BXjkw(`WQm0tzJ%-pi3 z-b~Z8TwN4}X-KQpfe>|7N^5b5ExD4|zY0Zp>8pz{>1duwR?drZO~vn!z%1|OEvd*c zC|>IU+u|>4vOP8Y+hN937;HM`n&~#N%2Ot^^Q+Rx3u)BAU$UKhhoUHZ6QPN6lMF2p zigXQlx=V8J23dwOFC91Qu3SaCO*mWIZk3BeqJY4Mo3(eD3vom2`-EP%;|r~>qu<MD zsz1rDTJBW;aty~H?|Fp{rYQX%XMeo}LMZm@=|HRFDPvA;{Lg?TJAyHK!|&)^B2yPF z`+0{_V_T4a;`PT^pj%_^us}(HV(=?RWPk56R@E%PlXY&2Lw7&Ve$o!#w65)%LmBAn z!+q}ii*}gt*02K{Qa;g&G=?AX@GVUY@OC1OPvYb9Pj4qT9bpuFlAC-#(pXl}L91XM zs<8`$tMG<H*wX9gS5$FeZKrKoROnY7g=-Ec2?pSeu#O5#FPK@u$49O>`9dusT4NQ& za=J*bHTyEp_3}FmN``XHJW@5d+-7Z#-eY0CtS{0zQbF<GikUOXJP(7e_ZVZ~+cp{f zM6yA6>9rT|dc8hgFIx*1+U#stt-7Z@@EbZZvt=d@YHpJ$XL(oQ{-Yu@&mlmdFn6;E ziN2dwAyf~$+%Iuo@-2u=mams!nScA#&)53prQcrb<MsLee%ag10X4?HBWCQ5E&C<S zk}CBLE*Q2jy!$2^l086o%&(!Cy563Qi>-q`2%p#n#?oAptWGqIP9WLl!9vk&r6CvY zk7BcAZ&q;0I%Xucei)h})>4gP!wRgxMK1`JBK2`q!CJ46*XJ*~KHMStdHEXvWVwsk zo8^};QvFydDKWQME*-Uhxn}@nbVLnN+3Dy=Ni7!<=*KUgE_$Vw$i!p^Oe4u<t<R5- zZ}0bI<}7-*VNL070@vD}20Vq^h68GUeMy@$FxysNZqWl_&YZLoHMZ}aKX|?SuSXoT zz2{XxA|%7gg<4Sj(qcR9C{3e{&CHM2^bvq|JHF#~PIo2g1sRz0jY|5#Q24By8!O1_ z$>BItN`CXHReNO&&P>A6D5lX~z|f)3HGO7GyN-U@cGUKKDYfTvZzakxaJjT>bG=c+ zF7-4K#atss<0?04L?TNNNm3tGOGwpT3pR{Gx1lOfSae5(AqS~0P(`?gg^^k;YGk^$ z*$B+$=r!q6>J^~=omx%1Kd2n17jD?!rAG&NUO6dMB&>9dKJp+-uuzo(q-H<lvhwzb zyoGmC)O?OlyWxcqGs0psnCR*x6iEM>XlH(*BD$JruL#-27K;$8{Kyg><4yd#bwV;= zrja5pqT;XAXPe4|CE=vgwup&aOn8dfG~x%dIx!tdfl7UaM=ooZSi-Z#FNuhB;I30) z(}X4=YUy2MV2$C41*k3pz0k@Mi?uraL~Wl?2ouOT&d4bqOO4l&q*jhX6<H1!z4pYk za(39Qv~)abQSQBkK%K4|8l6=O&wS#`k$jXca8>wh+cf*96H{-0VOr8AkwknA40CN9 zW?FgHo$^t}kLPD<LzPL?rZ3G=7Y{hw7y@v+fht#ar@0U1-I~vs3v64gY;vBlwd=9a zT2O5)%UlMZ*{{{++VVS#lgtF>t)$M-FRRewbm<N``EOwT{&5!Qf1ql!Q1BP6k1*jR z_^k)0<zOW`MOv-dB8VR8bMevZ=74YJs@UO@c=TbT&XrK0k$z#tv<_;rQo{0FS1glJ z6mhl^36YNyp{!zm=aDab#X6WyF^~CfZ5L%{calA^g;DEsK_ON)Ge*xjls-dSLq+nk zsGE_i0H7}0V@j>@D7TXYk3Ck?UE(#iay((T#-CSO8;z~Y9qS0^cNAWloZ;ii#K0UD zd;8S)&u86H41qp98YSZj?=Us$iAdaz)9N2YMo5=jZ0$L$EPAcm3m{b;X`NrnQ*&I0 zp~7>-=eKiYk_3h}!WWY>B0mev>yJkIm04bDaTY1$CGVH(=aSF0zAb!P>)Y$&<Mn#K zuj_r81Iroaj?$~{1OBI|LL3UX2?6#u+eus#$s2#z*xLZ~O^rc`cWB^GyRi#zUq1a< zDo})Po)#bncY>WVwGd5zwT5yTH!juXjDRWxDynS&ryYWq>QYii15loH4qVW%l!5gY zT<^DBB3R4c>Tjk&x`+e;4SQ4>p^1`+h=-XZXILWc6Z&b!T@Mv|N&bfT;WWeH5o8zn z`1lr2Ga<!$x+@}WenCI<^>Nt`oA@to8EjJtaq@ggx{$q{p@gWoNfh7qEjmq%5}(*M zK(5>BV{!*n+%;d=jVlxJX*0;(mi|o_%_`y^Yv0W{!!#79K|VKg*rGO$gS&+-`{#!+ ztxgm&$mvd<^a1(C^HeCCHo;uvLGd9{8s%6gRQWz>?Ih)ak8Vyv*V%`?4#mSE(j7$d zNX!hzp8yNz=cV#mna4;P;_^6*-+OU!0kTH2+_rcQUi$DVkLI@#x7RD;@$GPv#s$~g zk4##x)ecUI)sr`|j@}R9+GaB`N?RF;CBuO1<70B<@?awU)wr6$E6?rl@>rj<xr+4M zMW~^OnU7)(wNP7IOW%F>eGX}sgQi$0S9QJ}NYi(!J}hDZ$hXXLf~i^%V~H<71#cE* zD1dRzgEhfu=~c{ILiW_e%_}VA30|u_<Zx1`yNkLnkxN|ERuqEDkW7Mfv;xS)g?Dvk znPeHvNZwaV?Ez{Uy-<H5+Cpf*xYDRlCAs00V9Lec&_8LPV|bbx9LL11rglhwQ{`lD zjD6v+zRcgd6AHV)ysM)}Ej`90&JNG@rnLGtsVE6ql6_@<6?cj2+8)2z0OfhHJRLUK z{x~6r%%`8iWypb+@H|tFAXC{IjBod&9^Y6!z1Iuqj))Y<Yf8U*`2Y6|;D0pS9T+<Y zeFvL;ZAjzx&xc<UH887H`ja~1`(LJ3RT<}g`+d>+{H%ommW%UXue_4YF*E&Gxqn*~ z0Ht;^7<C&qv+WF`i|lBEeo@73Zev@>slKay$m!8fBY9t@nV3RlVhEHJ{*4{tkfiop zX}z-{s5roJz#cu>r{lg7hF_}rCY+YW7(qYg^qfs1DltX_`?{^cKbBBS%!Ywi(pEl; zD&uaAj^UtU!~^MRC`1Hi=2mzp+uJgX=X~2wbn!WK;}f4h_)4hVjbULNfC>D05*Y}1 zhsXl1rY=s{kOC6PRq1KB1^Za9PnA!_=fcOrf?V(KcD-FzRO1Z@fPvZy=i)*J=#mbn zy$pA;oBDU=ctPgs&2-p&vQ29H#?_6jij60kJ0gghqz%Ew?A7T#4Nf}msCpu8-LkXB z6r>Q*3L=+~8Vkz(;*21yKN8xCxS6ZJ1CCV{6if4fII<Y^@asGMSmYGUoVCzzQu)@H z6(rCLfT%8aEwl0hzJ2?))=GDrC$E~2f>fZY3((7wDt#=|M0stQ6dUczgTO!CN@<9K z`6Kz8oJLf}RF}IcCnKf_K_v#am)<vV>1XE`UteR=lbpuO((n!G&ELddRW<=wx!K4p zo~;W%v4MA=(bo7hq_;$s%~Cx@M^mJd8HBZkD5>TWN7ZS&7b6L!Ip{`9l`M(1y_5|; zJF;I9nVG+tGXE!9T`c<-?Z%2aQbQ~QnRg@?cVvMI;4hO)oaXm-9oBp@&--wGjyQS9 zh>G?*k|b`5E|r^FGSb?O`S8Q(&;;+*-=x^A1b9*wl_z5GLYJBo-_0YDw^QJBd-5FG zQ5$kvs*|d?A09Yk7Z-VTiv9rNddB~ZxZF7)N&_IZxItIW0IBMsY0zSgW8_0JL`KI4 zs@ju4-c>V+^Bc}S!=e#bk8>xGP~nSc%Em#{y-oCZx)+1Sg@FhApl){2zV3A6h#`+i z#!$#}Y5T+&lrSN(IvHWpDWBN&CumutVS_bp@N&^g>{Y-e$Mqd7iHj_2Mw$%mYDqq! zM#2->xI51Ia=(abp$Fd&f%%0xiW;9qf8wk_88n);x+*umRD+6z^0eyw<gX5enPxTV z3F=4;H;n@`V&6mm^kmA4JZ?YQcpmUf?j75xzxqHS$fZ+=hd1^?XRN%%J-NES9fGLO zwRyVzn^?bp+yK58@ypAJ0U!y|`F#aap1y4a(IGnNl$ryC(ULjk1x?(22_w?8KeiFb zN0U&V=JT4z4;gKU>+Ui%;iB<c@2Q_w+a`csgo>HB4<^MDv#rp}?hxWWkmxo}l>E{* z6`>@86Quw48SL%BkwJO{X`a(E$~XG1v214;q5kU>HEJ&pOWge**4V(Ym)b8YSJ}At z)iv0~x8=v$8^ZJ?FxF8%YjiL2Oyvyv2n?2wyWY4(6}G0L(3^#s*xH+7H<yx`8PkEx zhTeG&->}Cj@nZ`5o1Qnf$unhzQ0)FhWFO#pC!t61d;yl)Q*e-g#p<J|kV2M1A+IG% zBS~04UNE`dKYn$8^PJ2ek|$@Aalcs}2YEUwK}KGLjB^oWwVukEXd|}ZT|8i<P2}cg z>2=$r(!>RZRjC;@&3;CeX$63&H|e#Of@t0=o)bq?hW5SrGu+Bf6IF$X2HRjjpF;*I z=*-CkeFS_utqgTH@ykpdN#z1Sv6zahX#j_>&fWdW=R*84@8r4|-vD_!T?uZYnG2Rb zfvSqH#5ynh5dHY}p=<dMp+6^dnq+@*5!Gcb@3*-Z05ALjI&Af^O`c>05R74yZD?Si zi=uPiN7Hs`v#p<8I>>LS0Cc|eH(Z-A98eJwFB}-9!<mJmjIJ-I!~S++Jh#7aK#vxn zp99j_yzNUG(1#j?aXbA9vK{dl5^yh)v^|ZfK#+bBZ5)5-oiSr}cSDe<Pb4YnJng_a zwo}~QWM)c)VkAc6vYP~ta(Ik3C30-H;u81UdwGf#A-sE>0CRxb93AHiKRm4PvCQ2& zWEv%O6TcR9@_H7l2TfnWq-Zvxi&PD;OiW7Qw}n~~;h!#N+j@u&R<Jqssn;9}jMgtB z*i!s5GFrv<pAv)<lBgfwlIg1PDQr=A)dKOktN5o#CfkoysChc&NGn4EEFK}WO1;?B zSS>6K;1`iNhK|?DP%dczQ&$V0B>Y3f0!yEaqsclLeO(z0X?C8JqDejL{lBu=;JG$? zt89t@03ZNKL_t(4;8Di2M=|Ep{2^J4pbGT~f#S7D0zjFM#o-}N-bzVymvJ2>z=24p z?Kl9^RAxmtuVe%lb2=%6i+|j^?bF-J93}3-`Q`d_?~)Uopd*kl(+q1^#`n)J4FzT^ z9fa{!vHtAF&e5Hx<FcHF+xI1$YDwIEXSFrEc<27jE&5WKIR4bzO#t4?<NaRP)bF|e zm;sE#0N%8I2_B|rpZ8W%;iezF<O@r6EGgZgaOnJm1_F`s-xb(vcpU9Uwddg!{UT>F z`x%Kf{-7vuWrp!-N#s|ukf-lq$c?ovwODC4dg^t35cs}beFKHwhkx=JR8Pa>Sj0^? zC@$N(>;3ayU`)p_hW9sD&7`{;C*$5~-WR)W$lrlMpA%PJiSrqW*Ybx)Vsn3hm5K(M zs~(<g&*e6&<9{efn^3(TP~P1pl`)6M`LW4`F`w=N8yK6`baMewB}9Kff8MqRPzdU( z;r8{WesFlTmf{655N-(LVH)F$YH(0lYaHAV4R$3}td$1aTJn17da2?4e*X}&;A28C zd<ce?5cJ3wX?UZk=1$ZM8Tx1p<$y<GTiM=Xy(cnuU29P!iVowQO2Cp(GsL6TRqDdw zy4DMkExBQh2q_GwHH;DI%j8mhiKwS*ne;m@VF1VF_yJkKLRi;O)uaY-2|S*-MhdaV zJ~dZ``ZD4cRB^EqYDTQptB9xp`7X1IWlJNR*!VZ0o@9mmB#EJ$Mok@uis)NpsVdgx zu*@5e|3X(Y7uU5ev-kV5tng7z41&i`_vHpr8>Ci`ShZff3?6iBXKaVDUe0aeKiww( z`m3C7Pau?2ln>2dc>m@vx7+8LGMhbp$^%a2g@2n0oNvQ2^`0$L@6iS>88@xF>gJOW zyk|$r)Q!qe$=;prLqEr@pN8@%44rjTyjqppb=g=qHXb=&+dp$Z#_Gu3qB1y#=}<%K zV;VTQ^0iXBXh?uIVE?1=4PWV`<?{_o;V|-#v$&t(<g}>qB)cQ#oaQ)5Er#=HZGJ!O zoeJJQoSSLLY@hh14s@8LY^41uR6nYD-Q^y!yVhsNk|rCIi6dB`C5*I*8FBzC4-D5) z3&6Q)u2$r-9~X^ez|^bI!@j&koJ7{>Eb=a=wBUn<k-BH)!wR)?2(4bRKvxJuE{Opm zvOu!dfFrrAr7dW2^|0?TcFi>NmgHG!8&?mew}Ot&Z6nZ0_FxD#h=7jK+!SD<Ay{u( zxZ~4Y^gSbBUmssA%Q*pzKzlDdXMM9)8n;D<{Sm*-FN)J=DO@{3q&LOiS0Uf+HQX$| zuYW&;@V?Uh+$OS((j0`t>HwyJ?YFT#yo&o9{_U?nB?63!g^#ZSi}>uDce%WOCKNpJ zjDg6fw~B9(A<B-ZtQYA`D*;SnOIFDNRX+^81GGFG|B@<Hw&$jZglMqgCfO{~o_2Fu zO|{PAUSH$K>1d_7l|~~y-t}rLy9=keZZ6lbgAT-Vk*M^fq<c(E<Q<lZ)2XyyI&PUK z`dq$jsT2?Mn4rdZe?=#@Yiw06OXfbw#*AY?_D7XM^Ti%2+#qYE%+*llW%<VA?bv!c zt70N&r26IabI;NCdi7KpCvx@P5s~t#vH(V{fy_v(Fv#XG8{?4OiM<o<Tjtu$WN+Ar z4<FT!wt=DF^vKZYZIucDf<-2yz~<tjd5FiVP!%YGGg$yJsHj4hO2qk=u8*}|_-^0L zqK2eJB2^k&!TeE4-B|-!(V@AEu3BLDbjsRws+4tp<y>0S+}qc7Bbm!`2Ju(S<TK9? z#NDcBVcLh5q*Jf@gljc2YfZ$U$!Nf~U2DDUx*UNuT-ACri<}Gd3!<utU<9EkA`UFz z1-LE?pi}^q-F4~mkD$F)h{83|#%W!uCa^Pe;Z$|4m0moUDnwSer8Q}GvIe7>0phsA ztLW||DTS!IEWhlVzlA;}bKWUYu-#llm%90n_uKpfInUY}-k~^j7Tr!ANey-14)YXn zuE5d<&>EYMc!f|R)i%Kv3Ayc*fAs<03#MgAiN@XIyi5L)llNE8gswwFI(>B<$x-5< zHVy_cNyDw@xA%^4U?F|)_UfCD7XEbl)J>&N+ie7V&}!5G`cxX2BQtO@@p1dpaVUc0 z@53m~+dFRd)E;BrZff6?&19q~`&g^>zG=-8_JVMHd5UzNDyrqyED*1|p`g3jYe%}0 z_~hX^QVOe^^4d-r#mrqxgR}UVb2RY09fSwaPhf+ah7GEFf%|CR)OO+zHJYT-+quR| zRR_{{5jAiCgNikvR>FO=fU6k=^g{b5?)$OMo0WFi$h1mpz-ps0dkQLk1?6BE&m?g6 zHr$;p^sGJ51ChN~YGYPW4dS7Usml^R%LF7MUAM{B*^rJ}=bjvtBj!xgJsvA8UIaRr zl9(FBJ_`*)x;GU(k404W?>3I~curJBEtK(?`W<)WDB9ORn0N@7^?hhh@k=^}4r8Is z&RU(f6_V94Mx2VPt0d@H;^R7qqiXMv5`W{V?ZC{iksc-g@Wtd0G>f53W&6CQmVP{T zw(Z<#XvZR3JwaDJu;b|Lc-Y}@l}%vYBB{TdP~++PgAri<WosK%>Qu<WRyoq}XyzTy zsiUFIm_wf!MHjYqV7Ii3L%8+V{l|~9&R;y(ME8ptO4K(O=K0O|X|bi5iCy9*=1798 zHL#|H5c|F5+kwjB;C%}D)}Ed8c<3NJhC3(0JsDqx4sPlRhqrrfp1nOj2lG_C;Kkiq z!%hYlnMF9py_@E7oO5^kaHfZq^6}-IK5Bj=Cwk<xFo$#W=*ZRpwoeXZ!D%;Q^UZbi z?<ZQ`==#hLi+VK|OUo9JX1X~*MQf+;+uF8I$|lS1+hiNDTL<TSHA)90HFB5B%o5EN z45eP&wM#PonW$)ms=t=JR9*|8OJ8f*54S70Os^rcc`SBQt4?W9O;Xn9&O)~=o7;YZ z&6PoAY7PZhr*<DAslaFI1tn=*oW(!-_g2I_o+;0zq{AFPGW!?h;S#~+ekF<*Dhfq9 z+Fb0qF3Ad{YEa;!9>9~)6|%zg<$poZqfpqdped6^Zz;9FTKI5jep&!)EqYHbqynK3 z23nEDpA#JjF9x8%ZC;mK28Q3S>xW%GT>O%#Py)w?W#KZppg%tU<-g(E+g<&wa`|4w zs7j63TG*m!TSnO-PwuA)q<IbI9?_@YAKT=By8J}={O-%!Cc0DBKfdTF9kD%ZwEU|d z%pSR%0`Pdg-9Gv1r8UBVK#9|k)k+`l+9KOu_vQAJA^(RHc4sA|V`+_UdZNj`3<u3m zi(z|;)-MNkxGsL$moLA~(NpDni|^CL_n<38Q?U=n=*s?%RQW04L<CD&b}Rk6si_qJ zctV#4f6sOSBxz$uo?RgmEh4O>%D#-#%AO_{Masqa+B`jLtCo9rZt(p<G6>jk)2fGI z^GsPszYoLH^p^pSDqyzhE78J1z1uUMLEeniCP{IfG7v+!0*T|jrRFVSEL&k1z~#DD znQ_$itlTFaY!Bi^r<7q*XZ4DBZaNuv<mPnMxCdLcxQ_B{EXyROSs^Sb<ws|jQ92Q9 zbL{ebdPpBl1V;~N0I9<XjxmQp98h2-9mGyQ5#2PHrMxO-Wmp|Ew?(qpn0q|dZ<yJ~ z>-iYM5D4r@=2Sl>U+=wWaowaR*l<j@j(i2uj4%J8vR%gZgp1E_4+Xp22Y-TD``fQS z#sZBJB~qtLLzl<G+z*T)gJkkF%xzjCvgD(Z^I~H6r>9(-Fs;TH^Wax0rgbNN045+g z>A2b<nxK&GH2-2EBDT~a;!9pC3KugUCruqKCi2dL2eu$8>H!h2)GpqUutOPp8zk*Z zT(>ph3Db^)q$-0FenO+OTq-A`Yyf9R$|^Z$xIDz1*_p_$Eg-fD%;})mee`S%=_g%q zmGj=rjoYw0iL7Pq+i!Cv1flLe0%h@zQ<h2|y!+zicIiMw{;4G_979L*w7G;*)e9(C zlc>{Caf4}XsyzoM-t{8Aa}?Mx_aKCPn_NV8(N}`1BNFE1H1P&$w4=i3;!{kIZQ|3- zR1t66@(%WarTW+=NB9U_?CowD|8)~rF%?;^%kj!asgUAWBVkos-51tN*8BVStLiv3 z7%|pNl{{i0sPy4i70sNK(c#Op(rDXM&DI<#lu2OFQ!^*YLUy$-8LC9BjbawDD?{FF zMtDbsrNxq_x*Y|KVRY~#f=EIfuV-8*u<9nb+}!;oa8au;TY37$;qtDEM5H#&_nIsL z1K{1m0=_QkGB5$`Qs6}~+m@kSbA$V3zZO+XSgK}b_BJy&_#1BD<@)~P@BdA%x4XOP zdo5RgVd>jHF8j;-^`G9q`2Y4_|MtdGF_9}_j9!Ts6znD<C{_}7pinfqHi{f5-2-vU zpw8)zA9i5r?p$<@C0MCy`}i@cruW?Mzw1N~9Tk-Pu|t%WPviD)4soSdt__}XZBup= ztu^UGBk@^Ob~-Do=$Z^{)E62ggNN=Fc}S@>Tvta}kDT_M19gl~pAH9-D-kY~QMb`E zGB%aVRr!7`!F5+#8D+Yazsg&7uIX_>7B!gr_-q}yJ;BF^RVKFzzrQ`{h{jq)Rni_x zbH>e_WFNT!yyh|SaTdZkgt0UXzXYH{bg)bb?ML^-W-!crTbKC&sQ5@s2xuEFPb6wZ zm?!o3HX1W_+EM*1AW%ddhiN@^?pn!nd`=Jn4K1w$tuLjHo*gOfjIKJ<lji%(`V4sN zmj(-@x&y8f;d@b+EBTF*P&^8Vj4}1aGi#pUo>Q{{=tiB0Od|<JQDLgf$Dm!}S7HF8 z`f)uLwjICS!;;Gk;?cr{I1-a+OAJo2>4&@+9HLufOhjZ=q3klWYXnHVLt-k7yaNDP z-N)>xzXfs1f#&Es=7ssRcZNTNRS$yKj*Z{Ayr*S+!0YZ?esC5R1-i@<ZsWuO0r1bs zYxBufmT9u1`vzw_+e1P6Y_uPYR(GG5%M?&PD7Cgt5Z_v6*r#DQ(o+77uRj<8#?!yn z&?Ndxu7=b!OSZZc8p6}O#U2F(qoZgxfj+D52_D^+a$k+?pRgt~gMJ<}_e;BG(bkbV z4y8O(Zk3HNw5pjqN*+f`i`cPb?CFxukFnovky#hzqjQ}}k4_$r+n7|V#^>drz=q|6 zjNM3ckW+wt@n)Cz;qx){k0U&duKM9UVRwIEA4osh8QGqWZ13M@(V4Ln_ko>$n@I<S z-Q+o%SO1=a#s!eV9or9O&gsMI9nSJnF3=o7+r8Me&pY8kX{cq;3XUhtuJuWFZebUB zdUyp-ju=Y5!W}H#l3s1n2-YSIa90-kSy&<a*HTse_1DX)Tr9dDEOF(>OLvACBF5(d z_G}@<qc_&s!*oG{$v1}{>q{gfln4*Ubg}73g_?ACbZ-#=NkF#0(?z0=o>U=a32}(- zeia=g;3NdMKw;P7J|-ygbqBUJ11cGzW`fml<a=_iz`W@tW8N+iVF~WM%ti$Zaq}PM zCR-H3GuZ$tOC2A&^xNnEpnfg*3%XQ4K0bA=kJtL;^R@onzx?O-U;fK~`rF^}&0fD; z@_9MdC=xnmZrdi+X&)*`!vrA2H>T(w1?Vf<bE@4n^DP+|gWAM$@1c^Df8ffYyUub! z1Mjyt()a(4UsfRJhP62#NT406ith+M_g%Mvaz1T34SPthv0<t>*^|z64uYR8Z#8kW zS=s=TmZ?KOV^ViIe5SqqAja7|-zT>Vzs;}q1FqGKc+{$F*{>fv7w`~JXvKi*8R;20 zJpwhd^$)M?$6EakWF@xrrF+}J0vA_YnIcM4v)oQ8MN&Zv2Yn%SK?cA~!hFix&eVmb z(PDN1W+I^%6GwSuYA~C%3xkg#L~GYr6b2rf!ulB4nG)>22@5Kv72K;5_cFcJF+LSq zj6GwRcEZSng-ouXUgT^XMARz-FkXou&;fACjwC`gyS1;(`th3f_z{8JWQQxsn2dq~ zxT&vMEi2fe-|5qjHb^0gi_nr7V6M`9Hb{qFjK`t=`U~RfZ;Yi*f|bBbPub#~fhGzO z^$Wq@>YeH=On*%zvuNa3H;<`A0cs-|Eh~5v2$hy-o8p_U>RX6-teG6$4Zzr@%p_Ia zru#Ud#^1l@9HlhQ+kMl3(O#aO`$HV<8YWDNVOylQ?)Hw1RoZ&saTFeZw#G{ZVvFmH zlW;mfkBvEvpyMyMj{K?DA2NWSg66}7c<>7A<5zqReJAB~f$xKLj=)W8c~m>9H1kDw zom2t0GM1kF^cD6Trr3yZ=BtzXrCcdhku{uQu`1MEt)o4}lbpzwn~Bjcje$*?dmeVk zr2FJj&ByhQ<c%ylbOWNxn6G_k*&HG|5V0=0&HNbod0%w-k#eja8y{X|jjv*ob5agd zByQQ*@b<@+9P;Y>7+Y>~nYA>wjyw%SDK3w7fTyF5zrk=|I}TNNZ_mRRCTBpdy()FZ zqN~}=sE!~RrgIy+rVhJp(N<d1P%P%K)a@p?#$aNIp+~P)AF)Rc8{ZE%km)(Wxy+_j zPV3@GEyz+Vg{tanEkOVF_wSc^hAh15h+erDHVjYcpKyVwAzhE@6X8GHS<hqZ#}@EE zE*|Q=yvOKHJv$$zZ72b9-zfbO1H=TAMQ_A9;zQ&4l4_k!cQ}hpl_@))PFS^3Q7NB! zIOO{-@`SLPqkuL$4DpLGrRsb=A^WTHQN3V7auRa^OR)f7Dz6WHDHgC)*IG+IWPN_T zK0ZIzx6k!o<-`82wto4c-`@T*aoDdq&uAGt=yArH`zmaPpm6oEN5b`Lm6$g)<9izX z_)9`OuG~u4x5>@x_C-wWt7~9wz_^w(Z@)E276=t83b^VpDl3yUODgL%3vVXE2(?YQ z%+4;afk~Olic#mP8z;;pTC2^h(}P(aTf2|b{^O26leZsZHx)#s@F}7D4*Kf{NoyVS z@AHKzc0H1oGKPAH+tq_yu#QNBETY8TGyNY+e|H{cJ$AStk1)7xqKT#~7eI`N4sdGW zAex(sD<O-fruV7z)S#=?U^7An=cOw5kkt=l<1@y<kwDo<ZVo2HI5hy0JGhXIx$@*E zM7g#sD0Jq?m)~%%x5lAlN?mXUL|+idTX-!kDNh7SWfE|Ov^z3^W{DfG6$K+~r;9=- z?rdTQhH4%It7ARy6xN=~UgA)U-Pa&TAgzGYgjT93<s0SPp&nR<v4fy-Pvj4)Qfc6f z=1`i$1fFF9T%z_oiLv5s3#zj;uy8bU3YLx)Ug~-vUAtTpf6f_kK;GG}CV?zAW~XZ> z>#KS6ERrbw3Kugb)+Qs;re)Wsvw|*(08QW$g~$&Pb$bI2%iwQE6Haq(a^j6cq^-nC z_&F#iycQMzUSpVA^ca)*#ux|f%_|IK=k0p7uHFI?l?fLZSXd-0T35py2#<W>L|7bx zyT-dc{Qa($kHcta3*Br>^nAjjYGmpvqp39HAuut9vFk|Py`O*P_2(MEoLyin1zz6j zp!s!lhAHWV(U{nhmi|2`-G=!8S&8S?p1kRrbLstqQ?bhSQgGvedZZNMWZpNUdSAM% zJD^$72+IW)kr6Qp@6%4pv6;=@-dKHd!fvw?eS2i5l~M*l%7U*j5<9?So39aLnPH7> z1K*q!(td#lk{D73iiqHijFQ<f6d%_5v<E`xI2VEsA>}r0U_J@k$h50+bFbVS?4uOh z){^6~CR(=HQM>ZKCU;!Ti3Tb+O1;ogAhz&+xV9(}w4dc1k^Q}>V^~k8&x!Lf>aVqT zo_f)}OITDVFqL0P)EvckQ3Oo{>?yr74i9=$MUr9ZYb^-={`c>1ahF9XV+@f&u6<XO z#ycGWRn0Y6qto5YvL9@f6xCw+i5`0Dq7tN?^`84SNrXuaFBcf5D`CtL>I`OS;+h)n z9g|BuQp8rCj)}oLeJewV?aWVO)uuX?!IX|Xv;BpGRmx$)Wl~6nEqks4)uJF#j7yQ; z4Ali)x?XExDPEtikB^VnT5G*@y;NT&ABwfq#jo$zWrEArr8@P9d|L%Kl1l4dQ{d5d z73n&0E|mqx17Of&#sXNqq~^eSiG9*R_rO1%LBHqns*6)CLA@91o1n|BL}e9aaJnG0 zoN3^eg+PlvfeW+2M@)GCs%N2OdzmXUJ)}?7G9gli1ZZ<ly5_M(9j<SjCii@7T{xRm z)j`h-nU&tVe%M`Gy!_5hGK?s%nwgbRRp8q^>@c64UV@{tAdZF=zY%{kr-14J!+r|Z zTP-2C-&NULIW<`_T8r!lXrBdCBpj4d8h<I!A)Q>+D7RRa&)9fq&jQQW<b)wmO9ZvV zjdbL(l@(yzrekz{*N+|b9>{W@0tpWHH8_oi!v)f5WF-qT969Ro$mYx7vEVLO6h7kW ztufp&AR~he`vRjD(#v3ke?cP5Qkj^^Osjs-HN|{e#`A|V3q<mr!dX{0vqQlnPs)=L zrSYI;7ZairYfx8N(;dr7qYSKiJ^f-D2xRhfMC~OvD-~;vEa)g}BuT&qi_Bs8;J%LG zFcn!;2^?kEJJW~)x}V_vxw*2Se9m%PcU2og6oI3x)mC~=Jz~!XY$dI%1s$_rV$hS7 zxwbq?+|Bc7-gr}?dtXbf`K~x7GK|C4VQRycf<=v;WR`V0K$3l>H^`y>ZRXL|ybTSB zPP>p}e8%Yc?A>voJmeDZd#B$uw(6gG{V@o1r#t!(8I(aAvVulkZb3bbF{<F~qmETI zE+z0GZt@n6h@i%kkDzSDRCjm`@I092MCpn_RfpX)ZoQVw1cD$w4LDB}8_5<aRM!f2 z8HnPtOET0|<>TfX`_yC+@|$VoHO2$6*v;N-`+Y31EvM};E>-)IUhy|IOKQv28Ss$s zGvH6;7diU?!cht?)#b~^^Nvl0esJ`8bCVC1Yd)afIJz@XPba|RR$QU6tf<xAV7q-; zjP{8iwq><qA9mRr+)Zgf7wXI=5Z2PYt|Ncr9-F-z485DYB=b!tqbK;ONcCNK<=!YS z?@(ph9#A)l+Lft?RK<)khS`juqf|lINUGvufB*jd@(3}M$K6$!og~K!oE^y(2+<*h zYf@M_Bh}Xq-$fhujj21THA2XB3~2wQI|S>%yL83TeVRP6DC?NP&2I5JCtO*k^nf<Z z#sOJ5gShKsd^C8lV*Su+4Iqi8uo93gvoRxS0askNUzZY*vEC2mfJE^mAiNnbte3vl z>tpF!SP)&8s_TNjATM{Qz^oky3K2KBx!Ekw>hAjvYV7@P{T5kW4cdKcP)+ZtAH)Zq zsgQjraQ;Oa7?NDq{Y=?k@w<*~O`r`1p>aNFcaw9|<ZmK~f-Q>MKXRg<DuTVA2e<1M z^_@T766!27xXydYdWh)|9FIj&I^*^h9XVsiV`<d&%6v2|4|(hN^OQcO8g^kS8g|B= zQX&t>4`YKHMH%+?R5b+K*Ilf{i?<k8%}*x9i8Z-rm{;Ol#mPD5b+XMfy(gu{XaujE z>4jlgd0DyT#e-_u6=7G?C+L~Oi*7>~s*!fmZOoAyU~SBr3#%&!wVr#ehY+Z}yQ`o> z$@HFtjj+ujsM$Or&=njGz&vPwz>|so(YNJ1pO3HR(Kc!rC7gD63IxOA-Sp-zCfCYd zJShsxFK%(9$6+AOpc&~OTvj!wf}xmMmS}4Imad{Ha~IVx?O>yns$5<JPCZODg1u39 zfM-2LM<?Y*I!@xU8(M-q0d#c;OU2=4U9t;W{-EIg8b%x`7%#WL_QPD<#H`@cIQCk~ zlMxv{c65w20p}YCrQ&n3<<Wd~y=;be(n~59RAJX%hfTY$sQJLfwKa{{ty8(WFvaXx znYg4p3*E=zJjzV9gRLM#%{80tlD^S&m(snd$@BY7pegsV?XCT{y8d7pq<KBg)85@y zi*Lu?z4*bs<1?E^c!YUnq7;F{qY>QmPHSRD5(*H1+)$*H56WxC)ZEP95UiMe1#?pL z+h2ZJYl+Ae^hI0^fxg&NLor@jYTT@>Q2vsGQSdfK4~pJo^?dBe<I^Va^{x!fpWX9L zkNxKRxBQ!9Dy+A?(KklwG})~vx27@QD(TNUGMt)r>(0F+dHmJMPI%8(BB=)d_K<TU z%-HxN%PWtPVTl3aewkmRknC@qlv+-Z3~+MWY(um)@#(Rfy*f-|jPc*c7H;m><z~KU zs+@JE6ISTrZ^(km0u)#P#Q*;5ufx)13KC>>e*I9Xo1w?uj5dRh^S)Jy^pT=m$R~;D zRM&Xm9RoI;QZn%By>5NTna4q{KwLkXGL0m2s&p3I@&7s>R_;2!?{pGFddI0Ohhb>- zP!QaeeNxq<=&mpX%oiyXMfeO+;B&171%RarK=rlO$67B}byZo4m#VHP4Q-<0OA$4c zLrz*AynZPxVO8gXFT;<D%;<>A?KF8h7m_HBD<XsA>bd94nMgTtMwP`=t+;Ey=id1} zHgM6IY%`mOMsuQ2rg6462q;nh(uVz@JFY(86u|p%O>frT$Y}!)(0C4u?_bpl+Z~12 zsi!cXxt}=w*g`+fa*03Jldi9%<Y**vd}giJ7HbLg-9y(2P94H_3Zm-E?exqKrsd4> z#I~@uhSnkJ*U)sOSC>z=zawXdnp2uFIwl3Oxe`LJZU2I&SsJb}E<E4Iyzr1UirsNP zno8DUqm^@~-c$m***uzY)t7(^xnCj+jjWyqL^B@jbIm|5nAAE|!(3Wb+gNgY%d{fq zHIS|k9HK`phM4g+bu^AZ4U~0M(hG*#(QgmxM5qX|&;|%WKLwMETx2@~yQ3_-&>e|- z@3rOQ;kVd~VuM$hz_Kb{jzmGI!hckp<Vc;(ug;Hc#6d`{D2&p?w-cTP-la-m001BW zNkl<ZWU@~FSmWep+0hrtQKoL@OyhDFF~eIR0*jiZj!Pgqa;L_8*@)PW+;o`{?~0zy z0k3&nn|$8a3O_kQxX+-W=@<G!z9npyqqjC3WeS5uNE$X9r&W$fusUQZMvtbMR?%z< zaIwbSKnnnW>&$QyJoM#Yy_v;s=Be@LUw_a5p2FIPY}Nf+XHccmgr>izb>-3<`|f?P zaLiDo26$EhWunXW*jAA6DvkDtV35VvnC~IfgW(>mc$L!<v#6eUhbt;sM%5E6d40UH zIau%ab(!hP8cEI8mp;wV7ZHV#ipG%J8=La&-DPjc>wP-riM!`hZ8pGwuWYx^tv(mx z7K-1~j0Iw>rHNj_s6?qY74oqiaHHP#+?Tnosz-_>uNjo|GPh7SGf!KoKs3`we|C*s z+G^a!bGx7Gwba)X6t{{6;6}*xLtQq$&TmVC7m>y2i<z65jV!6JI<imV$VY`}W9-jm zQ0;llvc8L8BZbLS_3G_Lqfg0Sy~5W^J)l_l>*OO>v70y)z7|yR>yPh+Y2sOGl9Z$q z??<q15GHqnV+HQ^5Dc!8oEgS}SLWWVth?+6ZL6}=6gUEs7KVpwCdqDF7rD=iOe>{U zI7FKuvG2_Z3Jh4g>o#i&f)%4(bXrC9LzTs$lkiU>;A=5u8M!U?g{-xhm4|gpDrT^k z#99$aj(lznS*DO*)@!K-hgp<Vda1r3YS2hrlk$8e$j{(`a~o^2Y>eD%YmUi~PKTLc z<_@TavuranZWdqBw^fNo#wkQDdbo{RX>K28WPQ0!jshwpH~TkUb+jFR!vHE)uXo3# zR}VqA(4mWb?HZQDHM56z&fkx1RSj;spxK&Q?FXgjl;=OGKZIfS@Wzc6<f~nVA%IyZ z?kO2(6A?oF<bk_n@5|AVEwXaMCB@I~KG40j<Hy~&`ox*`D(O6&YTMz7h#NE)@WV?d z#GvrNXTKP8tk!rQUwZfAjfQvw>*Aw|NA~L#8F=-l45=+6G1{i%DBpjYL_U-h<(%k6 z;yW?5@5A*4Ywm*!VrnC&y>$C<-o?FKXjpmVPr>ak$3alW$vy!2>Bv`NYkTU>)m3kA zsXiMs@{OzGU=`o`rE)5HC?=1(@H9Cl3*u|)vF=TBMrIH78qZP@qp)74wu-nIT^m`- zAkjx-(EM^sg<M=Nv#8DDZVH&df;KFm;mnQq9;N1zNqiUza2Sfpvdyn?A6urzJR32) zJ8azO=g#pl8h7`~D6`Y%^y8MF(B-eB(A}ON-{2<RF_%`_N5iY~h)In9Zs+E+5cvNC z3v_a7Z+5IPi)p}7BsKVf(BPljR^g~&+8g^D+p$pvrs|9dJ+fTmPV=l>^s9E}5hC@} zfnDUX@KiaiU$4{ML@qizyEt1dEOXNZg}NoDg3G%o_FTI1cO>7jF$ome_X^=RxOtl( z;xBr)PC>)g?rvSMriBd4r_(8w`vQ5sGHyms@B?ISODYsb&j!?7if1gh5G#?O>n&w# z>7d%oi_%WAF;)zKCdFcfk!zt$p5cwNBe^VFANuOZ!DhzSfXM#i!XnaJ>|4dQC+oKc zVM;WH9P@xI$D#3rW*bu6T;>4>=4#{~IdlUq$-S_6Tiw+kJKJ-{Rqog3CCOtf|9lN{ z!fD1JQkS7Hcfz`glnx?qz!gj3k?|7-)mjko@87@g9dyY=Db8uh;$Xo69aw2-4QiPA z3?}O$S>;OYQ*m`@_X1U!OeCl{00iwB>(#{iHFrlbw97>I)my7=%=<zwgR+4^(U$Hb zZMgv44B*JVwGwVY3C%QQ6)|X|CdQK&!WW=398{K|r;*Dw*5GFi+j=4Y0~DH7tQO?k z>-AC<U1>k7E?`v*!I2dqB^h7>Csz!WuqZFgFokFGc4-yGU8jYTO?*bBIeD1aQKtCI zGTo4}{B;_wWEW3@D;E<teob()Pb>7i?r7WJOoerTL5}BQ*d>&5`RiPGl)i^VD7VW^ z)i?kdWsat(gKT4VHfa3$u*dozXZLruu=DwkI%56wu}NhGeWm0*>VJ<=nnPVJ=A;t) z<B2Gy9LnMC96xNBegoPj|Efo~YXF13>R^_Qr`kTe0CCx^VX{*I@c*|Jq3+^t!?-<6 zCZz)(zGW-!S+d)pMVBkJWE5@yM+m1Hy;%sQnGYiU1ny?8d>Nnfrj03gZkB9z;k|1j zGv918GB@%#KjwE|NUZ~HgFJ?PyRk7}l=yjM(7+i0z_j0@-+Ne>k)jP5+aovKn#Wg- zP2^NE-*xb26o7bo_o&4_8Nh<HHKqYv)5@g3LDN%ITIk4`M%DP{lY>gezXnIj;7Sp9 z7kz#HA_g~u;N$ZHuMf8iYBa**qzDh=#SUtgiK=mNqsp(ys*byna&{UVsWH7B*m#n| z=O>&-m+||@pMCX7m>mxad^IRP<f<DYVD}ttFsB1uSo3)IH1*T=EkHT4Nu&Fi%)kD| z1N8S@f6xG~zYW^BOq-mzaCo28mP%XRcs}!Vi}5@zWAD`eB=dDk31W65qiSJ!1QC=w z>2wRckz3bu`$g3<k&Mws@!>nNnk1HurOu5V3Sm?O_ac9bUq+Q8DrDqZ9l4X+$swbR zL2Uz*2yVDI41F8*ck><D5f;a=4B2cXvBy-QhIN<IM6;H`IzN~DaJ4pwRQg>d{b`Q6 z7wBR*t$*h48NvK`;|Xq@lA=sU9~~iJChg3a-Q!@sD@OBQZNu)r!9YwsnmY3VQ>&X3 z_mH`f;QF4C2sWDg6=lNq0*0sRxwBA8Pp)rn?}6={sKRmULu`h7yuQiWn>#?L_0gDg zGY<|YnM-_X*J%{0t%a;q0GP|)f4p}#j_~^4g+N8oWq1&zIBM>f!y%DSR06nk+zDiN z_9d407K-dG+b9WV)IBZm12@Ut-O)?$glG&)bKu7)3#BxV_zD%p9U)}~X^~G;$r@5l zZvZ5#cZQLu7-?)sJUReX)zW^H<W{o6=w6DKVnKuGDp1d=_@+w%4;RK%*8wa<Oxdbe z$(rCUsvaC70u!hdsjQBbf>Bv2Ms-F+>6c-~M>|YAZ*1EaLmy3QG3tEsz~~HT#7Soo z-R_{_4(P9b$H~pp;W1i!kOLn#x@Rcl(Q<yoXWoBSK#K}NZ;N(o%=zcI4yg0JBTshG z_~h%yJ}F+eR&5lL8Nrbm*UAHaH0Fz8&yF0>jK}uKO*s*+mb=~(iv0x2-33}N*pAUP zc9f0Jb1fWybQ1mSFnv<h$$qfEaci#6>ITPm!UTwi0rF$Iv)HdI2ot05DQ)NRP~IM{ z5HT;^>vk!mgXX*Y312;yVzrN>x{Jbg9&urak(cp&@`%L&U+jXzSLKImgVd)R$YneD za<_Zw0y{3R{4(bNQI{#@nF_$PGn`6NdkGN0DD(+m!gB;HnTd1AJx%O)L-}WmXdrax zkD7Xbu-F`G%gqRy0L=KmIwdtKN-X`RPz`jR3q)Q^*Xwn?e`I2!$7-oU!&fkDi$DzU zq9_ZZwV;esk>yOth-Fi)n$Vw{Z1@^h(?>=@Df!Q=S9oVq=v6uA_4eG#vAVk?27Sp~ z?Q~~&`}=k(7^x`tSNP3)n-YT=o&_$nN-;aOJo6uRTkm(Bq`&d{gAnLF)KebK&8|m8 zEcgGOj@8qBG9qBxj|pdmh-es>mPSTa`$!bO6Kf;l$$!pTs!fksLdYVv=ItKS$j_$Z zOG%#_xfw>qD&|Tlit?8#BhHx_YUXZW6lu59$~vv0O(|Hn`j<i@v#8z%J`*CYHqiqa zrY^-8bdgq+IESHx_}~$ho2Tlgbd6{XCkO`|`VOw31qHxv?#ay+bR1fY>1{@uZf|Lz zly&oZCDu7TA@p+@&yM)<%iz8Qf`ob6do$t6`@Aeg3k=sE8<>;A*?&m{5m6$bw0WoN zW}>#bieo>KoYmB4ZZ${}B|(zJO{ES8%?NGnS`kk~%b0bWjUl2h{$2?g^61fJ{`NrP z5+)FdURZ_NOp6V!>WSk8F89B^-{$GlcY*m5QLW|QLopmBC0o097^^6zs5kaFn2`*T zoSRH;g=g7`2sxstgCj{ah1IAst<t)j7l$U_Wo6vPy;XoRLn4`kn<B(4&B9VWNNJkr zt%~gp7IRd64`<GplyF0pUI<?{<FTOmE$XO5Y$cyFR2>TF3u_h4vj%B*{H1cY;S3`8 zp32a4Z9O4DAd56IKZcu;yLCYA7w0z%W^|=6u)a$Rhka&yYjUR)jR%YnMNZ$w3enD# zCs{E?)*rph-~Ep}v(A>ObqJFpuzRd%FhAK3TK7KSyriOTPF^SACI5NA^+$f@_7?BY z<~yhJ@p;&)$jABEgZcb+Ce^O5V`VamWsx2tgZR&fHy&rMpPy}g`AJ9iK{&r0MVp>) z94Y~!Orv7WtPkY0en$@1pV%H$dcs5Y)t;lceO>9ksjKw7bVhoCO9z4W@hFCS3sLQ& zU3VzWk5+`TyieYGq$KS7dVB2N<)<OaYib=tY=Mc>o$feY0RHtui+r@ywrcR;iM-t! z=TszwouB{!@)G}IuAQ*~FXf?iA=Z=%VprF!E0l^#<Bu@|!ZC(My<;*_RBLrMW}6Xl z&tNOL$~<{qT~?NbqAm|HszNpt2gTCltU!9wRk7B3=}VzQ`w@44Uq1wwnVX4Q#g!ul zc8Oo^SJDc)5&>*3ZyLZs|89lTE@J~2iD_MAI7a}s4FbOyQZx&EfSg_xEz`lyI6QY= zl7T<GO}5}CYj2GPG;A#E0(O4H{oV}#b=yI){&&?hbrkNDd>74ubT4iB{3o@>G!*_M zTlkNYV9lb~amMHX!N=co35%HEE!2JX!>r1pFx4||jC@%MyUs*j%rd_MnU)Hm!5l<T zO#e_I=*$H-X7hoeS5Z`<pp{AW2zqw`eq=#Krq_wM;GMaz5n}b}yit*5`2wWU@3Lfh zB3I-0OA_3hw)7}8=h#;5FwERtu3ezV|F6jT6BP4-v%VVK)m=s2d>SAsSnlQVsv0m- zB5o6oGPlscQM-$LaIY4KHv(l;E@j@1BIpxs`RiSN;uH^3XLByCqUc}^^jtHApW$DE zF``_dx!yR)(~bqlf0VNmG{rw(A*GJ9dDh)IuW5YGv^wEBp^8?E-<8#&6X)!Ky@@n7 zx<s@6U`;k>K8%!BR5?x~8sMwsT^&Q?PbR=W$g*Kk6pp=~(2;y2rN<zf77@A3{j$j8 zQJ69;sL6ipDy_}9t2ta%b-mt>zkPp`oYdXn@`__WEs_cG%9d8G#a0>yY^*-o-D(X< z$dN2ehos(33Zj{6x7k<FVGK(t429a2SB@79beoB+Drz$FYxlv|jO~q#=QL9VRV;&z zK@2Rn2@L6XP>&N1CTeMi3t68t`!|W86%pk92+OvTfpwXx2);pINP-qwOCuT#yr3#D z29o=#x_6V0lukh9{6gW0;Y^zt?hCRa&#MlXs!!;0Mad21W-tF&q^M;5$bud)!C8b6 z50^u2g&#~&rMji6Q>A(y_It14J)7(IxUP%Z{ibtJH{x%0YXMH*$Oe9uP1GC}R;PkK zMLot>W!;q?KZ1?L8|=rns+hy<$Q%U1D10jSLlkf0IR~L$bZ{@r_~(qQ>QM9#XZlPI zDmghtVm0ZWHB)`z5!P|MVI@ADeZ%X<N%7JGWq(l}f7Ck|FCERZ`LikuJYxPM2fM}2 zeff@)v>iS59cfT}O4=IEW4I3IY2&uM^@_~6DL-j0V40cNUJpNfLD&@}1n-0U2xTAf z*!uAX0ozUEM>Bp`!x-lAQUyD!C^~hG#ayW6u47y;>d8KKiWeM3=qaA-aGR7wDs6$` z60?h^;jovse$F6MHbume&mw<h0S_vng5=O@*njgOqGZj%Dx4=BM{LjCOOtw1F=bnV ze#{x8_N*phsp6;eSfQ%;0A8vqFiTK}l3;A_y~D-rh2?7MW|lC|2yQvvVE{wk?jp8E z$;kkR8bcCkSrq&-L9qDIUG`n_d&cX|)s-KX628WbmcwN_66gvKQV_oQYNprLT>m8F zFNnm;v*~4XrVIPFXh&ZT;<TrSPYtRSEh_Dp_YOqlVBjC%G51^i==acSe0lwG19+xZ z9;e+L`t6_%)rZq~jh~e>D-9SDvXdOI!4DpUK(Xl3%)@&u#R)2ClO-tcn*7gebJTwk z=qu{HFbc}kQ;RorxX?8x^A_rto8+CfQlfFzC<5w8{}8D5=!}V1ylHq4C>TKVP##@H zV19vK1~aBcdnL^Lq=0R~iOXaid!r4@Ihf}mx<7f1Ngp3?n&r@7woiPlt{ICsu*3z~ zIy!QVUhI7-RHoF)f${Li>+31o?99c+u-WL);xOq!T|d(ZV#PQ^E_8!hQ!=#MsNOZ* zom05{Ydf+j5Jx(|eC(D=%J0+1f0?yo+bf4zsgD%uVnqn+_4-`v+hy|W_wVI<9zxN- z=1I^4N_Hq~>}>76tuGip_uHt3v8WvOS=z)zly#3h<J+6ii=0wqF?yz+R+_KqSS%d3 z9>Sq$)Q21v5ax}p#9PI91IAKL`ubDEWo53fNO0RMjZEF8`jVz`CYe=a`KpL~2woZQ zhOf1<l3dP`2U?n<*aJt+Jl-*;TKiOp*)Fs*nabU>29{i7?KQ-X<+Vx(&qF8uFS#lJ z-)6k_`y?bgM9^^oSfRs{(V^CEUx&H-X8^ZKLz<MuN7IhYFjxB_3O2RIn^?o63RRj} zA$D*_|K6dn$EoD|pNA<T<MXes!wTKMad~=R9To?w2uXd6qwhx}<#yxo?N@F7Ne92W zeE;5Vy?9uWY$GP?R)<sa7lqP&9KcC3I_0y|n$rEJ`w%@G<}~5bhIxo{q5}_}V9peV zaM5t^wnf@0R>rU!6{PV}vgM6FGGTSkKxWr;8;5J?n**v?|EpuVGLWVLFforEQ>^hH z-LGFB+RMC3hdHfNTJnb*Von3bhud3eM$gx7zLmiBh|qz)IgEHl=P<&1!KF#bDta=0 zSyuOUY;}nE#K&U{i%@{q(x@_@q2`-g5zTn!+(QLW;I%}dz{;Y*7>y!&62f{(<CP8# za!B|h&d7M4s+ht>G&6y7vSP1w)!{%}FwaZkxLP$K5wEVU!(A-WwI55svMAat=v8jD zRYIUb!RYnr6AU;EC}Do+sT&{CtiC#E;qD^w>B9XVk0fEZeOQXnT?ikB#y@!Lzxw)v z2Jk3zx9=iJxme2mHrAfSw5G7GUFz;{BC{$1IMDi*NF1@qDjY4LNb-b4WKLTuRWdB? z(pRSNeMv8`Nz$+f4IHw$X_bprd-at3Mdhp#Q5MN>Lg*wWVLCtm2cvzii9PQ;xcHVJ zJZe?UEejhKFvT4~eIJIgyNZkZ%f-a6ofEI-t>PYs|C>zFTgk_-*6!m@nBN!Uh-RqY zEB|5k)VaFqX+yKg=mbrawk76Wv(n~7<>@GEc~4F_Ix>*n@cm1oRsr|LX6&^+(>&iD z_8X%i$&9iADqY&72E=;FiH{~x68WsycGuy4+L7*f4BE>h1ktDaW?MR>63$1Okh;Un z%YtRfy@_9*RS+^?bE&E>HxpUndcEz}@81K7JYy$FCNRC(z*)rylKyfU-5A-Gq2VvG zqmj+JA8}g6Ig*kTS=_CA8cYTTPTsBNIoH(;nW^J&=7>F#Vee9~uv*VBw0O+B0Pe3$ zSAs{dmNxLnXf0HAo{vjZ;4evjdV$K)r5b>jtWgBbf<;O7tXT1Eyn-m3soDy9bE^1G z_C48UG>!j#<Fh-4KqJeN)O?B>U_QpUwKrvtRou~=D51>Yz`Db@BQZ*4%!ilWTsFDN zkjF<k5XoBZ+p-H~w=I)@<@HD|o#!NG0{{L4loeBWA|W26yf&3t<MaVBBIvbR-BP9` zZ$TZA`$-*?0bU$_Qx4d+FAh7Z2_WvKX4wO;A(zVDm?-6VjuEpxK{4Y#j!m4fQ1fof z!HF1HvpUK<r{+m!9)|HFnQ)zA=Z&SwXcxkW^{Gy6n~2BiOY)F&o~-OwY9M@LKA|8^ z(#W6<@=Dq4H1-@vS%DFQ5`xI6fVUPDl5jPumgf{1E-T4Q5@MP+CMpnPI`Z!z(#=Ug zkk9E@v51HVvb7hixC6yqa$8*tpQ>+LtUYxiRmR;#y84D?mH^8IWg^`Mk!u~5)UW|p zV*R{KeJpe<0W2b}^0Dbu**o7iMK3DP1*7mjAdq=6ned790$bnW1#!|S^gCyo3ntE~ zsaBN|Re4D-$SR;Rw@IQJHy0;Ls78;>xeSJA<<XY;y#Y|KA4WAJjd@1ezCo0^L>2&D z1&4WidO3qo8UrREE;djU9uXiO+|<Bf*+&QbV@RM*m=pq>xOTh>bL1JG&`YTt9^v7I z7+McRY8^uaOA_dpV@HyrP^wg~*by9XRN`~)^b+Y(#Icu%!9S+&BSnxLhah-(Xr|J* zFk)X_tq~xpepl`GA#f&Ga_qh~jO%n*(m8k~Y1epEtY>prntq2k{mL}{J=dR71}O+; zCz#N^{Uk;>ZkxC$cAU7ocY6R?-huOE_H6mDd<4RqBt~imMZI=XDu2p|kP}GZLxZd{ zsVW@!ZiQCvnGXVjIir<DHq4ejv+JbHf94o8AiItS-GPsH{i)n_KQ~cQY(+}O&1i#5 zRN7RU_0+H(o;j%bn=&1|JyM$yMK4A<Xh+IG%e|*XN`=WER0r;aHg3l*?f369wdJ}@ zDA69%?s9@RI0cPSE`~9os1xGei|LYh(39e%L9O~dhBx@UlFOuru8)m6nKT+kuSytE zcQod(<Xg<0UWwbR9P@kc>SLN;B|nr6e#=g*f<i`bY%8gOCDN{l5b??=Zs8Ee^|l{B zzIO<eMM?;QJtxJP8cPFll2YV=@Kn|zpwPqxa|Y&c&BR5i6pv!7;(;FsuuPGPfJC{Z z;|GDJo}`_d^;=}f(x%;2UsimB0a(CU>j+M_c#W4P=`u<t<eaEN@F|(a8>!bi4B#kg zq>2Syq&0!6ru{5!%#-;u8!ehH@c4b+<t1=#>n_V(9!AmK<k+Mf{hYK|S~w5V#B|4W zR$jRSM1;sXX0HkM_xkjM<ZPCXDst?1_a<%t)_rCE#_J1MSD}Ztk(+I?K11tKH5yZL zf{N>Oq6xq5qjo3qsCP|qcQBC2)9)X;cywgkG6`Ug=cHS6?3jW6pHWQA$5QTLx>gU_ zUp9}`aM8O&*x4=-H@x53MU=V>oGWU)k)Zk%Xdsmc-A6}B$VMLDhj%a@Vivl8B&^!O zP~%`NwRilqpe}Wz-Lg$<Wr88H0>Oa-neE)Tww~5WqC3e}u#MREcPbiSH)<|)pQEFx z?z?_h!rLtkC$1IaWF&yjJtE1zSws&tji{F*D=5PcjYx(H)g*m~awU(_GE}<??R4q^ zfs@XJL<VUS)m%nrhB}X9yxx51QU4Ef@3JL1k}C-UN{hO;ryu|Sk3DCW)3?&y6te(C zAW+ggD=Ts_JXMhqW=2vUP&@@d{^wFrh!hJ&k24WzN`A#Lw5y!5zmHGE0MyXx%PFi? zb!E{NIg2)5X3Km{M`R~c6cp<qgK=_$(C)TeIB-P`1XY$51(*y#+q=9fr5^kvV?wg@ z?`jO$cH?EX3|T^83>(HmnA!5H3fu=EJIcUA4FuGzO<}i}-OfU7RXi{VGZXtl{W4^G z$VPM)P75sk4Z3_@aWH_J7A`TBXzv9m=--s8KU}|C1S=l?N^IHyMNcHyn+9jNSR*W3 z741Eh+eYyx>l4m5FQky6lX{>Os)RwUcOSZMNLvfv@NCsJ1)Ul(5u43yhxSq|a;4ur zi{KcJ8d-pXnTp!v|2F|fF@IR#TqLBxEgG&p(BrNHEJWz%Dozuv)J6nyHCeh<(rscr zpD#=(re-#?mruKKu+&pcQT20}l0l!F{@za|bqw!8J<tb+4JC%6P7FNFA%DKK8r%JS zA%8wT=8#eDan!7`IgC#ay4w<W%%1QT7me!nfQqK_bF~TFKP@;7;Nx>|V#HOoiG5wm z-M_!z-(P=3ge97v;+LAw2R$!B)Z+2VRb@yy?&{t?d=t@|>^zy!jmSdq0@ziyRxm%e zsGs0tWEr~nK^T+8(}+)&c<D-<xW;qqy@{g_@HUjr9)aTJ%U4y!RLl6f-2Y)&m3di0 zrG4cpFJH?&(?u@enact$Sas%=bXg7^wWCluy#vh<l$Yj2qE(P8=W>G#lONAqw|G2$ zt^cE7VW}kKyM+k{837>RHqJYX3+7U@a5cFW3Qf~cBn(~MXMfAp?Y`zrO)30+I|wR# zaW?54s5RBzHYTg8dXMtwA#}pNtsM;$hI3we<KtHn4m>O|KW=Z(*^JxYUz%qa<s`w7 zAL{34VL!C}g9%E5`H){T=zX74_B9Nef%2}XK(3^;IhU-$r15z!y}~{oYoz>b{ssnW z4C%96KuyDQ+2KWnxEm&dJOP|=!I|Y$ZBQ*K_$Ov@+k&}(W?}vf#Ov(d6qG{BN%T>7 zBxl~bq`C^Pvf)Ls<bs3S<+PTFJ0|uwLhETT>D=fBhe3stg<1|)5yi3KaX7gf4ctuW z7)l*FM>z@~u$9zQv>wZTHSF(@n3zuR$Zu@GG>Yy-8=6`b3}rQ?#Xt<rcUGD7l{FwN ze6>r<$(Nout@|EwN7v5?H~1D6kp{4HRPwaG(JkTFn|mBfK}lAXbf3In9{F4J)uRE- zfM+*|fd!u-&}=)%64)G6{bQFfLX0#Fu^C@Vp)yYDz>nya{LQRc)9cA)rxPHc%g`h9 zQT(00&*p)7<ag_JO5U+lu~D7iH?Q9^fcFMw#zPrsL@dTv001BWNkl<Zh^)yUo_A7S z`jmF%#$xvj@kNx@x%#k+QBnU{%MX@ODvLq$Ty!l|eN^*mnN2C2It<j`*xR#(cj1;L zb{wHb`i-e%vY+~BTGt4RU7(S`*mwkk8u!@a?m4U%1w-dGp{bhPMm0e@YI}#NE?adJ zTLqLt@i6bZj&|)dRKH=GKDO>SQn2PQdX9}*^*QnA#Ee!_`yr?%`@{fQ5r=q4U7Q+~ zR|ak??nVaQziAoF9R^v}yUY-S>i^xx^eOo^8O;_nl+h#TPFI{{jEt*S_>eCma%(#| zFc-(m@P*^FLPrHTkHKOjap-*>w)c*%LF}x9)w*x_P2Ixwa(lflU;h36{`!8?y2u-) z+<?*ry=Hgn@~OkYqk9@q3<oe&fTUT`9n8W7zNdztBpGzb4rbsAVo^0JTwI3L^~M=R zHE0<|s~S~QxrVjW;4}^im6=%~lNRn}{wwWcjy*AcW$3ouTm6rqbuC7^-OcQZ?vYzO za;awG7P}f{Eg9WVrX2;_1{z2lBz<uF-aj*_Ewmn^r$Aw`LoYe1Mjs1^LeMB>Euhpe zK>f>WL1mYUh5ehCD6|pEQe1j;>5l~`{~%|T;n&#a>c!~^HLhf3J?O77Q*wsxN}#`* zhQ#A|Zp@i5<~SxI*&IE*4bYkV>LH{dNai^0o-v-R-P%79p>+^j{hOsdH)|2Vx-K_f zQP*Vop#{UNK+7OgfyNv_w7OV;?GY!RjCaf4t@8)>1qjhTpCQov77*W7VtsB(a7Nyz z(hTOJSib}<k6gj|Ml<_@j(!xmpj?aQGh;lreC1#*n9jh&BF8)??47X~P2+2C#yoNI z?s2tC&Z{<a6jtS{<Bgc2+X_na-grR*l|(+h67YB~xA*aF75yx*Pam{qbZ&^(-jr3N ztLOx<5NH#&eTf3lN`p1NaqOm^+(!>xwOPpqyppj)w05OGW%!qUOcV+=rV(J*QtE6@ zlnhhU=0QT|C4zZbq;);ss2nfsJK>bG{8hctErI>peTUXA%P3l~!=kAo5)mlG$WGVH z=rPn4t_W~J;H|wg)4-a?HjYh^$fCVNwhR;{h}S?t#KTUGNBlxD2ak1lu_Fkj4EHZ< zkYFojLKSo2fBX6^1Ngna^q+@0@r-$^>nsc)!Be^M7V{Pf2cV!n#WY786u_*0#}C?| zaa7PF#Z+T)(JU9RK<Du&T%0TR*oJ~t+5+Hs6=fhr?lzt#AHxHw$0I+bzG0;U^eA@L z;&0@0&1*dQQE=Wig;ov((ps<57?aCwvVbr%+nY#@J5^4nFHi3p-}I?tJ#A5g?wfqu zh`D<EcB=8Wdm@1vaY%F_aO)PM%<q`&t)tbpNqNsIRM=ViPhalmri__sd#c3ENdM~i zVK;|1bGT;cx2Uxe;~~I7Gl;>uL}uA|F~Z-sN7Xwxk<+COTH5<<*HsmEP@LS%y3l1= zVqw0o<?iwQ{q_DXCLX4HCs;eQn0EcMhq5eaDQ+B_R0=kXVq~Dz19#=of$94s_Y6HT zF3Nq&dU(Fz+9%2@fylJNU0f#xUshK>_Q%ub4PN4@*|2OQ^q}Hr>o8)?%=~h{79zUU zvj~>0txKBwrlDQ;uIuu3;UQKneyKJ^tz?~%CF|g-6d^6jtK#$|@wPLe<0{eKXs8O9 zJ52jSZ+?pT<X=L~v*cb|!s*-2lOE&2WmqxmyBtW^Tk2{Nwr#tuvt8L!wB_S9;je>d zl%h4<maVuSApWVA5t^Yc$Uhl~L4w`KA2c0ZN2b@Q4MShm@!YJGN3+=xGCdy^cB&l1 zQP^+k;!GnW#;XN2b8h#?=xYou8IE6|{sh8C?HqQ^rU6CEIc=D#<kTgsL>9KXqBPn4 z$?ai~t)2=X^AY2C-pG*u2Sg-|`;LdBtxVmts+2qp%exywLZ(JXLpuzf794LVRr@3` z`9yG)M(gMx45^7NNG=pDXr=^WzZ?x_<t@Xc@5OW&*lb$ku(y*EeEDiKTM)9#v%OB6 z8FSffKzv2wWMnUUDVzSFWKiq6JL(~G=no8lXU8WG!fH43?-H^HCEje{`&+<3g<??v z9OXK^n(oya21zJ<wPAU{iDYsi6~*uKR0nfBla@;&H%?nSHx67!{e2-}^WEUcH180i za0q|&8W4Wv3>vr`#9hipgvYBuwP6|QL*bsZo!RE?z+)b4Umac)Vn<kcA^(;}_(2Bf z;J{30Z5<L&jGK40G)Ydo#9^AUSR7&R+PDfB{3NITl3@LG{U!vOZFSZYt!q7rxs=rN z?r02W@rI`x8R37fGLk!_Iy%Z~hdu%^-Y%y$4DwOG&e!tc<_yVKkUp1VN_f(>%`A2{ z4VE_EX0d%Yo4+NcQb%O`5G3Br-Gw46qVBG30Pjmg57VPbHjR9CXK;({$cK4@<+lv* zYr|7zF<`pp1t<@*Zx*+ZIRYit2Vlv3hiBoo(Vue9T)RCTw@F*`2YRhCfN@OFAiq^^ zz$+mYIOiC+O}p#+ovOcK%2Rvmx1tthWzz1cTYSE;Kl}j*6yu1IHTsTFFS6DxxOH+T z(CvruRLW4i_qSh{7v9$3R1WL3)dXa|m;3A2<tx6w|JbqDN)RwQ1~pe<(bsWI&;SYG zB40?v&QDXDL=ES5mQw<~@*fD9s?wZQFk-FiT-##YFJIY1wSx!s-9s`C5O3ygS3cQS zF!WqB=^SX5cE6DETRs6;DQ(}PAL7gGSJ}9$<F*+B4g`mjzwK@7f&si<wtj&zM(&tQ z=AdV&k|n!Vm1*%TE)Ah>T3b#N3(1R)ns&NcA0mo%-N<rWM=f+H@$P1^<DCLn9G7i8 zg8^(9HgDLv95A9K)ntCf`$R3qt=Gz*T&GH=RYvZp7A6hqVv5xe{MirhJ2Xh7blUb7 z;u<rt>Jsda3~iWmGDz0}X1MBkn&Z#~0uk%><NGY82s1T<(~-S(Ulncev2NM34Y^yC zJivOk@Xxq^MeY4*t<0VwrK+_*4sKhlFkxs9%Kdp`WO`269Fj7wt<7o7vi)hAb{UOa zRb<Wv3{W2RXuckUkK0!)WATFsJKloK>W7v8c_}6t)24cui~e$st)0bV*6ymI@pj=h zD=gj*gxi5ojRdf3`Y|vw7}V!Vxe@G^kAzwG*gT>G#P<xf`S-I3LhO(eg)Wlgmxl>Z zm`a=^RFqi>^s1VQ>|Kz~dKA|vMm}fCDTI*F;Tsh`^P^aaW3-VqYp!!s&ed4#zt}nN z)NfnmxJ8LsYq0tDGT)V-xnJqa5M(DIK^KOKrV=`+i<YV(mxhJqDm$&!KWB^=EI6^c z^k=fnmBWf^Ly6W*1j{SZB~eCl_`U?X8|b!^y&I!i!?qNd8itV2kKxt7aQ%K2XqbTt z?=2?@*g<(^(mBB@Vco|s1}%DFPX;S#XB+)NR%rlKN4Q)H%BPblkvq#`RZ^}tfRG=9 z2XxgR{B6TKgC7S0q8y=n3Lzs1BRO0mP&R8#_^x!@!rQPB1(+45874U)O=awe>yTab z=&s#CtWvwIdnLn^5zs9MrNDi;@11?4Jlc*`l`8OJbj~a_96CqDj!fp?=2t=rF*1ij zKT@G4_Z$}wKne|^jW)^QhBzV&s%_sYgY}DJ^Vlc<#i|;*lIk5yw!wNVvB%C}%k)Ry zbu~iugwTa7(y!5&E7PaZz&IF$mV<6MeF51U)|sq*QE6Zi(ZB`~D0Z^f?&LJqbX!Oo zP1Zh)Z;N+idhy=A&93lug?p625boiZnZ^72_4@UXUoZFd$M=43vvr~IAm8NSbeeb- z40nLFT+W3%QXUYlac+tNE3l_nEmwDEkzkf6mO4{Va8SsqB#<A~*Z8X`cYX1U`ej*} zs){>7omx1HZgyqykF}O${AS(<(Yx!q*a~9#`sM2v5YDU(V7{*FdPP0Det%sxvFsa6 zrYh}+ZJaeb`fs(A&0w?ZDH+HM`u^nv2-WK|C$&@U2}Dh>j}>iygLDJI%W)FD5)@HD zu6*jN%(>!4y9=$wVh#d0>~0MJK7KFMM4?ZQ0w{mcQ9T)gjf!i+SkSS<aDE$cTF#yF ztUD(4)1~jy?Pf?PdVg6h+2gsJ-Iz<2AWqz9F&srZcg2l`Y!R2zK<e^iz6nV2!3+?0 zK+ufu!~<}!T`9N}YJZZp{kSRbIX0=#)_iF$V9;lpzki>v=|BqiOO9A#3)``AmvMx! ze)3A(Zani?j>n>Q)HwbD6Dh+$hg<d*md_R;sm!#Zq+to{wXuV}sBI692`=yMS47+D zgxb}4OzNs*lE*)}15j>BnVsQ(%bOG)<t0!wv3B=z*E4be8xb3?J|p94oD9srLNK+s zkt}yJ&vj0`OYwKNioZo<Ptep+S)gGItKZ+j_(NUs^4+xcyIWTTGJI_AcrH1WcJ`(> zQ(8uONL!-h;TMmFFBI>Gp-7>O4#`{<7sj}7z|qz_Ts%qKYqLRSkC(rbw{|;%JjZ1m zz>o=)I?H_%b=r@`5f5N(t=|O0j>-adD;!zU!>%G&w!KQ&2K03Ik=gNN&u^~+2S&tV z?N(+fRP4P&Q#f=kW>iKCq6wy&S!BeE&_Aq|OOhH0ppdy<L_0gumvCJIhdgl#-4{%! z``g!V8Ndsy7OM!m&5w$=8_H#RVONx<LR>gkb_GqyW^+TjIJ7bnw|D7a8o<3ak=!a( zAIQQmi|mq8=0nSjXj`%L_`TSsh-d-NcGZ{*eq3-ypG_1;-P`)by4Lo{`ra(rRZOrt z&Sw=_1M(&Sa2nb37%S`-vgWSPo6~ZqRE^Hrj<(r6`l}>aU#LH9T4So6GLRS22)<0h zL^E!j`c<{(Lk1s}A6uz1rCbJU_q(YhW2X64pqW3WQkBS4_LpjT%ZZFL<P<;Y-^+v( z6c@F!iwnmzWC;XYBf2#p$#u>g!huyDt}N%8gRkXB8)+(K0|#89o65V$HZa7V7p=Ei z>Iiv@SZ`glpsN>jXD={0J=DYTHZ%jQmuH1T?+zAkvoDLcdH8$#J9cbeFZ0X%3coIM zw{0tyuXU|>UluR-z5SnmyuWwY>MqL85I!u$DPoO{K-?|3BbXdIK+t$2;|fDm!<hc; zv7Le~yDya43WpEv{DMrw&UJVMsWN(?jWDe6HpAK@1lL<(z_R3I8Mv4Gs@A;Kf+$m} ze|hKnrbP>+u)lm=HBLs9tG4qiT^x(%F-&gvWnsmlk8(Hd+)UKZ>baIrbEAiiHa()j z!_t?PYof;liwvsjV-gU_Vu=ME9~QCP63|{MX)&cr(jNWtGFcj^^V6%<hp}{Z&A@kv z7&*Vek<+WY?@4rjC0z+~cfxnY=B!EO@NyB5Jr#@~pcr+*dRNO7qmiY<<8&4zmv|L} z!gm7-zR<2&v0ArjGF1$$7{1>e@JrlT8|5VyVGg~X1>Fb&^CVlKvjK6z+zlAmw5799 zwlfzopv^}}(4!h6JOD~SwZ9<hF^n3*ww_K7q{)wrsELY}SRgQkyhomq8G#KLY_!b; zw4#q~05;uez<J#iM7U;X<Aq0=v$CYqq=YvC5Dy|dLQ+;~yV@y<Fn1WAq9nV{dRG!b z1CrfbU?&fk!~Wqqbh)hZZuq9%Sc@48>l@KZ!opUz_9btb(}{z*Rfr6D($r<x+K}hP zu;!*v>g?u(_q-<w1PrZ0H6l67swlNxFtgugtIAA5eA!6N3oc7%$(jW8@|TWUO6`~s z-MczDb)M=pM~v9)#$eJ8j9BYssTOADk?SI__Eh?&{$gdKZCH%!#=GF^Lij-{W9=F+ zaa|q5pbqey_HP9oOKPuz<fLxog_Xl1kV<KE<ju4)AtDha4}|Tt60sua1Z1(Kt3tjG zl8aK?A}(hI-|;#tDUjg-d!woa@Tv%|qx6(?maQt5Y2?3~x5IZyYr#<HK;DSvqoF7{ z1cCj60X)->iyml@-WKRqPvLL5e#-#P3h9tQXmVS+@^bH%&4@u#ytPIPPE8wTg+IEh zS-KNGlJ@RY=uTMvP}^L%0zMZTGHq#bG)fi2FkiNvIic`eqQ+W?z+i5ApyykKCSb9Y z%e4eg_1Rk9;@I1p=!GaQ@SQLmbXP{5TQ%~;fWg#dS^_OYP9?tzAyaOm_81)IAFkm? zEM|)6`i_c2HB45#aBgNE-`0-dwRfQ9Qh-#nn3s_Mc{*T+RQb(I6|dfCKu-n<JGC_G zx9Y9LIq&wocXfeuK{2CF^r5B2(5L67zz%PInfdV1E#L=v%l6&CZe61Imd_JH6t{^` zqPVDiz561|bsO-aV%sp{gfQ%F`@Jo)B}0>ZxW%P-8C$mPa$oCuzwQ70*L&|+#KSlX zaar1vtEWK4xJz{j&0@tE+pU~ZEFaT^J*q~Rr~3x<TFq=L(h`-R+XREYJZ+sf1ZtHt zIWjbwHgIfo653#9V5H2rP0MywB8K}_)v?`t#qw<D{SS9v3z6THY0H*-WW(MBJJ-;% zAl5}lboM}M{1u=w*7!3}4d7^Is9pn$nr9PjKcFD06RxNUo8MgoDI$p}1>^<3&XFP2 zHO$KOFay-+-xdy}&vR^##8Uo4{-{0EqtDi?jm}g2PPHCtL}hL1dHRdRI^yAferV)e z+g`><kh<&IZdg!MLz}?(p_r7om!42*sZ(lfpWPj_RR3gx(N8l5Fxjj)WB?n2l3|=J zir0-(nVNz$8lkUqQW5Bn5I);tne8Z%u)I74bCdg}^ii_DRMx<JD6?b65blKmY;>I{ zrA1t^Qkq-m)WpCF+kSkl%n#Uvthd*zq{J`jN8+0^JxvXQ#nR3NcODR}P1SRepU3?3 z017qk`h+iad*_Q<!@0)2DGYuLmM?P_tG;OC0;%uu-VnkFS?Xplhrl~j%42Y3svCj> z^yEXG5<dVR(oHv2>yVs-3Uv4!0-!2B$8tDg%&3huRJe5#t|pmt$=ggPzNsPno0ixD z;dLaxx+uFOQgukd#csUiM7CJe6csAoIzj29L+ckTem<D7pL<tPV<AT@Md&%|opFh2 z_YRa7JI?L9*&U{o&zXAvkT)^_h8P~a#~v93CiFzr$NX<Phn+S^hb6p(c$70b*g_|j z<YXp0s`_tQEg(ALgk0<wyf@Mo=&j+zE2zeMpqz4N4)=;`pTV6}1^PFy-!p(w?z5EB zQEntx0Ye?<CeJVB%}n)lG#rti%ini{SoN72ujgkDXEq^i*2D!OX1&&fYe4VqC?T7M z(HWK>U9`ZdCmK4IsS+NxTJi9`ZCBqE@~q1H-x=xy^qx8jYrw%KPk2aY7EkLJtdTAQ zqxInMR#ceI5U0hCG+jO_HwV-Iu5^XAs<-#j@c^3?&aa7i!*sRMSV>1%%TWeT2Vzr) z+tj6aNI;Kywlz7BM$vI_2w`Qr0t$Fc*5yC>nh;NcRdz}Yja;egc;7Nv0L+~Nm@=Cy z!xBNF_>T3Txr<>4ztayL=h}`nkXRF}*rGXBi1o(=OGrlH>2yoEk7c)N84u;c8PIsU zy{c?bcx;PzEWci_|9J29fByNkv#`S)uz(D85%@QHqvk?+u+D}dbg4YpnNSNeI92Ba z1}|IY>s^ICp_7CKH<ab1I#~f$<67Iko#bm3eKI%q3&<*t3IW-wTa^azYpu)us?uaD zi-Ih(7m8ag?%=wv<tsAzV%f!lRyZ1^la&SD%0wS*6vP6F1bmKewhK#9L>}C375XRA zAu6B>cp}SUg{qr``Qg>ttv9&nGZX+UKzU9h<LA<8Mo6cuS~i8=rIVdU>JE@&IFV+F z6ehGjmB7~a;LbsOz7R+k_5$Y?4qJkcR^hktc>x9KUz1UZAJZ8DOO_l7Kmyawb*R<^ zA-=h)6@(sTIMAK+R7^tlkqRWm*RYAenL{+Bj_?x>9i6|{RzdSdXHYCxtlhZp0E7@8 zF<P)<X0TsC>mm6Kvxe0A1vDvXF}P?Z6M-!1_**YugS~UL1a#9#X-a)=iqD++!T*J~ zW5H33y0rFa{;aHict}wX46-t@*3?i9_8wsN$QRJMkB;JAq`wNCrCt$^5_f?(fjGFE zpA#7}C`K=r{fQopaD!GUW63`YX9oAcAYQDkfOT72tVLrs6tL?H%jG3oWM7;yVJH3c z#%T!+(My*kQ7@DZW=WTe+vgR&eq(l^9FU^BG>J$lkW+|^=8;dMgHGH09ouvU498)S zV52jTD<+DFSFGx?ER<%FDOMrb4Q??^V(h|2I8ae(cfcamtfG99L7nMYNJw1lts1m{ zw8RoAy)@RKjauC+ifA1gX~${vK<z%N?)~QxX-{}vBy^&%55hjt#HDwn*fap1DrWO1 z)Nr6~sm)%=)M;5Hx1o0cHGnI2u`PC_m~LH-@&}f!xhE76!4kZ77b>Ix|A+Z-mEPCk znq{#&BGm^OvL4K#CvtPJ{pR(1Il!W^NvRJFk>Nx&gUkOi?ztQGjjRRNyC;W=K8FIw z_oHJwpO^9x<@;S+4i7^eYKp|KDCfigHW~>e_u_H0OGg_`-Pj-i#5~};dieLw(Jrw2 zh#l2@%vb7myMVyu+79Z|V-X<#$PKsbi|D%1<>pcS?l@#N{mMX|xT=F&9Ik329JH!B zcZIAX?7F%@H+xF#9jyehKw4vf>zq&p%c-F$NPA=eGk8!&qjbB1J~o`m$jCAyg&a1F zz7@>_>5`s{EW_O90`wqzB^<}3(vVb{&LA*Kr-bW0^MY;V4mFxyRb>~{gpMbG!fE+% z&`vx2_EM!Ta4vTwAQ>Hm5fShGhSf(sYKOh|-eK<7TIRN6zxVRj>-8W1jP+lCd`0%3 zZ?0}F1MDPG;r}_8k+seZEkWG?Udrv&#+1Y5YW=fxcqO)_nitVJ&k6vrc#T0|bGPMd zEq_B(Y^hsi=J9*)Rz<$9bya$A-oMs*t%U+zRUyUQewnXzRiS5Sk=H_pUw2zqE3eR@ z%cDeW2JJNBqBtt>cH-Zp$~t`ww2X!?2J9!^N-jzNM|14Sw?-XfI8#su#gvDO$mkT- z8u?mJf->L=Ts@Hh24oboIA3rCvU2VUrE`0F;a{<VVQ6)i_}VSRlvZZnzy}w;wppy0 zLum7XUYBAZ0h7Qzr3me)a+x6@bBR()rDWBRSk|#uRe~f&#Zi&~x$Kr`&&GU-g{d|w zYwGZ4F3TdDS(W*B*o%J$#4kJ8FO*@kULyuCeC!#U{XJ}oWsN-zzir41Jsoez1)^Iq z5$W&|Z9T5iI8%qN<ZACVsn)*NFtedc$RJA%6&skp=O$688OE@{3f~R052`e8yCL#G zU1I&hI|i!QVdZUdzsz>TI{~HUizO!jPUfau@E$T?{=>o9AVn2zT6lHAf?6QCcgqkc zZGB_Fa7E$_>SaKnShmBg{jGeuDEk92CP(H)j$Q5Ez9ey`i~U-G^c~i3B3Hj_#mdUb z4B+orou=0!ojVflYjbm%x>xSb(xd9g!_X-L%jB9IUWCI2&KvL8OofxBnVrkH-7oVD zGhSvM_5}oWRl%$j0P6FNzi?46SNT#*OWy4E?;G;n95{Susz|`AGc1ag-T@)5p`N9N z!Ad>>??63vg{RfZDm=zxQW|ta13(wGgBX4s)vDeF;mJiv_7zxxvJT!w>v7HF{OIN_ z>IyUW?Y*{$%I?Clt@Vvntr$$iHv5XrI+xs7M7-k)^RT!0ESP#7m2?xoK-E^C6tsSs z@5<H4!pXZGi>(33vIqW5hT#kY{!Q2K8o+IC^^SJtA=nd)fYy!Z^lbs(AAfimbtLGd zKe0zec_Ay+@X28Zts8?f;|Z*pUFnmCyQ0-%3$`x25Ng)>kS~fYnkIt3%_R+^cXinU zX3F^*+C>n0%VRrW(rXfi7H2DGIvys43dSYLOFu~+-3}PlT8!-c&EtnKeJ5N;d<Sk- zg(s>U0`D!5bJ&K=fDTlo7{@Gh-=D4r)AW;t`FLB{L0ZN_+=B6WUIZPXfCc=1!rjbb zqr-YUTCgV1(I?042lsn52%LZJVwclG`TWM?H*x+X+aNK&KieF<_m1zdxB0b}U282{ z@ecRP{Q7$D|M#C?J6L!l=)^Kpx92gDbJ-?%+%3f~Do}ZsqC!dKv5F}1-y)3_o;HmO zhjO7thtv8^Eu5WX8_&CdST18Vi#X>vugll+uvpp1cU@~;(ju;+z-BLB%dfSvaZ$og zY^7x_^)nT*?-sU}q9pc>Dw?ZvA_P{1z2Q9862}Bc_i7XTaXT{6Y%1adGpB|^VR1jl zRCb~GMr;Hw5VDSkXV$oQJ0GooS9*Saz0Ovb_usuVtf!S@&#a32%h3Lz<(P&aO`bME z908RG$%^wKKQO?be?aSk!MA0Dx;Qm0-J}oq+orhOXt--No`8Yto>%lBkJ`!OT_2|) z3*IXu{$>7#OGi^df*3G8w89~ZFTdxSb4UuWpsnI<@C*ll%w;&Q>pcT<HNwsc(a^c* z7APxRx7|DhjgqU;pC}}Ks2O)`GnVKl-A>dbfs{X;6m5nq-RvJeB(EbbX@D6~A3;?M zKHN#`eM7UvYbu1tR5$?6MVfsutpt{*KqJ#ozn}?hv%Rt}(g090@ls25X0Nv95<mcU zQOUu-yMoEkY34MsO!mS{(dfa4p#(5;5NB0C3;NKv5T0r#Y&oesA?E7IIhy37Lh7NE zKCu#|z@w~YpT>^65WpTv_-y&PKqZOh3k-oihVTP|S*pvA!$0NC)Gxo%I?<?>`? zo%Fi3!W@(E(tJ-a*@73W(dliF8#+AUxRRf{S8<S*$c9kRgaW&pb^cq7Kftw|nDbKa z*?;>tWUO4j34vY(_yQHQ0b@KcglFJ1hoj5ZQ~&@V07*naR8^HQCY8-CojzV=SZNq_ zD!eMTX1*X0Mdal%3qc$$iNW9vevlFEMVK_qnWr~JzR8K;b?AH1M~7Okvllvx(h!R_ zI15^bVP>ACm=YZUW!3#+@wN_=GU6Jx%b~Mur+0>EktYC<h^V^q98__I-V|m_8rA_5 zi8U&tx2lHo5bEg(?<xiK2V*1Hp1D<VH}lwag#227_3XXbN-y&WIlpL>fL4RY>B1S7 zN}+_v+^!foby{LniP78PVHJf$Z3-bRhJX8hsO;vxeD4j<>mn$$v>T!vu_J)XNYa7R zgLBN}kzG3E-v;ZJ1aZ{^^4V>8qJDcYMBErWNvbTO+|2tca%t>Kx;)FL>bBPM_4@kq z|N6?hAdZAXWZ|l7q1_`%5gS!2;IkBUiq(>RT@2e3b!>(#7$|QMu<_81!Lzi3cOeso zT|o$eUc1fXst{KFeRV!lS-)<+*2)Uc$)I8_OK|k^SAM?M<#sIqQPW-y`$e#Hi)e@( z@3S+Dcyq>3BLD|;B9MWS;WKLR<|_)VP`S&DIB7nvFbF7@Mw@4fJ#)c457H*ZLgH=c z0U!0SGvmD}cvz~DloMLN#LOo9q8JFQp~j8mksP1UlKkplcUf!dSgR2jZ%mcFJ|Fmt zh6H!CkZ$;05tW42v`!5ZC3XWBA1?W@;LyjsU<i4t{;U11F(x7?+%@lI<OfrWY4*DY z+bQqxh^<acrHj@;xE+nLH>C~kV2hN93%F2S3WXCNm6K{Bu~n?QTAV~bqGoUZF4Qm# z(KpOmPkr2-P>CQ0E)OMZ5m$yhDL)s4prKjBKIrdAERtoNyb*k^4z#7a1nZ6#X}tw# zAP){g%DFZ5Myk2`bNrcMWTXpb@^<SpEb61ZYDitk396zC8kHH==5(;;qb^k$>w(R4 z?;NS|gUX_a-M~)%vO4Try26O^BZ*+%A*D>IYrJ<<(H86(k@T*fFNBx-MH}zJOJ`R5 zjUnvYx3C*yRX(6HNo@yVOk|Eyh7odyeD7Mb+_g^9@em&nWlK}6v_HI!uvQ*wWIPnc zhwRD>;482gu$U?DiROR>h=4h$P5^=;!iW+reV!5hDj<`2vq<Y3yUD#fn(7gAcaO~D zP{&J<iLnD|Xti-T@&RaGY8=VHgQhS2<8I9mSXP}Z6h;1>HJ)Z@moPD%K)Kf~%woS! zf$eE60vVBbv?<qr=labEFcGkrr*1??Yg7;!a7>!Tk2^{i(?V)m+`_1G!P#)oIv+C{ z|N8j)Cf!}tjzEV)jMd7l8kWFqPHHrD;vC8WiHvbsr_r8ApYB7;C!SUlHSunz0Zq_8 z${Vuca@ge_0SsB?8Fi@)uafAfYzeWX6{t$=Rbo%i$jr?y?A*=Va!ol!@!Nv2g~ejo z8@pevOLy?c7rMiNc4B9%k6==V7nEpfvi&c$<kb(L3i_kn$lsKG2`Q3>9l`MZ7DQ{8 z(17YdB^}3`l!gs`2mtXODtraN!%;6>kBK(JIJady21Sor9yeKnxTr76aWK|$1Xmo2 z+rwrSTA|fgH210$oN(K2+ai{`FaO^ApI_hZm;0;6x0W|J$t*TqZ)UJ54T+l04!NCj zMSQWZ!gQb-ltVb@(xSF;cg=yJ%%G@Wt$vphx2(!j`EY!Dn62d($5&A2%GFxFmaS}Y zbooM-FBtyvSKjOEN<+CK*Y3Vv;Ng{9vqWD(ku9vzK?hEa!A|?r`j|Kz0!UY@G}OnM zjA39MSWi@N-eC8AOpcd|TQbNh<fMFT<P&AKsdHtTBK!*eXKF&$4)Qs9U(^+N7KYPs zu&im5KRxhYz8nH_nmWxu7(E!~T+r=lS~ROo!+J`TC6;bYZ?CTD4{-0NSpetR{Tj$$ zfoBVp!XA~S)Ig=F{DeH3HDu&b9d(KDx$25Lb16vCLi6-Q1R4Ij?TWS=i++13hh<1w z4GJla2J_k__u?d&Ll&4U!VIpS!toQ2WeV#3r0AwB<k;SD3N1m7h_pd6BF;8XZr4nz z2u~n2n>)gY>sSQ$xyR*w<Mh8}0GvB8=c;eC)Ki^dIJOL|xAhl4s1C(q@*klAe~mCN zGeuq$xlLn*H&(OEIF*s~Ss&%iw3(SU5rBdc!`*}9gg(PDbPo=QcHP)by2H-Pk)PQA z4pW&DbIU|M+r{3+ESE*5U@Eyd#xolS>QNFBi5NxJOb$yNeC9kRNaVQ}9q8SX^O$6? zP~n;H0&{m9OilG7ku)`mZtwHFPnDl41vn(NW@z^m$BhrHe849SPbR{?4Ys1{vDK8J z(1qlMa^(dV-8BewITu({wHAv`x<-?T6Npq){iJDNq1J9@8;l<{j;1^k^gI3b^|#~z zlL!Kf8-{&5_Qv^3?3~ubqnv>+<Pa6POji@t8LVpuIW$n|`*J!|`YN9S5OEBBj7kjt zu;N`P^XB!JxoehDMTS?Q`DI$N0?|qg(oqOyMqRre8039Ys@F{4hT`qnr`NORY6KMp z#UR2u*<`RC-qxap4g`XVmM*A!m(BbHF`q^ZpkD|c<-OogRBJnUi?UZN(Q>!TTMe|8 zT|z|!Fl#sSCh5+PP)5u|HQmAfOA}qgS6I(*od8V%${?P9bY@~L$3p=+ib!vL+GydI z2qKiKl4?feTt8?_JrQD4K%8A3`MklY$FNmZN?&$EZKdHJ(5og+0kl;W?t!x~_Oh^e zM|`cz{PM5;^<Q6q_<H%e%3|>)NUb~=*we^z$$`3u+t#IVPUt`Rm&^Pr{;>LZvdjm= zy*r|kX!@eO>S8S&_jC7!^kD8;jo?-JzHVL_yICL0%K-N4TEE<11q&-!bhy3TuXG9+ z;MWz#_A3%~=9S{u4*SgJQZxMEV67<oT_$BCa4>VKVvh8rg6Wnj-7Y_q(@HZ28mFb# zfam>2Uyh_ozOJ2-=P{9sy}ci(7QGy31HemAWPi<vw~Yj51Y@4syA%fDP4k^I>Hjv* zAFh~xyO|luQ+CTZ40y*I1%3C!p%1lf#10H(RL`*Er$L<)7gurToC1zCt3UX|<DUM8 z$1>n^Zfl(XxoyP5f;YyYm!oO$(*`|y^jhIWk-(AJtD{4?rE%}^s7IRZ=d?U|9HdZd ztIYVz^a{<P*)iZ@D1H<g6-v6F+@UUEz|n`rPUgekv?4+AAtuU@iBjbJ+?prV>*m0L zPN;`n{~1nv)2-+I2T~~x0e$x1L*A!qx`EQt7siMWA5DW#$7Fo+WLAh~IWWMS%hRSj zY!h)A?cCI-B3R{cA^TIwOf5G%aIiklrr+j5&kl#H<xxKoE8w4>&^M3g$?-lQJD=dv zdUEfsB5Pg0#o{E4m>>2{pJbdqFO)5OIIguw`2G||!WpO@sjZ%0`XE}4s6m}@Zma$v zs@aFFQQY78l@22^K85ggbUnX0&ELCz4+7oZof5EgnE8Mz^&R-jp)2<<1Pol@wD!{l zQ{me;_P~o#T7%>VD?-6eqpwdi;=WmTzjR`*CdJ2XnyO;z`mpd_IZDd_h8n7>4(nF8 z4P3OkVRCfju-t+UTy?R2R5w9c1-3g$G722Rk^vDB-@a{kGK9>x|4V^3%q?Z)Qw*^6 z-|FXdHo_W3XBv;hI!BX7qe6IyBQy}5?);ejExMQ!PYuLZx>w#ZT4qo2+y)mGrZ4Lc zcGJkR{c4MQQvzt5s+_dN4DhCMQ_l#=FPdvdVv?T$AC-Tu2=t~{)1r~8VT>ox8w$fi z8=!M}>24!ZMXQ0eiSAB#_G&(sr#z~+{ob~!1fExvYhC7Mdjk#ij(ERb%a?t<|M=tU zpV=_DvIn~DLp3E{7A&)Y%&3eXu55wJtRAdVI_s}MK{a0zh{(Mx130`IQ3fpBjNKZL z%?|62Tx=C_`G%{=tD|p%yVsQu&*Wa@|E2+aEnjQ>a=YBJ$X43GVfM@ITI@886JAfQ zDBh+jZdEN4$rioiz>);`1`uA>-VMt3s%2926BRhj&#NT66uo;;HA0b%x44!G(W(p< zI#%jMkG(ZD2R?1L|Fv1^RQ{@DcV#`HeW6(L7G|+lSK;lYK=EV|-?i+M?@dNnbN^^h zJYDMcz13BikmH$bLhh;xHGjx~o!>Sf^I5%?{c>`u;`!n1`Q$ZP6c<Iu^0tAWBIHjR zOh_N2hws_F<1iP%p6%0v<MyW!(DcDphwjBqxup?QB_xw9Ee+9}5L~&JShmn}QD4D7 z`>-j)jPJ4oO`mFn)(*0I_6b=(E{^9MEHvK7+v!nSht7-m1Z$Pwtr1_VeD7c*&@-lP zU#lA4c+Q{Z!v2)Q&?=72&e9KDYn0|5pZ9kIkf_f$e(TZIrukvhJX+MZlPF71&CRAA zVvhu^QIMyl2=-KejLkH)Yes-HpgTYcE*r%4;h83mdh<!gXbO4|&E%)s^drDW?5i=6 zazAyAu7}&q{Cu*MIF)hg-f0Ky@CT~D5r*pSnM2+xyt3I*diLp=ch63Zlc`t@^D*kK zV<P#3RC6NOWtPaS<N9GdH+^15y4Ok4F4Lq#=(a6YCmvW|BZXsmO6E2IognS8<hKF; zo7ZnffMrnaFF>)xwUCVox(^{@A9|<sH6f_bSiIYe9;QP|9V|f4yg~8WdTQi<?TD)E zx%OJU`}t$Jm8U&3N;(5%eQ0A)qDKujT1;p+JUQ^|cE-|h1_N&6aam{Xx!L7a`V#Lj zce^Z>6D}O+Y!Rg!R*|oWh-&Q9VcV)s3I0*1E88huf;P+A9?Dr3x)IR0MN{7#M(R!@ zy=?)ZMco2P%oSnkf(;r$tx6S3QaK^I8S#!PNW0p2tBnqiYXH?aq|WishRF^UM^WyZ zYNiwoYEMD^Q@BMj0}n^6xDsjtP^(b-+pw%FO~C7y($cW2zmPbOnrHp(0g6Di?PkOs zD;p7og1CtM<58`ix}pVE6~uSMAKU!p%fs!xcKR%?ZIzC=V7dKzU2EC*`|Iob%h!^G z`HXD7WxH2o>X9pBdAmz_-Y&}M%P!Awy$4O!UIqH?%6G&}g(_~D9ehU|*wEC(tDcs* zEzc}pc%<s9e*pQMoBZbA*Ltn%SC-3if044+Wow1mD-AaMxZp`_kwmP9u;fjRMZ8P9 z(@Mk5zCXy3BJ8qA>8$B2iP35zXDw>^%{Xbf;Bri0+DcU(_c*LNgAI=cE1SQ)8Bw%h zRH%EzyW>1$=DurQlEeiqJO%d_OK%bMCS=k~Wjy&_9qO-Hz;w*rt=~)z(x-|i;7C9{ zuD(%YZdkX&Y&qUq|J~q+bjY#{OxeKW$Xl4bg*6|KUFY*<CN~xEnA!)E;O84dIeCb& zm{6hJziCkhk6-ogIiCslv06d%_3Lg_%e6l*!h`uSzn1m)G6V7$ZfP07YDp@#goaN- z<v(w)Gwl8oDQC+uJR#0o=O<?`3F84w!?K{c-p48nVORwlxf=e%+OGRIEkS$~13#mU zpYa;-WRK5o|5WG}5UmZ`OM#VU5;a>Q`yOl`6P(~}Xiqhn^9q;lDz_hvlcEmX;|4K- zkeAyAaIh*nT>pWZTMz4_*x)}I&-ry+KEIJX*!Y1A7$Go2zR#E!1tSX6GSA<CrY?W} zm~)xbHT&b}e?Og+IOvcLid?8pLL5oa`5BapR092c>^Y;DEa*@M#~D1nUi!R>egwtn zmZ;4AjJUaUCvnN9^7(woaHt1&#QyJIzh?l~b@=t^Y(RnXo@9kI{qPlb!mU?$uhs6G z6Z*kJd4NBCeB}qlM{7Tgbmw4>x+5A)+vw00PdAz&iXsIkkH^X|*j~o~{f*<614Te& zU<WJkA&tfh8c6}gF<M3@FLMje0!u7R!V-Lo!vHKUW02wYc4lyPf5_^|EGyoa#bN~E z+t?F~7Jr!xDCU*n0u&5sE#!^G$I1jI-f8#j!ov2L9&zwmDyHV^of*O?zRf5TY^q=q zH0ZH6rC<faxm->8s3#$LFCJZMJk=z{s+C#|IhMJ_+Wvl<-9(~W#NNf@mX<XoiQbs| z^VO{{dTkTf?1XCbpC}>~i@p!q23G7TZ@Jt(e4_`Ip2sWf^)~zGwtu*}zgO(bUKY#! zwc{(o!!Gk{zxV#$sX6}f{r%7HFTW}egmF9=pAojAHa&A_Q`^Ym%;Ax_5*sFMn#32X zwZF~S*w$dx1UzlEEMD>6<@R!0?n_no%+-xx{bovKU)k2l9jUw?c2#PzC;s`B8O`qQ z{#yPIkCoN2SLXRHTN$Xf73@yov6cZn?nrjPh)z{md&~%*EZyZA*a1W8ak=Vt#nfVE zXW161Ny1cntP?kc6yKt*X}qzUNko*}u|YuPAlhNR?3Wa*RvPxUM@w~(Rd@*R<O;C; zAQL)ZkB62ay~j_&93{0g7U^bQRR+^q{wwD0{koUAlC^Ji#_c6eANf;W--A*sZycfB zySX*G;F<;F@Ks+YXiVl}dW1(d1+m8<!_VXSaS?iUfAvOg<<aatK|N{PtYHK)3*G6` z?MjWbem`4GDmd<=InfZe8#g%Z?Yn@xhrs@7mB-FWHl5CfUE>+N6UiYCj*CSZuP0^s zB82`4bb7BWEz3~P;il{!XWLrLz^BJqxXr`*QD+zt_+ly=cQVsaxoKmY+fsB(-p4IJ zNE&c9Ms{5s_mvy6iZQy~B=WI7p8y)<qW9}FudoNoq@Ct=^b8}hl@V5p;Dmml$X5Bt zRA>8_$KxM&vr45}Z;Do@k)3)x@+JP9XE)Rf)@%V)zL}M+4uXm8H|D!N1)rVh1r4gJ zWTc67FSz*3F1*`+mR?BAr^G6xeOEp^oh+>$d}4`w`*Hn9U7@?#(*&MKT&3qL=^+pd zCe%tD*lZ}f55Dr35{rJgeiH&+|E>S5qeglCQx!~6H=$#yW9dK+q_9yV<RLeMFgA+n z-Y~(_F|XK>QaiE{KKLr4Lk*r$FGaJQch#sZG{r-H&=aZ52UC2h5`n@3#JVi*$)c3} z{X$EXp}))R4*o7PvknHj+wx1RM;6R@mx-Ej*Df_xJH<lES`KK<^Th555imG0-7Xja zJlN7jnp*<cL>wJ5_K0MDI_<teQh>&cZ(oe5%sxXIlUf$rZHI5$SkFKQVDfGha**R3 zLY$-q>{^M!bQf%pX&Ri{J#JeGPFJ5@Sh`2*8q?FBtKMpp%g`M7g$u_FcnX0nAuHiH z#Vky<iYV$7UxHD%5*4}GkubF6V<q129XsNB{Ugl(_~YyA>&yHyn4#|3K&k!e3<n@L z7D=*hZZ8DG>5`*MxLU*#7gy6+0LfL==PcBgbwL(_fn)l~_cO9vHJtJJVxq67!y*k} zl)tLq<PWa3uElOic^(%#7MC+CXIv11DY*o6uEZb-1uE~$or=2A(0&|mspJ0u3I($Y zp=aUUwV~E!)$!`moY0zbH*iasz(KSmX;jl$Jr_+RQ)Dua6teGUteC9(VksKsRf2b* zG$8<#DV>R6S(Y8<y{d9VE#zbB;lFyteowuGOKQCWJ?7|ij6O<l=+jTudkacaE@bp0 z#PLfm9X%<lmlP`p^Cx#_;!Wx$5_>f3!l7rPFIK+T)s|W48z+|PZdR$?*d>||R_v_s z3VlOrGPLze76nptpuHWaZ)&2s9pPOl%8$kLC$4^<OCcH0WiiT>CXZmL8>1_{R}3(t zN$0$kukQ7^hvQ_0SYNZgI%;T-obd6Ca1mXc<52}lRf6>Mu_Z6NF7ua1PlsbMC$%&F z%b-3hR&ZZr*M+(`7at1O*pwLm^f{xN)grzVr>O$JrPs!N@Javz$YSNl9*tHTQqF&0 ziXIS&1m~~4LQWEC2E3YTK*q>%5F5rty_t(8D_IhlJA$`UtMsuWDD;X?HcBm?Ml5t% z-FGm8@JjD?2d1lfIHO5#p}1xffjmL8^8esON5+98_z5*0jvGG!?&t_391Y52sav_C z$p<!QM8Yy&Cq3p~gPeB64%<)eSS1FvV`D74``j{e$Z_PDCp7D@GC;z#-g@bVlHL0s z>M`GvH3^_-MeqJLqgSuLB?lP)JWpVk1?$DVIRQ1)&(`RCcmzvVJvxv`ius#wa{~nE z_!(8G4R!H(Jh#V!TLmjXAlWa*=<!uj@}}B!UW2LKmobBcZ?1yY!6>QF&MF{4g4p>% zok4DF04wThD8)~;p8W%(%&_HXH4KgiZ7`zn#<3ewmIooAM50Pz^nsU+P-|cG_*1D# zGdxh9u|8$)lZc;lLkH(Q%-`}Wmp};Rt>v02m(1JZ>sVb(gu1DYTGaQ4W73*YEwhs{ zytn=7yoU#RQ9K>qE(|E2#Som{<>gcpBij6;9s?6aOeqt!E?8&6p_aAk<7TWjlqsMQ z?}$p}0@1u-FB!7C!+gDd{YTjP<Lmu?$Mt$;VPu0G$v|b|0LYGEYUYD3_ajR)_#K{u zf@-dxE`p=I!pPg5U5i%P*N*<Zh34OB*rpLXP4W7@`$Dw{M1k8FUW*l`g*K2yZ1r9b z6t!{`SvBx6n`}h&IhSgJLx;IZlT^7&+J{8Ay2RIzj(C{@lOoK%%S`ev8)eP+s0u{6 zG`h{7s+O&<ny@}=WU`DI$(i$@5w@q{2w9@E6>n@t{(RR%aN?+MB_k@g%Q7#ye%FTo z@>M<FdO>pOc9jth0w&2TqzRd`@b<RYVax17dGo{Fo-d<i=xQ>xR_!qYi2(P2QPD%9 zc0$Hmw%PJ6p6E7>0@LKevhXisO6)E{1GxK7QpYpu&HbTT%NiZpcG%z$Z;Zs2qo}Pk z797rePJ?ns$bPzkQ(goAX_?ls%oe;a8lsVjgv~0cI+2K>6sif-Iz4Q4RQBeNz1<(; z;@ON1%>HvWmoy};ohlO@pyB;3<8q_D6WcLz%8A<_HM*NEza{>Wg=%YqD(Xd<W%FoT z+^TAGqbmujvy(tnUhavjeKc$lbWoSU9;2JAy?#DaIF(;b?BL0T5!v#&`m5FIIP{i6 zvAX#{zLc)S9qBOxV|f9z^_W##Z^U+VqijKW923bm;w&G|FFAlI@lWNW=O_n(#Tw~$ zsj@Ruy{}60J9JY@388+r<T>WOBaA~bg$GS~I6Q9{QT7EhC$wV#BF1^?G*=Bi^HKWV zl+p<sTpcm0@*nE@3l9rl37>(3qH-L<z$=bO@&n9}X8DdnU0v<Hb=?KCrn$}5U-(n8 zw9)E5mO2oNE|Ej|=v>vpmLiC`5diCR<ZkF+N;9NFS;%BonWAdv-*)|N25`5Oqn2YV zZce|Q_X?a>R1TOKV0cFL%Z#A&Bb!l|&&|KV@}^JGNHlF5Yw-5jOEN?$4Yr$p^Wc_< zE~9m5LeVx}%<gcl`zG^ZQzDul$#x<Y@zGtW$8b+{?>Ba^%Y!*}Jq3jhrX^3;pxatq zIU-7)1rqM#ong}09Xv&(^gVt2TE?F}NN(*Vl2Z2JBRD3;e<~)GJmN4P=>;d*dUb3z zYo)}u`(^+fefiSOwwzVCXI%=nZ2a9GtQ$QDprHrPsC828^2&j1)r^5?0owtJPwQgX z0t88#+sJfMGBA6~Uh8PD%BM9H2AiEK#4|^_VF@%_o;0#1{TKE)!pyF{ZSUAuu5h{k zrBp-Kxx21k|Jb(v_>On1>w4LBO&9)hVy@tkL?&*Nxt0}Run`6?1KONSesme^(5fQg z8)>%*g<h-L6m>x=s~YRR{I%ALp91Z?vW7GJeQE$W0neGYT$|J<7@_W9Msc*z^iq=O zC`1&Onhn{)f_|e1r?k}@WHHeD!A}D?=+nF#cra@j=7~LZh+OUE1uIain0V)D1B=NW zjN7**tP_bj6txztljz1^TomPbwNm&Nm1Vw&`d-mhkX=SwLI2JLE)U%TPB_Hy=w;tr zH6uYVy&`C;Q4s#1G@OMkKw7H2QXn22M}sZ;Nq9^m=_f&n6kc6RNv#b1X7PK)Al{`v zZi?II&Mc!rS;q1XI&IjIp&olZZM5C`NzU1WeQh*iFlj>odnSk}dzuTUAwFEUIk)s2 zdM(%Zm2Og<jA+!AMSt%%iqQ2LNjlROLg-smtaEWk<tHD1yD6^aWTSA`GXq<hB3sU2 zb*6hfVr}o5ksZl=!#aMTj$nf^dDfZh=MH79c1A2Z*^9Y$U>2QN)yD)*Xo_kf=%Lw# z(d296g-M><j>zRyOJ^d;Y;r_m>aCXKOWD{Qxq7mM`g0MMPrGrxQKReXGg0L{j*-jr z&r3^^U^_&iVy1x1bkGb{N<tX<!{KASzgwe6Yz8@72T}T9=|C=0s|AXvL2#mqHWjVj z=~Fp=CjP)l$smIgugwH~j9(okuI8D#cy?2Qd_}uTv4w)fq~i?RothG%Up4s{>wd-~ zCm;NwruV;l{bmlZ&YcAz+|Zq*Nbu+<bh}{gla;I~bLfwG+<3K7<+G0ie*E?>KPl{e z+<SYN{P-wLq7a>N4x8QM#6~Abt8ecv7fd)96!-D{y?r+M3y%RpTz>Azq_FA&6DfAZ z>P{pk{N)8DkBD^OrYcU`HewT};W(ARNespu!2ml$i|3{=Gz1Xrh9DjM;+($tBOD5J z1eyIv9WO78+ur7W0h7GU-(_WJJR|w%&T?X5z9WvNe~k;M_hL-VVw(Iq&>FEDRVp<G zq{HPTT1Q(YDsI7bQ*(kQgaQSNRk^R|IP~^Geq8)6K>=h}b@r*(L9xhQqvi`f>Gh6C zcka#@hx@L^zeSEaVwqpBf4sy0_>OItuU9oR8awD#`KkpH77b)7jg0u`UzX>Frp%*R zjfq?t-etb=vYk-o;@4}f*Q*OAmnEFzH?x=9%PWO96MnBW*DF-m!PI;~R=r9mcM(6o zZ1Y-3<t7LR8N_I^ce#)x%m4r&07*naRB(agpC>COmBI^ot;Nr6%D?joII5zBhy*_v zP4lh@@z}K`&sexaluZ6PDPJQmcmfpJqYvTzA<De@IQ4J^YR8{qnY@4R;m0&upf}e1 zuUs8e)vbo7->EQ=H%6A9SqP_BZ_fa3@7_G3pBzkgd<z2{yeKRVV^ONSz=SAllybA1 z4%^c~z^zi6VKI(vqHcP@ZhS^+^<8B|zoo(Hgr412y8lG1G*I153gM#X!0^Re=_I|f zEIZ7|B(Qu)k&_r&X*Ew`f)KFHx>mz=RS;~ChjyB3jqqOn(fMDx9mIY^E+DB}QW^2& zMS1jz56n%;iA2~Nq21X@+o&Pnu(*I=JA_}H*IK!9KmAq*)1z#5fjJz+xrQ{pF#?k@ z!7uq;4;kp|2b7;!t@%61!9Gg3|Hg*TiBO#@>?lVYAgY~D=5A9@81v94`$qAUJ&|ko zQ^tSp`IiIW<4qgqToluuUG#RpBf20Wip!WhlbD6uW2w6MR}JPwR(?40t|tYmjvAbC zE`oX}L^(&aqstQUc5aG}WS(}i1^ggGFNwi+LuY$9e4iyrQx^#`n)&;3+p?y_Ug4!K z$IN}M8|v)9ws*<b?DuylNuyAN63~SU(v`TTJj5`I1co<H|8Y0}p6mA_z|CS2U>~kQ zoSBESq0>B;o~jtC2Mj)?EywAMB>i1XA&46dySO^eX+-~L>K?5T8ie675$@@TZZ_$R zM;+>gmA@w>u*_rGXoQiB=N(;rx|G-9z%vg5B1Fk=4o_jys55WxcuQ3q$0LH{SsYRu zxaA^Ta9w7^I5t}i2eG-&{T|%4J$lPX@7Rm!J8|t<DJ{?1LQRn|<(aT22BDi-R9U0I zX06KudJ=hib{-}G*M09tkVbl~CqfcS_PCLN%Fum;Dj*#uRIe}G6xKBY2N{g*UgJQu z@5<e~mQLYo2kUhVILvIV<)&zv!@#iR7Xm8oYuUc`{w^PhXRO5c-i{ot2-~sOTGy{% z@361;-tM+u)jSqPI!JL9ve*meT7nf8q+fYMt)W=ZW);*e(vmK}*;t6t083=ErtQY6 z=0k`j`|_xQ)AlmE+-+T#fShxcF2st7yPousK<g(wiIB~(Ij!ck01(oR9*ENqSF`{V zJ2MET94>a)TBEW>JGmK1M|uc-c^GZ*sGif2dj%ge=F*(@2Bv7HO09lsiU+dM=bt{m z;-pl~dQ^_tizRNV4YZqPZh!4+`=m7_$H-D+Q=>FR?G>4-ms(?>c!TYSSQ&X*!CrcO z0M}tub`GA(N=M|9ui`YhJo#Z_S`$l5ELD7i;*W@TQOlk$I`zJx({D9m@uL&sWH#Cm zI)oB**;)uFu!na^9f(xoL)dZ%`ryz6o``}Voiy8u6R$~rJ^oP(*UH>N9gBt7l&;<~ z_a|ax$!GzePu;yYlxnfHWNH;qXHy}dH?b|V!vc4~AnTQ@Y?{3wtt~Ar?1K$lia3%b znYlJr-r}lPJYY%Y6N}eWWe4-`j(H9ZYRwXWCKQbzd?VfT<bKxU1~{2nczsvFbn7)+ zjukZK&|&DQ?0N;(>c=6w2M5DB5@R@2i)aS*bj^aGe$0hCLPHdwm&(GsK|Y&}plN(U z$qpm`!?I$ztOhgDd~g;%QbL{07+WmZ;JS-A)9HTo5tJ3}457Of?mKp>2T-v=?@v+j zhWQNPRpileooQ`S1LR|y^VfhI`O=tKSFw09Qgz<tE)$ZVvUMe#o4j;T7odFIcB0SI z2mjRHas7S-xUEE?ggAe4Uewfce(MfT@1N0xtFVnUMygj(l(w|E)mZyMd@A|Qbe%uH zQK`Y*E`S`^Sasg+#2Bb4MkF&(QvG(PwA1Bm#xqYw1t+mSDJ8i+-Wlw7iFFt-3d_lU z4y>6BkZ$_RgRZ+^ZJUS;_GYaZgJKmCv9gj@^6v<<*qYriR`p2G=b5}|He-FNf0ig) zh8wrcD{ec^=WBL{>dLP~h8pVw6`LWbHaF|q`=H?h`gYX{ut8_b!#_FQu$80Ei&qO} zCd<*7-$FltBXTFp8a=ASx!>bNMx9VEExxTMWy+P)IC1l3Stt2gw)U<zRk2e$-(4?m zM_jLKUDx-HulL*CeO=*~uW&X_YvXElxB!*0i9hD5N*1e(s_aGpn9{K3KKkOG`m}&! zRa{pL=PX#Y&0ZFluPkkq4ir?+VrFteT^yCdY5-(hL$2WO5pq1|boi(0F+P*2{?q{T zeopF69r{oi#(?1kZH7QE)xc&*WJs<Mx!5K)RC!Ub$RcC4CMO!QJfB&MQ`bKW!{{;B zh^0PM!H^FXEa!D7j(^W3K4q<RiZ6|J<1spxA{-nZBfL-Kh-s+X`u4-~>V5?BiumD% z`BIm^|IqxCxBM$Bd<1{?k3^{VsXbFG@B7vp_D|+wlcN5`Dg0o}3!435=>B9sA5!e+ zO@A^S|75gs-|1`n`4R)*40u+Nn<E?)LmDcM<7XPXg^qY$J`U_pwCbQgA!2of*MD6d zzi-OpjYsv6qayUd+4SMcZ~yct&Gm2h!6&+%_nw4vpUcni%=w!$$~qC3C+_cl@yBc4 z{;yp319HFpv8wimxjYP#+~6ShMA#j?1?N4G$p3@a^}P0^t~;Z6L?IneZTmct9~i>@ zbIxU%o?pd912C;gbnO#x{mB7GRh9Mc1VaC24sgO^>7+q?K!G362g6V+IhFVYv3i;) zu-WiyYA4PXYUtDwA#aZxJ%q)3j^{=$9iyY|s&cx)iQ}=xv>^njEBz9|5LYtAPDk|@ zL9S-#S7Rcl?>P~-v;<BkA5^H>wZe6FKS09F&e8}Oro9kEW$rt0&)dx}0o5SUy~1(s z_Of6d^RgT9mv5_*?Q2xe2npf(-3v&3!3TrEklxU!80`#^(3Cfmp{mkAz!BpIPN_09 z%wHDStOW*JVbP+xg)TQ+v17{bH2$}HWI63>dR67b!q?kSErYWhnN-HGfW@w;qx&np zEm18x8eL+>^z4dnuy0Tjc?3?qM>fHZ*yKdjyE4c<g;dyCm-O5T-cqZ!=w`85Zg`eZ zzSi2raz(`Uz0e%1CL8<p>p!kv*MIHrukUYL>sqf^8K<hA67{mM$c6-ERaP<Hc1f~i zlu3v;jac(2SaLA@m5s~Y3b34ZsjCH?h3=Qxy4+qqBFBlUzT7Tz%V`??nuw%d$QIu0 zLJZlk=mTKrKqms9eG96f6oGTl=$vX}M&lCqBR@*BbQ@>WFuSnX!n`G56_AQPCbT*( zSg(vF9`<LwfhpS{_-6aWK2|Da6j??^4wNRP8*Lr^1$XtKrD@G!t)p9RBXF+PKg7Xw zT*Ude)v4e5v*z)yT#nkIx|RLp>R@-U{<evZP0x?EYXNOLBKZi-2_{#Hmp-aiA&0$o zm=Iu2<S<9hCyXiU7l8l~W3$3f;TYkE4Y6}n$&RO$kB2T{*44YoR*t~p;bxd^gvRq8 zHAS%);^9O6B>2r}aCe^E2n%~_nxZfcl&Ekqq~}CR5g10S!X-XUTur#6Wn(z%%w_ry z8kH9soYA2fKTj}s+;_9%LNVSi8B)hePRL%MRmTY{Bjx|-x(Y=CR*6q1zXgcw!2=Om zUxxfMIM+wRM!cVMrL+Fr#Qsb~34+)IJgAc;Q;^S(4t5cz>ST{~Ocdcv<?nInIyeEA zE)`_mWK(WhG^Tl+@h+9pKi2vB^T`|QVB?lCk*B&j<Bc3rH9VKo67%;mNIyQu$DZJn zpdlBA8hh0p#g!Buv4rxyEEEq7A3nsH-9&A;0<!J{_HlwFbUjw}L|<kznqJ#u2@svq z>C``$gYd%q=a#?!Hni$~{aysPNh^z$A9V|FaS8c6N?*Nb)5h?cP<;fT(<5TV8OB8V zP!(~LG2KLVXKg=JLA+c?$R<gpT#t=!8+eo;PbJbzJ9J?p9(L$R614)VZ8SDG6jtR> zLDdISR^f#DVL5m-Zsn%P^2b~$gqS#SY7!%7@##bZH0z9<1bib>{J>ouKTwaiRnrL1 z7C7uRY}+6Jtb}3c@KoC)1K^^iDx3xGl{f82b`s7#mWnbYQ{KPF$%k$jMSs*ex{eLV zCJ3H+TUCl8rG<O79YWD1!}ir<n)NjF+TBq|m3ohxM+WK<nJ3Y9UI4mY4d#R*Rc@gZ zVRW_WpRA2>_-c^g#s;WFX*Tg-Dc82^of4oz*-<T7BZp@@_OI8q*7g40-+P-cRMv2T zF=xL5Oayl5keb<%*o*;K173MmXWq0_X#gi&`EpyaNb)Ni{H97*mhKAoD~oONcWnUs zRgr2OO($`pf>D@Ah;c0GS5X9-h}t0Qr{o(<xaqHT4AmQk?=ME}UktL1gu|~9Q|IQ9 zm+L%Te*VQpC6{s;a;HyF8Bb_Lymd^Hgm8?v^YamA$P=~0S!->l=SPO^lCnk8UH$EC zdgBxy=>}3M|F4?C0PLt8tMSYNUnJelTlcvT!uin52WSz}N34SaZx_4Kx^zq-Yx$(6 z94$#g9&&G-b9xYt3OVzuoLaD2AbM-<oBA=wqe#>-Uk&K7^3cry;6#i-n}>;<qfOZu z&)+^hR@H!pFUtBH=qK5fV_wh7p%V~vBy5?Pczz$IGL47xvEn=F{9&~C5gPN!6Qa5~ z1{FP+iz;Zbfb#%GyJA6W_k4%@JfbS1Pb-Vx$z-EVIIsTapLFi_!qkrVAjKG4bIbic z7Fp~%i?H|8P+{Se`}^^McTDB1^cx?yQ{)H3%bLpjc;j*Ignh+P8~J`~{P1l-p--e6 z_{lzAddy<Rmh<Gcj>nw;`;E7TbEAgtX9DZWYLDdS@Ge%eNrd^@NSqj}ifXI@fqU2p zEs=+D+CNe*M?ASnUZGjMN3Q>2%~}i4`#d>KoIauUt}1vR7Q})QO#VD3b2wd};|Tm4 zvi0%$O$fB8LC)?e2R7hv`J`^R<nJd1_xa6_LdacoAbK;Qh0{zr7M^M*Pkug!!HuJ6 zGrcB_f@AeI_Xw8pFxID0NWFLvjfN1$6A%M*G`f<4G*}vR<70TW?8~}xGc#n^l-#SI zjho~xEbChHx>?Buy6K|#J5$w&s{br|Rpp>6y{}7CV!@$LN1*s6)O%>cV%BDZnVmHf zl1X{y>Y)8nWK6kQ-z>K`9KE|twX)kCp=6m$Z;BprFMm|Exm#JG2`+ROrvPc7mxg4S z+&PS$9?G%>TMty~Ph8UgYrE|{I9_Uc_+?%p_sm*n86GkVHTGdDm$`IRk??l#YYLe| z0pdC09=9%7m7JX|b4|n#9^z_a6&Xb5uJl(CSt2Xk-x2m5ukToUTiDy}?Ine;@GERZ zMC|?R^;*8Z-|_tp^Hssov?-f0E@(zU9J2M_XbHNMF*A2tmn}E*h1N>pZA7o-FZZ&W ztH##KD$QBGc-cz7UDbAmSq|{OVHw<fdAFRV=*7Y}-xMeT*i@f-==fgMQX}hBqr|s| zn3Viwk|n!g5iTK6g4(sA%8WR?fpsI8Br2Wg{Ud>jOic9g<|DZ;YzNRa0DC}$zxlvg zx5bOv6^Ik9r)+8!H70f-qbHzwR_2Cft1Y)`@)6yN?Wp!EvnVUc4_^b^D2CEdP>zF> zL^)P*-Y>M9wtwxK;ho(7C5`=9_WW*n0u*zI&my?!-?WK>?sVny8KqWgB+Nt=g!Mge zD%-6u<!0_?$oUti5prJ{vCqMh^d$zS98e&!5jW)XSe*cVK$4J6HRCazxnts&FML@= z)TONJLrg5<El+qz{BH$`ur;R82a6FrYWDNI&kyB})5e9P5HAg=9Coym9b3Z!rQqr} zTNI1q)|G7V`MUj*&n0~0YOVvd&KYJu%?VZ-OM2dT@J0{6VL=~rK}#@I%bw-}p6TxH zJIoJiA4JmLrDCw;U`Z`naQ?C43EsGIT48zm`?ICGB_3&m&+xb%02bm_r1sTm{&kHV zi6~HIICHAcC7IL}hz2c@LHy-0_xm)tV*NAWW~!?{j)#48R_S;VorYaKmiUU1o87MG z&Zn#1er%_vco`YNd#v~5iA9=uH$3mDAIG`Ny)_`1&NK2s&$CO^1Mi~7kvmw=sXmlF zhPxx+^IU9j#ezSm59=cf!ar4c=w>(b1^=qp{P(ZlGl1E0MU;>67vIBwKydG@36|ec z-x8d2RR(VLtI>ekRUDgfRNK-ePH1ZnAb+r-&TY-q7u=DXWqYpdS`=Xdx1;_<p{%UW z7;*G2KH)Hg$WZ3H>X{FPk^DBivi#R#n~?XRjFR>NO{Nw_YgSsZb$nG+N*eBh>IqKK z-OShMu)+`$bn_L}OtDRF8o-(0w@|(~Q4sHnaM%S_QU7Oo4zI!qJM3+-b|9rNF|niQ z0uEds$<}(q*c9OkN0E9WhAByPA@I0i=D|cRx~;|Bt@4#Ivz()Gj%1r{w|6>XmW79- za0t}t6zye9VX68dsB7)ZwuN;WV<nzeN?O^nY5g`5kmt0V1MNYOAD0;idy!yW#X`q& z^X1=ed&l**>us?U%oc`%qwGx|vG?os%iX`ezQ4XR0$et(%%<uoGa9A_FaxuwVU<zY zL@`H&e0_yoVl*#w?7h(1)z^w_&uf+rmz8jpSi9`%YH^fO*-<DW%(Frk@->=wX}Mr! zO<Gx3uW6A&r-5cz(rdaK=JP8>T@2bYwbl6t)rDfsqh_slE%c!P9c<sBD;seBq&tDL z!S#-w;u+oDW*3clXUR9#dy8fEb~3JF^-HugzDu(|HjbeprFD7R?$uMRwy4lKshW>s z2ekv^-MY(P%vsX#Zyrs04Oo!**5zKJVaJTl$0n$%7G$$LFV_%QX3iZfp`j>J__V&< zC-ru_t}WXk;s~L?Df<k4=R4;pD3Fdl8w*adSktT#6^yGI&HQborXn)hqqK3R`m9hN zB?Gq}gUXvR@xwGF_dW*9&a~^8fSnh+xi)u~B|V~lvM?^+x)~hbp?#s}i{R!HR`hgX zLeV|B#(2!myK_f`Fv#eF%G^fWPeXs8NZ(SY9oAYuO?0ZBl-OE9*SQ$yI8BMUT15iy zY*t_+qydyk-wSTvpE{T`GfD<kL_lzuPDD5uM!PrFu3Y7f!&)&9(SPT$8f(5IXsb}0 z8JiNAh`@9lem`!C-bf~46R<?;B9`QXV`2mbbsS!ymmph6X{$+X)Mg*J9@pPfu?p$Q zdQ#@o)e?uPK=ojh8JefNcTlFOrzRsBPJbN3SIcEnj&=ZwaR3P_rJ20?wzj>(dF0FQ zX=YNf=zi+ahz|PUu}t36Qu|zutj;BrF@|gucYl=AtGNu~eNd17mg~0+;DzF+x?wZ* zm$lk*oqwP?#s9EiI+ea9R4a7|>pFtWcw(PQ{6?s`n6+OGijc7YW}8u*6=>sw=Pj|` zZ=gZrWTB}98VHY4@Apl8l34d|N6)vYOhq72?@Q|*ndI5%mu`;N<MHO@W#v*m_i|yf z{>^b_gl9D}ZR3y-TnXMCaCR^wmW8BJwT~?Rcqs@(aD~|tHBav=;_Z7AL*<zn3WT*3 z<m~)vND4F>b|*(;<fpTw6lOm5!mQas{&Mvz>E(?+^aZP3oo5)qYMGH}9t3j{XBu0- z5H-)L!Y?u%z!_K}djuO)YizBK^Bd<R1PBLz2UH*f^0LhoFtaG?LRB<}H^`leF76LY zSA#{wWm{90!`#<v`LeI?Kfb>Iuq#8jRKgs~=nN4sM>nNWC;Db0uP?W?)^%M4PWF`w z&c#Zq335);*WJQik>y91tz~#DklvR>**pqRos$d1gq7a>6fIhj%U$L1oxpO35PXah z|JgMvf@vdsGXEyJEH&Cw;eHVO;^#`nxT9Bo>Z#{wX+*R(DZQ*4ZewQXyJJj<s#Q^? zu+((A{1N3F8DA8=Va`VJay+Ral~ye!zMo}k3yVjWyl`Ml%GIJSAL8)P{{`!pxFk`7 zp<#eIAVGQ{Egv^i1ryoev2;;g%BY^TcWi^{s@0K~_X<dwBJ^hLtnuRmOxO+8(kmU@ z9j@WI?kso_KpmkIILsv<oHpMzt2ywoTvZRVw^cI&dbb_RTjQxl<t8|yex@3F!F~sZ zk8TsGxu~=aOBWmK!|g_Jj1Ul?vEtNyk94z;v!;QvEjp`^K|1Jbkw}45;RKyon=w^b z2v+#3nGA{&Eqo#kX$Z;CQFq?Z7OiYEnaa#<U!eC|ie@hkLyH+eHJ9be27BUc?b0Vj z3`q92X!Wv58uW`jiyL+Ek<7A*I^C_m0U3nbAU0DofFj*XUtJj0XFUt89;KoCsmj@` z2d9K7nrCPZU;t24r}W4Ur4ks84RC#&S^8>epbH+P&&bs3gE3f(vxW|qqV{VzG(}(H ze#%<u4~oIp!%M(6N7Yj>mI#u2VkmGNobDe`3YOFg(B5hx3WTH=dpKZBPJNiJW`ISP zZ;?cDfNi;yIP$%Isx!ELSZf|^H$a)rmElT4H_wlVLp;uNa8ZK1GUPcBb6uavO{!p$ zPVU_IZ@PXH0{wK+ClnWU=u8_ZSnerStL(iXkkQWW20od0^+CU3Y>typQztjI4$oSL z=ZN-SdiWNaQ{UK!<H<4fvS}r%!}!lU8NGU+rg`9vvw+jKb7V%_Ci)aHqvM>2nt*1I ziA8_QeL<DnWk7a!h{0Go+<}R>68f=UU8x&ZpP9P+JIspI#!_@*c`VO~yIp=2J1h^` zt{e-%0?ftiCs}rmpX`{dn}lvqsq0}^j@*@5qCCuC6L$%XmhtIUO|<is>v48>(3*(d zxiG`BFHD4?kIUERqK?2OxVcxQ5Z1S(g!U~41EPUgl_wA%ZD3X(X??uBjI45K?c~lj zNH{uJEO+-`zkY@J_ukuLT`SgFzNTwJ6P1a3u0}$OW^dKAVyL!4y%2?$uN8YcfX-Q? zajg|`Re}kEnT=#Fz+i=v6yj@ENa>%?d)w#Hslp#PgGl{s7aSI0Yt-=mg!$yLVmw5_ z@ET-LPo>;~S^xsc!S~N%h=vn-TBz-pkXP4b*=g2$mjhHwo=1;*{6($we6Q<*--=sS z*AqVNzC`zlBuKKmJ)hGwad@8(`7;jxC)ZR%DZC0scws@b*gLJ`cz%w}iEDWF&{Uz^ zN56u)omzTZ;yG_w6Y7GFC){V3zK>sKC^uMvEIMbOs<1wgTy8EU+76RWhvS-24tg$X z%x@VdYuAyGvS$HuAe)KPR8tX;qBcYW3h;HTe|groB)n^0$>1KM2dkNQi*>0sY|@I; zw4|`K3~h_CUKfV)QT-g&jJSC~OgM0}g=~G?y3=4{y^(lD8x+c#Hj$aPd2s<*ml*8J zIYINN7R1089cN+g1~^X)uz|!s+t_={80ZQntYFPe;Y5_WSSxf%pzM2|Rvg$uEMBse zQ`0~&vy``fbq;*CkCvh&Y%%n(7-OAj==8{|Z-oO{(+4(Nujv6i3h!OL?`jIv5q`@@ zE%s#H<gsN%v$)AIe!WOk1h#Nfya~*SjdEcrx+7vlbgi$Xd;oxrX3PD^^N-`P_?mh; zKZ*yiKnq##O>qVy`dD>GhOqra|9mW{%e!THA|0mLJ#>7m4+p$@0OdbD3sTSwi7xy} zqlt470GCtx5ajjuTfe_+0GEfa%?7M2o7cOjBSNgD6NgU<rhU-m@7g|tGxX$Q0)>jW zPMrFH|6vzs+j*(*t$S5zWAcY!{u{m4cN^g8DBegs^Q`>%!CX!Q4aIfCzi(0X%#>jd zXxe-t0x9morZogTc-@no3SW>`!5WnswVuxi-9%IH&}fHHWL&U^ff^V*LXz1MRsO^- zmZ<40<Otgl*?u;A?4&ydbW>=f4Rg_B9CEZy<6hK#mG$AS<D^n@DxGmZs%|0JyyU%` zOqoih+j7TFF|)e$iw0vxFB)r5RbREey)im6Ik#}cDLsqH;U~T*2I#OTVEo=F;{<K* z!0o{g%8~Z^Jt*Ut(hjBOs_$ECZuaXR{~5mC5!=nK<tvR?TEJl*Fanp^%0|8U0$;Y4 zWjJ>O-dqr9mjmeTcG+@YSDD5+w-vVB_gYo48FjBEW@~E)qH$OaJu<ykEaXi3GQPYR z3fk)lXQLa4Y_m92ACZilpr!D<<YxhKKJ7H6&*o1_csvq4FZZtIU9T?AJT(tQ4nyj> zgJ)3xU@)h_<@}M40p(|ko^>%NreHRhqy9-u4t*V;J(dgBrUtcMvdEClbYq<&shQ+& zm*|-J$&so<e=aJoh&K6WAN`qFE{~O#?|N%Jtke#-J+(UE3TyTvcKXfF_ySS=lge{K z4?J^Ttp#@B2!0pLih|wEmrc~Vmu9xcmnQbAcWrZ^j#OrK`p-~_KMwf*wfY_G<0DYN zl_y=!wW`ro=dxahUTK{n<uUKO`&RkJJlfR9@<CV#f)D!6W17oZprN$3aNvxNbAS~s zv!}R$ZQz^eTri8}aPQ(pK1oXrshr}K({W?j-cdU`=3SztP;b#a0jtJ2KW1{X(-@9E zf+ciR1r$y_cB2Nb_ec3lCIjnc^$qNDN$NUyD86DCZTcF=FPrr9QBa+9B6L@K>%9T* z&s-!QU9E7h6ZO+Lnp1UduC8hJbF>c()@7(P-DS+tJ<O#tW$QiEnY<sU99|D$@vdmi zg;G!bzYls4A4QcL)l=?s;a)dpYDzIHKX_x&3yA|j&areNsx;-akANz~$E`#LonNX7 zr2I;LrKdQT`DnHRE>w6-mv7@onetoLZ&!hSpiIS%-f0MTc1fgzLC)$>`ix%bwnOk! zRlr%lgx*}GVAuL#?vC6u8Y3(eQ86k%UwfOcOQs(_EiiDjERj*QlIdDfLhrUiKU4E| zD6*}a8e=Zn7`p%fAOJ~3K~z(HqhL~O($IO@;H_w$RfXDvdY;~>3m%H`6?=T}5!k@$ zHSbzzwPI}H0G$RQH5IG|AImB=%H1vYj>vG*dRfF?#vGX<g>ulhGUx4q2Z&B;y|m$6 zpw>-PxHZZ}l4Bo^r<?g22Z2nlXdT$)%4{{vh@_ig#}t6C*RTKizy8-h{_{Wo`OiQ8 z>uXo26X5T{GMLkg5G`H-9H(2h+Ci}vSCLTVHDp;bq+)fEWd)Kc+{rnH<8bAJFROME zjdD!jQA8%kZWvd7y?%xHA7AgU_cp(rAzdb1_+G^-FZXL@<J~mWmt~h^_sFQJ8o+YC zGKsgZ+yh{w(G}Q1Vnc;m+$B{^C&L=sO(2Fil1#T4k@E^<Lprf_#PZX&YmG$o`1vhx zM-Mz&^(|C8L$j`04^gU!1mP!B8!+)epIKgq7=v#sT1y=i)Azcz^A;O9M8p<5jSwby zpQvgJ5AIRrmV9-)45qHgGH(?dWKw|s<{*oqD*v^M%Tfaivd7RL9JNUwCYVL_&c^~$ zGJ;11G)O^dzP`;0Y0Pd(R1{;U>|32TK@G`{AQR`Z`Wdb3902>Li8N%a0|Kd`dt1~a z8@a93s;aP20!KT{w_;%Ic+)_>Ee=?9rQT@mRB%4o$5FD*Bx|X^?1@C*PVY2L({1)9 zTyBJj6@48`$n#uSEe45$(h#GLVLZ=*as?}VLqF=0%1fCxnV)`39>I=1_*LO;N=P2c z<o)6jsgTujEuU^Ac6}6-0=vk6Ds;|7HxOHtAQ$8`olC+0g@)`tO+;$SmPFoAsvgx) znTx+~dbO}P(Fx9P3$gWW9_~w!|4KH6b&rnW-*IrqT)2jnsNzaC;^pbvydV3aW|*W= ze0<|O;@wq;=v(fI==POXr|R;2W~<qKFhfxAojq|Mtgh94iJt46Pr9X(cRq+sTY^2Y z2psBW8)G8ln7}WiNHnJ-`&e=5%(_biPx(l`dPIP^DS@(32;=iNwUTLl95^qg1N{HY z0G_%Rg>j)2=CL_$M7N%&gF3yq^L5jvib&nP<IK=ps|0H;?K#d<sYS0h8aE?!Eb+*L zwplNijbZdlgyQ^sU8DQr8U=o>F|;oK59T}QL~b&;eONNBv5tN!#1Ed)=&wfQ@kWIr z&y*7l(LamNKqni?a1JNZMuH8wIlY5D+*+A>DQ$@5_GaX)X(HTLIf~Mz$R1FXzY(zI zqiKL$mm<uw<sU8LI<Do@6|Ps#j!qIDU{|$Cbmq)$)5B7F5XaDPU@Su-MtoiW*MI)! zfBSF${lEW@|MB1d=l^`a_y7LC{~z=3YFF!mzi%2z4~#c-zid>(q5Kr^*<ac(o|!5$ zT*ARo+Ll@xppuD7$LovKBE-6kuvhryJAr?WCIBA3BEECA^Wm@8Ki=X0_4WSa+kCyQ z>oORzl35(pcx}CWUCURsVe_=}w?(Y=s;)=AvdopNtNU8UurRBNRC0OcEfcFe&)6!z zlXDHnULS|6OH?cOA{ms>=^~=o6opxKf0r`VpLHPVJ<~x8Ld%Bv-3R(fUW?N6LHDi0 zr*d>#>P)Qu)dSwJkwV<Sccq8MZ82~Je|DI;i<WQQ1)=omD5)}KO>y92mwt+&$!5u0 zrHNg~`$Tmpp0HqBezLxGYCr0%KU{s>Se_c(aXeK)$T~?TQ(c2HsaQvcMCw7XPYTN# znS&=PEM6#l@=-EAPG`{_XDuv52%JU~p61Nw9JO0r>}Pmw4mT0JtBo66tROvJ;)hhF z0yiKvqSE>NndsR4<Oc&da~j>&&20gxB(c;sxm8&zy=Iqu6qm%<k>UZWL*Fm90j~;z zRGwAgp=g&$2?i>b*f9C$YWrB~>q3*kQ=9coCr-#~hvsu5@P2YD^sPh$&N5RC`+ntw zvrhi`XsUMak83EbNm^jav9h^?2C9CTh`{v+nX$b&)ks-Vc_v8qx;@*==jFHbgus@u zP`(AYtn&<*s!vq6<q<bVcb|wo{Us)K<s2mNdm^1#cOwg}pPVhKfE=?$Tx$3qhCr8J ziuNTPI|3;zSlnoiF;?Ko+o@XjJ-Ng0?v=56fq;**fU^*Q004A$Y#~gbka(HxVLK|2 zuRC(TR0L}xmZ|||06+PBsVBsTiv4qh`maApg8lcezr_I7wid*29}%(hU_9g#);Eef zy8lA()n(x#rj$ii+kQjQ8p<%L=v>(jy+S)2W#v$2c4AZ>CiOHCcZ+sNJ55T-%cb*P zG({s(3s5a6X|$8uCz9Yv)1C)zw!?=s8c&FyADgy;CySg4pDG*+^7#Lw?cJ7SNpj>s zz&x|6o8$|Hl>PrN+ehxo3WvgnnPK<z3Bx`ZRG~1l$hzcdmznB35#jE3f#IqE+^Rkb zTW)yKwTnS0nnoLr(<2KYkh|NAtfQ328o#GTm~`m9v6{rPBZq2f00%t#9$|B}`(pxL zRz?YFIp9_xYGLkMp95XIQunaJ4h*Y}5p%8_wrq@^-I&Ic70}Jcc>eo;|G)n0fBSEL z{ZIetZ-4vyzx=QN^&da}F~(Tjo;Ipnk{e80XjylKwGoGO{&<Oxr-(z$twl?DcMKN2 zAWrouXM~{xP{M)GjQ7Jv;>oAkTpovYOl-uAIpcGDJ|DlnUiSC@nA4t*Uq1cgF@J`C zxIM`B4YP@8?Rdrqy7Dfc3mV>xU&bnHh4kN|``kb@H-eSE3}BBX3cwOJ``15osgDHF zcCyO)b?Vmxb*igQ32fd76a>n}k7fQ11ZUPD%O)3>6bs0~AoQrpHn&5)YWvjy_OI3F zdYU&?MG!w37E}7ytI~sZJ0i%WJ{HFlVVe3_SUpD{U|0pwPFXMsaMwF?k^THoCSsfX z0&gzhhN=rly^A5{@z1*?zcJTGMSldm_2&X^rsGNipbFF#JGa_6Q!kI?(<~MovPzpG zRV&sOLG&RVQhCjGM(^7iZuvx!_Q`UX^%OfY{B(Is>YAs|qx5fh@6Nmxy}DPZ3@7!8 zYXtsSf5%Q8s%eVj?9Ro4XHiN&31EBXE<<{WRPEo(BJFTn%NVXv6sS_QJGFc|jEhF= zXmAC5m24UD1q5zf&mfe6@WcZ}|BCwCag$tF6hLzDLT3%PXx48%P!uG1J$o^iBdRTo z*MzF8&{W)-WAA~7o(@LaOirI6V9*VIIem?{=MnCf(P5HdsBJ~-Sjcj+^J1Wmz4cRZ z<$G85TUF3v{}RL7vKk6Ww67<|S|vGc$%SJq4Tl6Os?5D|7NZN%B&$h1U8c#%$#1fH z)C=H?3mX--nM7^T_9thwi6IkryDc#Bi}_zHu?WX>({^!5vN=bRX4Toc0LdoPx;p_z zjmyK6ORKPOmk7|sjYT#A7lRxZ?Agz^g1>D5JCHeSEJjAK0!pST5wETS$`xk5RO&cy zr2miynx!CDpO_bteH=(OuW-C8@JXMT;6r%#UEks>pu}Np^1C?Tt^7vAzJl2+xwvPK zIFd!m6IK@4jM5<=UX&gyagwZu752?M;w9<XZDG5T7d%Y)TrZV32TF1cT3CRBH-R^6 z{aXM^(myT9#%m<9wCN#Bs77`}b?yFQJ+a1-qs(G2U`jcI95!cGZt3}Qx0u6LpMc@u zXfqa^CWhJ5v0=;-m#U-(>nKtq<*tB*&#-?$x&*xi&-0l1{4ruqa~~g{zy9Sf|N5{0 z_CNlg|M%bi{of<(`TWf0T$xVUT-U5cvD(|ttdR)=xSDVdvoVHeE%by1EuO&YyCDYf z#G!kbWMUaH%i58Z!Ufci`#SH#?J;-vX>&yQD@tFBu-7YIBgU_vK0g2PBVN;=k6(Wo zAM<hd5BHDZ58OIoKG$5v@Zrz!Pm+seYoZAM1ucy%%U=~en>`E4HP~*%4IXfxULG+U zMZ5w?EB;XDX!%Oq4Bq!<{d&<g9mxgtaV#gQM-No=StA_b+I&Lv!fe5ZGgzK<hgNsW z*Y)9tg_a1Cjdqd{gD0K7ESUJf>4c$kb=p_jj|BV7FHdc#+}mE?LXk~`VN={{KgIYr zz6hdx6Z|?0>FC2BIAm75AdAUPfo%yg;XEa8*7*-#(9)^7l36VZ0(<d@IJIH*#}R2* z*}An9s8<g`JQOKl;<D^v-e?Mq+Ju{*$Who?)M`gVldjQsR_Rn0vGq}4pr-I8*w0xS zAIyKI!simk4DhGR{&?*oVKV(oF+L-mfWX#9@Kkp5(s7vU-(?xM2u-fjjG!Y11_R!R zHjUJYRq`KshF_qsZ6g>6#bDPmU?!&)chQ-MzD`+R3#7-*<ScKxN>LH)WHQ-$r8Nh^ zIT3*wr?#%~F+q#e#_KUL>mKrqf|Mx>Y*%c7JKBO6Kro9^wq9=tAaR_fgBoE(iA}zj zz}>b8d%Ra3k^(xK;eR~VELLC2)};nN7^yag3L2e=c`}Ol5{o3n5*2_E!EtV=5{4p? zQH7+G|ExXaG1OiX@@CaKcYjpT?O-mV&ce**oHSP1z=S<bCc*iupG&HF7mt!;`IQRG zjJaM(R|oGKNlTQ@ur<m?YC0kuPYNMCv-q&)61N1&ZBzDaQ~r;e$5N+IAaFf>zH$BZ zbG<Ur0?zxL60TJY+kCA*@tfB-t3Z>jFm$;-Cz^#w3}ulfe=A@01Z^7Yc{Y;_(|)v& zMyC%;PG)4^tj<F969T9X+1i!fwJi8+YJU~rDz-v=5ot&yF42;59u^WW3Zqi$PLDIF z;@MPBUJ98|iNZ}`DMc(^WmkLurJBuKz73>Qi*~m0NK>+=+Vm%EG!XKc0+5s%26kd{ zWzF2}@dj8bTO3cOD9VrhfvHtXJ;;6#dJ6N$V)z&cbf=~p79Nkq4=*jmBDU^XLfD($ z?1W-Z^9B8e<`Qlb(N~a^xs4Bd9<yKBfZG4RfB6@4GasM7{w0%eJTeEPz<W?v{mI@B z88syxxs7Z>w|>AnPgrw>*+(HYf{JobMTEWXW{*KMuDt6Cwa3d|5!uFUTFi)eg}vf& z`<P*FGyDmErup>Yzx?&}@t6M-A3yBl^ZDhkAD^#}$Iye<0enJ`X@<w}CtY2ITQ+x_ zfx1`DdQnL&h5Yy3QunNT4ELT?f6G#9rQ)2&gcfqCP3-ZD+GE=(CJJkcz~9<$Xk**c zDYm$l@{rhv)DC0pe>7P#qH%9lgf@(XH9zTFBy7?nh6rQT4+P*H^Wa@+x|k=|+RGxv z;y>ELT@|}cy>5LzdmwjP0TV^@;CTCoAsfLNO<~YKK_o}Tc%}VmkYAlvP2DPkCzX}% zRoay+6=fIFnqb%L-A8CJX}`YESCr>ZA4x4fMzoxybJ18STIHtqWlz^?q*I_OoYTC7 z+6R|$ASUUjmewZHJqsFR0o^*yHtbYv=H>QSJ+S9*Uceb?I=AUG%_O-rz09oQe`=6l z5Q%JV=O<~~EN`WG3t!U?Z<|7&f}X*xUh$THtLk4Bs(nAyue4zy3G_h9`W+*DetA;3 zS?CVM*l+m$SnK?xZl}da#EpKtU9Wx|wvp(3`JnCXUtb+-vzzO2Ja+Sg=!*v8K<}>K zzbSfV)y4MprH6&dq8#nU<g1LIyj0zqU-0CuR$04%7GxPPH50?zNcLMh*CN~Q+3<~o zt~{_mDlS;({^R>4L2p$jF0sHjk0o7UJYF92J{S7*H+H>S-S3Y4n`G}dgVRb*-?+YK z0LMo`x}jSlWU(qzJS%BuIOXds&qbwmA%wMhblL+!CHvIsVv}YTQFR(BkhAD3`iUdn zxJsnP2rW$O6H2b56wrF!04Qaqkaps+S<#lnI?M)~BLg3r+YFmI%NT$tNe`|}EmN|d zU`G(eQ{h-_JY9)`Sl9_o0^d4WwbW@~-h7ahs{w}l2qe-ZqRfXh$yl)niAZ}jc7U|j z;zOHHcfE4qVJ9N?2;gUecjDhXlh)YDb8>@{C9#x`;*m0e@Uh?))GG{i2$zi*;{zV> zr9oy(koDkENi`k|ww%7k;R2ZkfZff8XU-d2l}@kt{Znv0Pm97+7)R#z`sZ@ZWb7m+ z(BQBqD<BC6u+!`D6w##XW@X8mxinjH20b)_L_LQ2oTY{l+#cC}dBst~;>RkV6VoGN z#w#o=USY2pKIgCqkNA)I`mi6L;~&3_`SHXrpZ2%uf1m#Mi2rc+*T?_;KmX1D_4(ib zXFk9D^{>z8kMRhM&%x87zN2y!b!vBHG_cK1eiDtkEV9Dwm{m!FE^uRDGs{jmQj)w* zjdG-ctx1IZ$`o~9oqpHaKIH~$h{lvL-H(I(>N2mWfAft4LKWVwYLN;ead0^Ul#8X6 zqmD_q%(vjyWL(6xrylI7G{bA|CGTfeAq`mmYQsN%39$`HS6gfK!wh}HLOEM^iN-1g zM8iiD+gxsW)p-vbMoRI9^W1JH$azVG$qrr?Yp)^Bxak=c{7oa|i>vgNV7!Pi89xmw zy~-!pkjyRJD9Wx*nAON_^y#dZk-oTyU=_GyMwLnEx4}TLgPFkhGuP53-MDWST<VH8 zEgs`6kglBOdcJyAce)jm57u*@1?*W(aUxrI>wDxM(9R3OSKnnMcC~)VUXADh6EEbC zY&(c03Vp20;bPn`q<@Ue#mef&DVr9<&1N7g>Oy8Sis@4>a4xj>=%TD1S8lK6Rjt14 zx(3Wmt4%S{k-*SU4L$=;F;=Y)oV&$o*sNug+}t-sEVnC>6uvLnGD}phyihNlYP&cK zoRnM^FGW-&AWHJc38KfGSc%qa>1rLdmr`1Z&Y$xw4J{9QRkYfD9ZtxK#t%`Us5x$| zJvIjLyi8YIl0w^GU8!q3^4r=r4`a|V6q%Y-BKQbpgMQR}LWP1-AbYB|Q~R}&O%?ot zWI=TOC^@lN^4nYp;*C;`Q^TJTr%$ABG$c-xkaes08Y-uR-nB}csPn6)4e!i#uwV69 z6;&3LkkW)|{8{*5eI_<-5E+3kR;fR~M8v0xfxo;|#(?ST&?q>qmXfKF)ZK;kXA4RG z#`VnzFnCawbcK?EW?_o^%lJx55F*JI#ZWGmw(3#Kr&*&#BkBM<FV@pjbK0zIZ0Zx* zoMl;VWbRan47>>q(ENOCjy$M&1ZO5_)vVN20|h8xuQFvDZ)r*=g3Q5>NO_`BTm8t? zcS8pgMW*Y^z^vsATYI9TX2bRLow)t}&njx_$U<@g(ot7f;}THsI4{?SI;tnL(lJ?i zb#*5}w*S)m&{Y`-g$VN@3@C!}X>gFB)SR%K+3Sx<xsht6xyQp$+p=k8+h-~dtMswM z8R?!qg)Pi&I!udLm7woMH7Iq%Y$eP%a-WxUDj#7!53@iqKnqXcH|+<T<}uR%eqbv6 zz!@oCoK=-$wc7SHxBZFn`SO>I7$490`0J0)Uw-`Z@#8PQ{QcMe@<0Cd_4?c2{{8jD zum9P7JXUGiwJ%QF9l5&w9Jzbg0|U6h-YPM7BT<n?$k-J+s6~|1;rq#8st};jQqV5$ zhonSiF$ojut!XW(-#yUfW=>a4!6t79Rv$)P-xasK#gLDa(vifdA5(GlJ4R1fIvfOq zSo6shP|EOKuo{9c97S#x)c_<w@*JX=-)~*rT-m24ie!oQP3deudb7p9|7uI7Gf#@7 zo?31oKeoDI2rCEJsbO=pD1Iw!U$}V?164S>kY5ozviB9`T9rN&)$@yG1$#Mb%@Auc zNGe5^mo_bBXSAo=guBIbXjJ=^epD}8ijZwZcxz$f2L08ngl+snFzT2voYRZetF#AI zly0%#xP+h7Co1ys@LDQ5%`4hliNP2)gW<{cq9_WL11qzVmTehA#ho<W$4m~qY{#ni z!3n9kfRv5ek|N<6F?eY?gG~2D*Q$srj6H8BUQ!XWE-791T`EOKAFR7rJ9P15m8{Wo z8zC(&^(ov*OO8?ro9MISQF4LwY^%{9wF?5WaV=La%y^^TolwQiQ4hYc4J+o?zftmt z&J<+zG6vCCiIgOYZs-qqB%O=6$yO?#=P_&w^ZtLD;bywsThoNLS;^gk6x@Fkx<;xD z982kaRck4go2Y23Wdu~7tAYH8JSi+K5j_!1JO(|@0AHxj>##<gSd3#X|Agy%IlyIG z&Wf$2=veOL**2+YYXu|~QD$|tP8EXoupj&Mb_>@fiNqP0oqaIt7EVOA^K>6_<DB6L zn$YKCGpq>W(Qhw?y4acTv?wYEcwOQNg)vz*F-qKE=*eM??p~-ct4BO-7JQCzRA?i? zJO|VYx{dZ==-Wih%*R55qn4`cM5J8Sabsg2vV^{BKf{0Nj*26d-%-A5C>BQ7R3B{? zLwKMfYKB9^2yx}+Q_<Zw&?=TPuOe@=$~?vho2cG2LRHhGgb}M#d8(?VbGNECteAUW zZLZg}n5?h^#K}@FL`djFP!?hhhLyu|2x;}KC0y~w)o_UYhs?3GS&G@laC^phh7X^^ z;^XtvfBnxNpTB&3JmYix<Ky%1=C9ZIF`n0_&#)0MtNa`mB3oj7;WOQ8Cs=seSHK50 zH#l!uzHnm&UEm~3;QhQqxzeG<W8&~Y*Nse7a+d<*#{rSe3J$yd;M~W;1?w!x7NpN) zF$(x=cgvQFlp9MlZ<+1%^cTzBI@Tz0!BCQkv>Ng?05IVTcM|eerrt^_0u0OrbS4`U zJ_CwfMzGU)stlIvzpt{{74+EjBxlF1T+%5iQqvA|@b_PtVwV~}d5(1QsPG+<Tw^p9 zpOzJkt6)0JL?89C${cjtz%Ryvu~2sii=xBAwLpWC+_ad!qWUD)Nk0akuhKvHp*VL_ z4HAuSCS;@Qbl_S^%uWGXhaIIE5%UR6&IQ$`*2Nw+NMA%lGN~1m*ap>l3mQ;MCrU7n z1RM}cO9T?3N-nF1S5%tF@{`EAXRlXPdtCNQoK0nGwQO8(Okh0##Ei#=xy5P<AU6k^ z?AeTXt>T()Ml-LK+X+d9=u}#XGVt^S@6us{Fp|154STL+GE6uPXkQo;K7xtj292mH z-3CJUbm>ahSts(Gt@|viqB~cH(@Ee>JI8t95Cvl}!y=+;;R>iY^mJqdMXZGY^EAYY zrrbp#1)!NK#!Bt%=20)=S6dw){zpw9FEgH;x*ATZ8%Q__hvKumyT*o#xE%p;xZBbV z5&Wu0%dmP7xyEN}&{*eE1B<!-N7=Y$L4xs?Ew|e3A`=RD5UBYq>DpR*$^f)F5`=zA z&BQ@y8}pEzCCAt&QU_m-eCS)~-!C#QMsBMoXe-5swN=;AI`Y$-duY{|B@Pt6m2_7& zkpXVWdM|vVAO5M4^j4A1e8shi!}qUm7Qtff%>YoRBtJ698Q7{5vNV1%N5$mZA`qo1 zj@luUm(+i+5n!gVF$Z?*F$EqMY(KSw%Y_!{gu{$h_^Z$Y?afupGSraUO)UQHBam2r z#WQ%8-8EW<((EY}$I@bB^)ReA>IvT>OY0W{kL@2D(3r7dfl6QU8USMjR0yt{0#4*> zw#4y@fOKWY^1AY1F)spJlRqCk|B=QLLKRL?i5pAvnCF_0VdzeTlujyj8GJ-bTH1}i zhbyHT&`k5V81X_l(*Vxw+=Zfa`!IhZBC-^)^1fdD(^Yc~Gp%S(_j<KD%&;j4#aIDE zlSWo)t1=6R*^|`gVK&DY!%=M9EyfS`F~-Ljt3B^(LNv0o?(k<k&+{?H$1|Sse5@Zl z&*$so7aPyVaI^Ujdztw(pW$=Pi17Kiy9D6Y5C{r*3R;o>J1|5lF6zAG%9Ewc11u-x zv9X<e-sm+;^?YTvG-dhP3sG3X(cFoutulD^Rmp?06GA*SRH|aELu593DJBZqTmQhK z7Mi0n{Yq|Rey^40x1EzL7DgTD+J0lRoJXP8YV~kfT(j%T%d-k%8*$eV6+sK3R`0ks zOE;hCzNfbll%E}UYL-+T(El(!n^Y@y5%9;a1__I5poQm-G~^;sH-1<+>>|e2tdy<f zIm4R(QrE4yaluhziJRpBe&^(eq!KLgGN6vHwQ!Vz^K6y8xXYfbx>gTn2Fas=Y#I29 znhP6qo7cfC8(=o_R04C<YuSfkWtoCG@TkLr;*CnNd;*Hk=OmXG=91c{arnG9D3oD@ z+b|ym$(DnIeVr{n64pq%g8A~Rw6&P%v`-(VlYl{-NNiwAE3XRTH61H6V&F&QRP|UL z2X_@;&nT9qBO5fWyvzVYM#C~()PzedbQEoSnN?(-T*j!0xQhW?Q@%u~f&|&fAi0n_ zpj#H0LEs`}k~MBZoh&L}bgdle4~06w`iv4Wg?-?@=)P_z!UYCW2BFMo&+-)=Ql=cz zyr;?*RCb2=aM>)^mUfdmcFZL##PUnl0btQ<{TZfMcZUPQ6SrRjEj*E%;@EXHU|^J< z>tz(gL~6p84wJGEL`cCJM4$-bwHZO3oYV*^-jx%)w`d9O+&&lLoSN%|w~OC|@~bo! zL^UjH(;zRVKnmi9u%v3A3q@Ed06b3^m-CjOIU!^BYLetmEmVi?QpUL8?nh~cv;4uI zxxNp9rrzHKlUHV59DDO1iwvrZ>Cr!|+=?L_W^pz_MYltd7GM{sBwo*(@&Lg0CUZ5j za21BW*waI8xT(CWE=B5y9*uFts<26o>kvE$C6jR$39hp-O6>=(h~0PMG~>BcE|oKD z^<-f5*7RFt*;=a!`ALeo9d9a66Gvzq4=FbljP1oUM(j2@H%N;*6vvA8z+(yMcrx?` zt&yscvz@)6G7Mr2hyX#JJKhYtWx(?`>i42K%XsE8`DH~){snZVC}ip9!X~)QZM(xP zB7?~Q0aqsWhN54zJi+B2dscoddJ541E8*=(YFG_)-B(4oC(#kB0yCNnjWG`Aib?<g zAOJ~3K~&s*KCji77gecjq!FB~evIM%VLohp#Q2#0*cj6v0%&|Zk0n(4!+h8?=gVK_ z_JMX)DdTaThf6_z_tXr$>G3x@X-3?UQJJ3ExJB|%VYBFS7qLyLq=Pu#kSpUYaUQy2 zo=14U$e2!zbv$8x(|FLaowt*#ypbhPr$RY29oQ`_&uTzw0ITWSxJDntp)a;|a`4a8 zu`YtIR^a?%!!p-n&&{y3l=5-qpiKTdGTpaA*H>Qpv#v@{@N{3{?bXwq31EmOIjgTh zW_ftA5sE{~#FI;x-V>~Gk)KY0iKpmxV>J<t$e>o_qR;^p#~zH-p<O;qoXgU&3REnH zokkL7Ke<-|ULU^1COLmVUA7(`>1p1;;oB25VX_M;v9EA+MAr<44_Bpz%?l7(&#=b1 zFQ9M#E8)a4HK6Om;~H^0cd{wSUz4|pJIqe_n8S4&NpdKfzkcwho>CB7e3Rf|_JS5X zxx7gR9j?DU6L3S?bsZ&|M639YE!Z;37HSH~m4ooZ+wo81_LXO|QefWf<MyxUjv<ps z9TJhE@D3d6taFoRTuE1<r`v+BkB>T4OO0sw`<3gYRa$T1pUY!&3enJqE2nGXyu6SL zRz_6lL=w)Yd{6eHJk78BkYIq-n(R5K???+WkZc4JSsmS0buj?XF{!f2+h`fqjkkTV zH-x9ce|_sy{1KP<;eKxox~K~vh9NYAYUGZ`hAR97Sm|IRg6?*;>E3UOTW4;JTJKT1 zf5!Dq0~l8;v$3vg_oFW#QGW!Uup4RO+*jSJ@0Kp{Qt@}=vl}#u(-Wn$e*#U>m3jsn zzP}+~+DykHp!Su#U76JO7&urDUQ;1cS)e)hq7nF7Blg!dd3QBj2bJt)=fuu8X+_T? z^GfF^i6D%b@z)osQJZqb_xza4rr940pHR22sVfJwDy*!)Yp~ji?q`V^j%&(J@xd&F zE@1dt5J>ApCQ+{)S@67+zc#nwpSmeh*L*bpE^II#8IyVJlhI!D%#?LxvjZ`{nhcF) z+%7zG#1jc@4o`#D@dKNS!L4X-9<aJBAM;^j_;`Gk$8)#we2nlBV?jBcJ37N+di=;E z;xVOOSDveJ(G{`IUlQ~?d4tDN=w57_1B6)@dlwntJzt!uI(M)Z0x5`8$K7I7v#={? z2x{<Gxb+oF!mr*uw!Zy++&g$G<Xku0^5up%A6^}2{PTR&B87K4MBFH3d-&!T*k2*l zDFgZ$m-##Ou5P301cO(vCgj87BeEK_vq}jF9`v*3Aixc`0PpguWL^%1n`ZB{+@2&+ z#&Rn^!YX1G!KzMZtr3i7!;hdQ$}iBU)I?#iKn-nCRTX<60qt7BW#5HR?a*l6^l2*1 zEJ=!SYRu}e;dtVf28EKJ3%LVZ%gk)d^nR6lOXmX1dCO@%6Mabr1X*;=pKt8qLk?ru zNnLFb0(BFEt~C9PdSHd6#4vw(IN&F%V^ilX$IfusR~|vxR{8ABD?!_7gKunN)K~yA zH2hvRMy^j(RXlnO!)P!sr%Y_o1(J8Wvhbu`sY_UyBVUFfyU>Z8cagdti-*=k(Pa4r z)Cv{qqPcb5&DeLPP<wV!jZoE(4SVa=?|qtm1uScYL`DB<rWc==Xkwl^wvz}!FmDWR zqaV=yzA3u78cBMmfrH)ID`KHOmomeGwe<11`zrw2?@f=Qd1Nw@WZ;<>--JLZHO8w$ zCHGdB&3o&&ZOU4`PaOZ!7W>bVybGGNt@_Tu1<qjB_;5|c^xIB*W~I9I?6aRLXL)@S z0^QbHgzlzT95-4~+co9au1-F;f*fSSUPr)vnh%c;+1)_s#k+->b^hCX)wYrdM$N}% z)EZ}?!!(Eq;T7f|)`~H-8?9o4L}fUt7N;feew4+kf9^xa923~@7vC#VBkmm$mBO~3 z^qy8+=KQjoF_0DIbX=a=N&I&NSd1goSAOXB#zr%4;%Pp|`c&fI@nwcTAcp%y9$A)C z)2+fhsQk?)OfiGWpXBLWO%jNM8|tzu2qOBiaUbXz%XP1thfr_d&4UKo*DLoGON5h_ z*|2WEX2`lcKqG5Jo5ujAHQVQ+BDH&D&tagRS9Bf5=HpM=Jz-`xe2lSDf8CbFJIvDz z9)QmK<1zdN9_Z8D27b5@#baj7wEz_>0;@fEn7II5GTzX5t#$d2_kg3fV<OvuPb&m^ zQqiMCEuJ;?h`Z2#0=5$e;XLyArEkqe+AfzF&?f?u<Jw|@zn<?`2!Y(oYrU(&8n|vS za__Nv@cS>iXnf%azap#Kjc?+)yJogK2!g5r4p1;Im+c>;w10L0?vA~S|MyQ{O~s${ zrPYa?)<UhkgyBmG4$Rcy$`jv2oUc=1&HBJ+9L&m7L!~g=P|q$hb}dI<C#RqV6RiJ6 zBdEeWYd6(7wYhQ}uyn%3Lt`}*Tnq=XR;oY&b^J%HiR%-rQk!!Tj4bLbgoeGu-(40& zaT)fk*Va0Lr=faw13@G=a~kbx$&|J&OLVSw7sR11U9}4&+Eqwf*6&zfw7{ufJXUzG zSJtxFzrm(%(6^#%&Gaw#IwobMd|`}j|J6&W>)Isd%9m*07L`{1wrdzOni+r9Z~Nk4 z$7O7x!>D5tW*}o`iT7jDb`ylQSv-E>y<)vo6Nvq1TlNr%cJtcABfuHzfJ%OwHdz04 zhpXt~g=ki5vd2sm*HT!z^%7n8XshY~CzqKDez?Hu&Xl;*#^d~>Z<G9035@4`N=5jv z8b?33Z#gijlvdC0gVG`K$0co0HcrHeSzjF8oluo#f7!7~Dwu{+Na}1pbtuORFV^o_ zSLM%L-!p)RX5nv2Ky9<xJ|`3`eHWdeuJc7Sz@a;G;bv*Wa+rZ5H}huR2v%^lTGfQ2 z?WHmv?^Nh1lOm)tMSZnCdFN$c^DFeJCwdwEPIDsL8mhB@TfKG5^zax`w`0HJzUr>K zxg9pQey-G>7k6FnQ{t5Iy|}B+s2!nh(+zTj<J<cI<Je#$#Ws<Qv3|7(@_IbkvoEVZ zAhVg(p)mL?aBR1wt6ic%(xLkBPVI?V%dLxZ?zl!gI`PI3vh?vl7nxl76}&b3#oSkW z9(W@hY55*wdX{=J#(viT;5P!f4$*tuQH3I#?mo|x=B^L(5A%=p`0UDS;Wmf+C;}Ma z!)(k_Ya;CBV<kbaruHsH6x=m)wc?FXa^D^kO9uhIJ?z-V1a?-N38Ldxm0?tU)MHcR zn3TCiD=}kqp8p4pI`WM^?+1b1hM3`|o~cI0=e0SQ&J}ofqqT#{k(X_@X*NrFqN_sR zr7tDBv;Eunt%-bfBPrya3R|sE^F-z`TwDBV6Is2%z3C3eM80#W21!7yW&qZUKy0~{ ziR8d6w?-rSStse}FYSYI!7}s7*xZ<KNJTxJhPPS;UX^;afRvK-ss5hUnoAh!GCNiE z0!0t3%Hz`~YyI$QF*Zlfxf)4CwW2}EjqHqNp{0xp=`FmYLhh<^)Iy44%G)>GR9P@N zG|d=lTiNy1)6sl}CFoK-rE0O(rr*Uj1+T=j!Y7ON75XV2;XuBuDwsgHCVfJEQk7DZ zg^T9e#Y_`z@p`HXOOrv~(stdsgeYv=v&d;eX|IR={2Ic_e|FDxS-Ei^zZ?x5JATf8 z?i&xVp4{2A5X?l5NfjU7$hGsR#xgqZC_G3x)Yd;cGm|<j4P3LG>ss&12(*Z~VF~ly z0#Vu4Je><m$Bxh!sR;w&m`(%cqY4$)H1+w)pW`qH<6<)2R<Dn}xx?ggD7q$8-G1;M zgLXOc`--{CdF7*I3u+i`+>HxW^wFhqitKUyGMGW}o7YcC0RA=v+WRUr6G@m|eyh9Q zD;w>9^&8s>$Cf9PBv?G!L2~T9g9Qu78Idc``1@C}>V1TC#OVs;<F_O}SLSx*ViP58 zn5&abZmXb?cLsD0zz+J$>LhNPD+<#;xN4k_ffgNdqqc@4*pe2JJ}hfHE!u{4A*BV~ z#9Of*;CLVh^UgqBi$LFpoHfVn6;E{mg$jIbTgTMV2f*#kqvpt4<{B}d&Ve$vjE}d( zBbJvs5<gbrF#*y{Zh?+LHSw1C^z<ERyX@g(nN<(+{T#9;!av+s-R9}oBNS%$3CJ?w zVTg__uFZ@*PK{e=4;on682&ske|?yLgn!yt_{~=$I2VFB6WTreaev$gTR($Z*!0Cw zS5AuJ0^()mTwMz|j|Ee%q6dEqqbUZgi&fhg*9q&OsyKzo_d&3xW$5wY_F#R}c{Fj9 z^if*<l=@1ISIfKgT4)=oz#8Jz+FG^c>H{EG-poIVI8jjMQP9re)D2EE>;xp+?VqQM z{gNht>t;De8^>|61cSC`SG<{D*5rK4pSWBziowI3I23f0xxA=qbe)cwOv4kqQA*%R z7=ey}3>z;#G=r_gOgnGlFmxpn506OPoTGji+Xv2Gs>hDqWT{&_be&dw<yeDBH5v<8 z{dk1B5J3%CVw6j_OG;FrpY|%!Yv{rd*R5xNrgwDl(z#dEx{)RIfuh6UTtaxleyrZ8 z%SH{HXIXJH_XR*Tru(UMXWtUmM-Vj-XVcrj+Pa|%hL)m4WePC^Y6f0z(8_A((Fhz> za84aGSghtQ>H26<+&<Of=bk%N9v|_DRfQ?#thylE8b&>~_Jtkbui+Dp<XuZ}bAN$! zW4|f-XqRf9p73ZIl(o53J<v9C{b%s-qK6fiVJ81j5~)DcgL&+838c;2X1DLFN1RdG zgkg%jXq~+)Iwej7vGKICZqI_u%`RhJ7Tl8N<YSi-AP|DIG{2t9`oLwsh%pgm#xF;{ zMV1>DQK7XfV(^}Qxx}TSjoE#Kmx6Yb4c1QPp4ziG!6A7>c9d3mZDhMCZ$I<;mI1uG zPnvp9a|iW$P2C1NoI@y|YE$Py!D>T7B2lLdy5%Ad*7vInexRlYXlN;ilLihfHig`r zfcJ=IJ5@y-j7wEU=WT|b7AW=$R|h?FF<1==*(@oX1lJ*@Q=J@heOo93*se>3lRb*3 zdtWxCP)<=PxTm5S)Y^NEG4vHs$PG0Q--viZKNwj$!&L%7NOK!%1-RjLz?@O>3aXRP z#O8ODT-$jp8!b!|>}((}*X%)$VLB|roqNGL$jhJ|sB(hZY}rM80}qJUEAmO1orV>2 zP-#%eHT-G1pqD)J6l#u>m;XnYHAKnQ2!uw^qpk~k1((u}6rN%0V09`56@56_q{ zo|Z+jeP!)sfoA`()hNaJ){$<C5oU96K?p{Lvr-%zY5YqO(cx8YS->{?F%jACb->|N z4oh`_iiHN>s5|n1x8j@uJb+oew9MnmqQSw8ih{w*o>j;4!vP1-%Bf=qdH8)Cg>6>J z2|H;zprI9s3cW)&P?f{gJx||?s$cXA$l^4*MC{bWDVds_!1+RU#7$^;SZ7GWPBl8g zH5BbR^(XJYvAVZ73Gl<Ye@7FD+yaNXwvy0fWXmj!9?7p)-z)q4?u#QCTJZu-^;T^` z_4lg(pR%oE!u=(8Av((G7%P68v8h@v)T*7g@J%CZd9fyZbrfFK85D8UYA|3g!rfl# zO543isvGSzu^DN8d`qiIY>60Br%lca)yF_amG4>&=~H}3ka{UCz8DgllU<eF=(n|2 zw|P9mfpJ}4`-%FO?6AOnpPS?00B=B$zqUeZ{lYO6T-7PJwAfK_Q_N0D<gtU_j(?~P z%#*H`{5q28*N{bh9ytJ8;_Af7J&a@%FG-T6DkOHKs_E+N4&`nltGz*8rH6J^y<qYe z_vmB`v1!E+tjhssmzvCSjhn$(ON0TviSS?|tzcvj-Y*5-ovrd#Mq7JC|7U;>ec7H~ zs`%VZKBy0JRPT=!Z2x{q8*qwyx>uw^BqvCwBvpi>(sA+3bft~Uz*ZLz8BdE@&$q|K z9EtkZ0>-XkUg;YWB92pZ(oWF^NU~hrW0=lIx@M^MM7L#btIN-IeO8IqXurErcF9xV z|6yKX@yUXEXZt(D{HI*sEP}NW2Z+x>)3AVHV{R;%H(G{jYaz851~$)*42=puW(_pl zu272ANh~9KKt8Ys9bX}3<qOag@I+#)!h-jSl)6S;*)T|&C`+}vF_DA`uS)(?N_U{k z2xN5$j8@_>&^|<x<tiqYIa)0#5jC@t#|Uea?p*SQ+*ws?2JE6~BcV0GkU22jnlT70 z(0Xrt=%&akP&N>WD$*ZgUe247wi5An@E+PKZVdA>uolDO1Il_Z_>7(k1i!tY^hj}j zL)K~vl416Eg128`FSBq|O<0r2oL`zK+RTV`;d9wXFTer|s%(tOUCzAm)tAd6i<ukM zOUK;J?d4e*Lz-UNgePMlE}b}hw-`R%ZQ8R8W7KvIgulbxpYaK}wI>&Lp9DPnYvlx+ zEr-IB<?c&#O^Y95fIX-r@f7N9+x7DCV_)?2)pXR>Wp4Sc$Y*ZGxR6gl;8f}FK#3J# zx78y`oj6{Q21ox(oI#N*t0KCahZA7$1}M9u<Q}VnuN$8>$o$WQ2eJwgH6<)eII8I0 zp-oVjPNFP9nv0gYDHg?M`2^3kbV)TulrSYp+YZ%4gcWZa0uwAocHF@LNd~d~xNKw& zV2ck&S&}XFTI7z4=Dn*{A(adM?A2Outv^^l^HmGGy`@rDy5(<526{~Jo6sVn@R&f; zvJcAcA?@5~%ChvRJg`=BEybgz?;^IamG;kmsxqPyVOwz;EKaTuRVAUBoQtlHG^!}; zmvc`XNQA#PC+Ld88{pnc8qEW8xNpeWY_H*u_a7=mY`dmH)4;tWcFNSs*p76;FCvF_ z+%k@qRGYV!<($b+^l2|K3(wV4mCvyt%g}vEn(Nv0fk>Ynvli<tXytr;jJ>dm+X-El zQrGET(Fbiuto-=eZ&L16wxD_JJAke~bm^y0jTSxX-DeMUx67TqRHy;UvR82LN(P;N zq7+cv_{a}N%_Tp7)tBv=oUD(*T3O5VRS{sKmuOe*%Q5LK!L~oRo_Y$jKhx$B!wV6) z0j7qTU^y_SlCXI~!lc{FjY!gKFq^vF*2jcey8)H4I`wFueR^RJ!&f4*%*^+|vIL*I z&pmA-6(}1Y*3kDJdXLy{?3dF>*^a!<Wt*nhdhZzKKjHdGRiK*}WOuN6^Yq;B_3Ff_ zJG#{<|H3OU-#%TvDR`mmtScdAd8a#N*LcmgMCI)(T?*xcY3T3P+j>fdf<)uwFMMc9 zURb3`Ry=%VsCuuC)J8%m+I4;QiC~l&T7eSNn@<$(cW^1|kEX_LS3+4K-lOB`d7kN9 z;9pB{j%e$H?K8U@zlQ2WKC1IX)vgfmyj}Ob?TEuv&GBSHDKY+>$FielFn~%JvaVm% z_<ctj{Pxk$-9BKk&o+^k&r?rbrkX%HoAu`Q;qb{W!x-4<$Ft+nN(|1*&#O2V6A#@T zwy{d7l21~WW1F7Jt$@Q)`alQ?94_SBK5vkO_6qggd@+*ibKmp^liL@jJK|;TwOQBS z7qJH>i38KTW$T)d4V%07949FdmDQXDfiyn)=Ee|Laf&Mzert-$A=k;8uFl|-32z<6 zzpxmu+(Xck!tPcn&M{b&NQ{T(1li8%Wg_n{H850Pw_|ty)J0dLJgpp9B1B{sFu>}c ztm8s01c<)EEvW0kRlkE=d6ovr((ubKLlg;6le7!#Aix#4u9q6vP!NA0f<X9`dMH$( z4`Rq*oYSCEg72X=wT)X~VOz8URA)2A*ldFlIFOMhVzo+Ih6+(Obt_OjfRlx6=*fSu z%g(Jgg)`N1BxjzY3~Z3y$OY#=-EMEp{=NMGg1UBW@TOVK4$V5-NwgcS{8BHBoVtrr zyRv$2%A9?VFiwCJaxOo*?AHAAge*yJFzN}lnol&4(7FPa5B`(d2%Zx%mvzjhH|jds z2#yKYiEoTo)H)~fISJl|W&XKl<)|TDivvQ*Q3?DHH8-{?pKLIOvBU<FR#JjE3zN)R zNjdWPW2vU(HUVeB@G4`0!|3agWoib1DsJzN2|tN4M1v%qg3rSvVLSEvH1?b;_LBC( zDIH6B4kaxi>~c{RUcD$KeS$sNhj^O&ftyD9n3q)hAkT9(4mZ#2BElf?$UlXv)NxQ2 zwEi4$t!_DAx7U@NU8;T>;XPCFY`i=>Kk-DjwS8&-7cpgm=f2A@f5!FAD$sBANMzj* zDJkCq;?gIPVfu8L2slTpDjxHOY7g0Y1-DQG@E<t0s}2_QhOCC_(Cui8t0zw<sgaY@ zSFwcjC_;|p3ki-bpu^cjG(<BVA|d2wzKus@SmD;ri$>Q;J2_3iq{Wh3nea8j75Lyy zWXfC=kX&wM-aA{Fi%^P}gIsG+#!wrjE8)414Ux6zXrS;h<s2EP+CL{BivF|y#&wIo zJTcPF-XCU`oqjSHo&<*5(Gh_r-}zXZm7i9&<-iZ0ta0iS4*_j?TOw3NT55B|<P#h? zs*#Dz9zI^^;GG!h?BnY({8{Chm-Q<H8&w>-ZB0J5mN9H*Uf{6I;B|+pEruVXZN`%0 z;!xG@b0=qn=p8@IhzwMJ|K)&WjgSiiksr4R*!F{^X005JM<l_?xE!_A*FR^bmq)rJ z3bz%E&;MAmjc%-b&Rq=9&e^m5qn)qza}G=*7&s=aL2>j)nS4%-wpsrDY`)65>k_+& zvqFrpwb&;Dm4bB;E6Uw5b-F}Ek-fFIE2pc)thTv$I{58}*uZLcjjm|^u`2@Bwd-aL z(NR3rh~npjT=Ab1D>KYT1ZfG5)KraLwf+<hOq*Q!4pggM#ZziX!x0!oR2*_m`CFJz zw^t<0O3PkwB938Cyo(U9rJTB=gd)%;meuTxUI4NP$zv>^&eeoi5FRnK@~kZgu20r) z!+30AZ89jjx=cahd-wuydBj`_ea@v|^8pr%orRAIWoFIc<YtuEfFf~PNR6#EqD3Kv zvgITQ>EbgDQkPOP4jtB(&LqsGoGHg2r2oh~@X!SpRWMB2+P%a~$RE%6u~Jx(8AO6v zyZitnqcMLFKoIe_#4ZJ;W+zEhEe0|;0DO&s1lmQJS*rpEotl}V=<`{^cT|Csb%>hC zT*d$MEmS@qJb7@BJYe-fe^wJNY8akpF&$f66Z-u(_nG&t(Ux5c$))Lz8K85Mq%a;X zFH@7rJ!a3!J#;>QQCCQ{+J&kOg&{n~OnW0>jcj}(%DOrJcpeY4yf#h?G3HqyZ(sMq z{r-YVG32BOsk8a{I*hKs)f97!Sp~^MTRjrAvJQW9Y|%5Qc2oYa72aEpl5$L_GYF|4 z&Q4~SMYv@?3z-tp@5wx+3>$l!Wz&k0Ei)}kZHK;vXc2f8ln*zBzVYFphEO#x&@TQE z*_tl$o$Kcsz$$E7NN+PyY){HEm_LrHMOg^7S25sX)gl5Ex=zKRzc!ekyvFr8q61be zF}r}`z#kJyxuPX%IK}}}W79a7TTTn`H1kgWR`b%(%87&dp}(rQuA@!kWmA@dK93z^ z`s>wg$pa6Ga<7qikO6s(d-F=<7J#7r2b|?<YI1eD_Bm?VqYuN^*HUas?QwYMtMv}e zL<Sf7&en~hVeD<LG?Z#-1C#7s3>A0+U1^L9yO6@szjbuec}2pWd3&mlm}u>YM3?E$ zQ5%?Ts4^KI7Hf{jZLCH^$ah{q=&``gi^|N|$cUju{?fc=>1HwKM0j`&a?%CB*1*XS zYHAWsOPf7KU$cH?QQLkM&Ig~L?$sMSfQigKiFCWjg<r>4r5{E@-RTG6@r=UGw*vy* zB_2ZzQ^vK#(vOludpm?{d1RO_6?)R5YO9-6ir3zvhE?dDM8nOHtJQ%8*{6f-=7EDy zK=8&)OK6xC`Cb?H-KHr0XmUq!U4e$2K*~-3<2$d|^7V7gZfDeGxHZpvah^&lyHMSm zYioIW4p;+Rj5E-#<+%tJloyT~vMh+IMiH<gLaOZ5RY=jVXXGqVce5gwE454+L)ma` zd2-0?kW^H*r{<mx6M6vo^(pN33%Xi%=nL63g%*rDN>whXYY@Rj(>Hk=2??17;Ic6i zkGLO+#@p7Af*esv;;UJD(?JJZ6;hM3801C25}WPDPK&zgl!4u;OxK5Vl-@=8^^dha zniLM=Pn>XuN!(P=?rV)qoBrzeRW|n{bFQ>hyiXJa>t5=SN5W+^Drw<ABtJ(Mq~wn1 zG2y68C-Suc0PL%5W%1DvTZ@a;#R?@<d#FImTvj-fl(ct1MG@Ur)_2^5Z?R45$uynI z_4C-4pnV)=8D5s8W~Z~>&nmSDb}0`zAB^hdR<HtoV@<F%=A2c;$D+do`p9>U7r-qt z^mDn+{1L8jd2feR8WCRI@L+njNF-sc!l<sDnl4@3liu5L+xl&3E%9ShL^}%p6U5(g z{cl*-KXH9O2l&R<4#9@XLVmgN@cs)1V`uiq?+czGqv$3<8xlqARlO+jU-j-9pmaMz zOKBLAcixzYd+C&>pAtFN7DU8$=n^5a5d$cefpr-egIhZ#Ti19%UfVLQ<<We+gKJc( z`qsN*yZrbA2$@(7gmv}AZuF5}Pixq0iNM#Uh{3t^JUXTFC}J+Q9Tm57NqF*hO-SSO z_vv7LfJ2)S3UkRXHRe!-cyLt&4w-_yC_GFo(aU3rHC0WtCL*5{q&azv%Z9nj9Aotp z%B6rUx+*ZQ@P!X%0<T!_$ROPqw3!Pj?d2t*B~Q&CKQ&zhUe?8Mt$JhWVVyigKx$D3 zd=*gf9rnP*ChI5zDq@s3`?9N2)zc?nTe5Q6##1hB5^6K`Tu}M0uj%Fxy=tEb_>X=_ z`q@r&YHaMS<@M6_zuA3RnW_86pjqEY865*q+hhsfRb{0VM_GRtH0!4T03ZNKL_t*f zAJVp}IXe>;e@HY)IaqgRp2l5%D>&V~TJ@N<;h74BuGa569=ApN-B-rYRMS;&Iultp z{AwVs$nrupJhSitZt0!)qmUa-V7ED*?A=A*_3UL<34UOhtI1k(qaZ79OiA=<<H^8R zD9n3}XacUabZ$Rx+>6BaQ@mZODPjz2<0VH01JAcB06X#oRlsMU?oNa*h!arCxnvlJ z!4n)6(ISL`pw?H~<hxBVdYW=PYN)8)I4Z}amT0LTC0I+PO*2xf$Z}H{$ep&Dna2r+ z?1P0p(Cb>ATa&~r3Yc(QBjvj{gN^7jy7?Ge)<Cgk;7&}4u!%0j8!@}l=xv5bkbru< zeb+7yFnq*vC@2%qq>cIK!Xn=r!=RTWxHU~pBEg5TUOV_>v|aA%7LU=n8OJe+Dxo3| z$(Up`RxFH{8E36(v2d7>Wa+SdH}j3XD8P{vttZ9E?f6xJ#=KT5+uCK|l#;OQ#-Q+( z$`_s)Nh|c)H?CO+Q8Y7ATkC|9?ZKWRac7O5?FTAS#YY^Ze3e91kTOiuumc!}0qSa$ z;e}YP^eecU06W@uQz>n`ntS88@?bg>YFaR0`oS!IiVgfz3}BK4n7C6j+bRuAQO>B8 zOP{pl8gDDnmjqX$A%d%EmQ-c5hry})o?C+R)<!EDkFZ5I<XSn;UcH+B;B6Y<$4$Kk zvsfuWLta`+O2jbpVITVn=-^c0gXr>APiUA|{0jWk4SnlWvoCzoqJP+Dk@aS__u?p` zoDK_04bL<}D>p%*f(N$VyUpWrZgu?_=A~K1eRn+CQHw~pQ3592O}v9yJ8HAEH*1GH z3$?xsa*LsWTsk7nbT@OF8GCne=nDJ8S7g~qLZP&W-Qc%FYL*d=TptZ3cmrvLnT_#` zkrkv7(0#@-fS0@7vz)b1_%s_HuCezXg%EacwwkEs18UgVAxEq!cVAHB7mD8OS61xU z>NK3rf<aw*Q;bDt;zn$(H5(c>S3anDTYVc`+efgkSJte8eFbKQL`@G(wB`;QIJ}aw za-i$0o%57{teOK&oJc^MMkB<ZD_ZzAmxjL({TK&F+OJV>V<_NkfTSA3KJiwelwU~* z<=C<;>PfstXSO<WR9qLDb~^i*Q_zN_mS<{F=O(kB*dGb}^4jVE9Zxqj$ASb(3aPa1 zj49z3D9}#JS-Vy3ZQ>k!4V{x7eKY1gWa4;c!JU@s;xNd!s$dDm3wLPwxyuzl4L#l4 zjis$BIDhZCsCNNW{3gLcOPa&b&6Be>lQ`0C=}c;cr5K%Jgl7{*H(B;t$_Sl^EHNJM z5;0>03A=gL7w{SjHEb5yaw<qn^q8%@;uhNV!@WY6#C~`&DyJB7j@OG|^!KIKpIHVf zL;H%!iC^oKl|xcF5`aKtd%wht%{=0Ka%iG&BU+)ZkiZ?;>Ooz^1w`8vsUyP-<mv^I z!$87X6`7AI*2}tYdgaq9eei*bbrO`UNg}RA^!BQ!;SjlmG|$dWN!1Hl;;e71ldc;6 zMYkg%U~y7cHbw!s2~%^fFnb95O4Aef$9bvTX&I`)iaChuNOgf>uIaM$k`VpNhsTU* zF(s8lUK;eorT=}o1xn$O!y+r-5O&?bOSi(Rw$Kxcin^2!SDP4;u4n8=q2_%20;>-_ ztnDS41LblCs8!6c?&T?s@G7>n{Kwe8RIPi-)vBOgGPTq2Pq2P}iUCX@R=6tx(X^m= zSa&27hw|6^h-eu)GkFd#B~WInz?rv_l9ZuC>br`K%fXStaZnfW1pQW3-tsa!ETSkz z8F)%KnD0GhIwY#OKJ<x_fSIS7O&RmGUb_Ya<1!fM45xy=VX^9e&_9Me7iIAPv4)CC zV=NeaxUOA@<Qqr>D=C6fSDJ6b#|-h^Vou4WhGmhbdAySWWabm%KRJvK_vzl8FTm*S z>7$$aC-fjiGPBZ2BLlBjZf;AvJ$ATPed+QOReJCQkkIli6%8g?hS<+<8zi9pbzz&K zj|}&454X=TvfRZOHb&yZ)9E0P)|yMKqR-jZZe^%pO{#P9Qhj|*gz0(hflSn4Ay9h0 z+B>&7$zj2fq(`^#6zaE<hDz2Y&Snky?#}4Hn{{fu$mv}F$k^1zmyfrKp1Q!`X&g$R zMnbG}`EG)ZHi04M6Jvt73(pKa#@P&uQIU{pu3BVu!qi{(wWv53-o*hhlQUahh<N~Q zGTeOP?6}1jwZW{7XN~x5MBx+UL`All#}YGHIa;%Qzwhrd{s%BJ>(<S4Bwn!JGm$F% z^M}CCe5cx4v3;8%`Z_PCOxe5%g?#~^Kaoe5Ib8JF_6q%Q9K1+HUKPYDoK)bn#*8Yu z4(V`zi;jv@kK@Mk_g_RFHg~5T{|qSORAx?Xq$;AVR1oN9TGhNm4<cMOpB<Or-r=H{ zo&d1FnoIP5%3Nr^o=6f)uV6IO#&3`M!tnS#mF+Yc;i`7m8^t}{U01wuMK@c$-I;MP zVQ~kj!)sCN(~W@CV<<rDHp+Kuc+G-|Ki#*ru_P+ALzd*?t&`9Aip{;E_clLQzw!L> zo1lHOw3)aLmAj4be6q%DDWLUo`L=PbcBA+1x?8mTyc~|#eynbPz*xOJjOX1iuTD?d z>%C$haj9*=rQYP)zI0VL8-0v!)g{l<vC)+x518$84h9%Wp{{pKFDDz?s=C2d-jv!^ zg1la*<obi6^G{vhuL9jSpsFU&N@2HmuH(p(GmXas7uTiQn>AQJ7@ahyC!XQee>Q=D zeK->L&4qAC1&+svan+!Z#;ey%U!KQQ^@b@XYG1YLDl)|7=JXCkftLizmEFlcEX_YU z9SrXn5o@wP`s9|6Z&e(gwBJ}<B*JZu@R>zB$*`6JU9}3l4L+Z~)^j~d!)Q}Jc?mKo z*%Q>_e7M&pNK9kvy1eYbU_L9$8&m;LIK8Y>0{y#fBDMQ8#wzWeHQ5b@SCT=)3MTHS znkyWFV7RA!i%lnj0KTr~Bh(ta-pN3ZNhx;jC2QS1tBbk0Kc0G6_z1*vKinVlY4$=b z1Ja+neXe|Su8sTZVLP&;5o%Ys10uL!mf5fJHAVu91o+4D6)&sy>lx_j^?uGP<a8)j zUqd&l>{20U)YYy+Ur&&NHYnO|RF8@D>oRm33hi>CW7}S;+7HOjDQTFiqb~esEv$Q1 zv*?M?_1hke2i~i2q*?=m6XEKq9?yZLzE#1DT0E+M-jB&9EW0mK;}wL2$jXYi70Yc* ziy@Lb;AHVm12vK4?RD6`==89J#fVtVDu=9<>J}wp<fZSas~#UxRq=OTar~ic)Thu; zVd1rp=QGu=*c7i4&CR2~m{aKa!h4J{#`V$c)`E`lGVwx^)0GU_!0zYw6);%=cTsS4 z(c~oLTU>ey9)`hhg3i?Kc(s4G$#n|T--%-+JFui%R!eAOj*iq<0I)`9MB5Va=<Ohs zjvRc|Z+5+8TRNFe15sb8i#~r3d2_BZ*?Vk(dOf-Nv~zanOUcTP?y}a7Npv7a7@-XU zN{{~i@3^vJq?uQ`L62Fr!Bj=J<BIr__WF#rAplE{<?5K^cQ^9MWaB24X{4S&C3Aw= z26r>I_iglJ8ydM_*p~@PH^?NAPPD||0@nv{EHt8Hnl)@csHi%er!stBoVSz!B&J>7 zYxdP{7X6=AsKpvjWUm&aaIYC4tjzg3YcaCcpgd8)!{}GUz(cPeumh}WmK@twn_xva zy8gf2cth<Kq`Wrse3y{irApMB1{2@9zG(o{CM@!D`3lC&6II7gzlxm_5IHge6}&x= z=fi9%)4YF~k&#Tvr6hq@5oY|@V@H1Ni!S5g`y3r>nOHdGO9++bpam}1A+s$Ckw<0M zUy{``Xc-t_!0bCB9a6l%h3yFoe^_Dn5S@Fq67^NCwr8t92sy%@40B)A2v@ANngKR( zn5}=A8&I5==nL{|VW2s~wc~PtTS7CU?#6SHzelY5Ay-TrW<~q`9SfsL(2{1$2cJS^ z(ylXKXc?=jFfPV(g!#<m$r|KlS_g_wgf*HXiLI_V4AXH_Cgf}`px7Q#2P-R6t-eIF z!uw+kXL)B7uQH2xmLJy_4kPRD*$Nb`en;YnSm=U*q}|nw<B=>C)bvWLnN4U|dI9nC z4xKHpuONW?@r$aN#AljNlnM1#SsHaG*QOjYrwl(Jn{z%@yN+OB2QgTfeSi$|TrD+K zHhcpLQezlMftnTB$Wu1Rpal0$WV_OplG*yfYw;rK4ocgMQ3U}1E{i-R0OehgNoYO_ zftTvzbxevY?>P%z#J{RLqGkc;TNWBzb1qjAN8#ojNi0ohEcM`G7xb*<XK2Y7l%5SU zk59tKD}UMIBuys+Lw&(9@h$@Fed74^ciO=IDvfB{skEjCR!$d&HXb(8I|atDqWiw0 znHjw`$KHJZYW$Fp9MHtOX0M?KX~%_!Nc|Lb5(iz_x5omebk6{k0jqqRz-({s9*v&W z>Kz-kIwT3(=#vzu7>SmPUyh!`{Bes>2^Q94P??Au5{g-GpW$kqMtLer#oY4FbhI@2 z0;;@fvV$$txNBTP9@>MLqqR1<8##TBME?c0l+!V7wfJTtl)UflJIR?m&e6Na8rTaq zMb;<Ty6ev@OPc1e;m{^}McQgifT1`%eS41Q#v#;G2~1c`1=-PF>mgSQH6O+*t-+>y zmChV`<hgDhp(@#SO}b6{z1DZ+y7*sgipe0O&xI;M{-zY#jmNDto#5|>xb3bqRCS1s zYn(1C45nGs%7m4W?u+0o&f)!+X(`da3G)`kw2O1l=neUA1%V=LjIkYgeb<ij+R~fx z6oH^Set8;G$B9`ku&PMc^|YX_)i^EZat70X%JuCCFx1VmQ<2x<{z5-MPn*O;n$(@S zWD0C%fpz+VSioIMG8%q~j`N|U=`E9XBhBvoI5F_R<(r$mI3#en>{XR;J64KwZ33~% z=*zs!a)jxde$1wg+1^;?_^EAhg|lL?m4UkEGLTFnfb-;K4k<A*4jHsLeV9$3X0L2E z0H0<+k@YNLr78srIIk6$?lu!-9wH{WDJI@`%Y0J90nn3}N1s69>cP;y57=61qi!(H zx%|6s+VBku)52zi1B1XaC#iD-Xxf`Sln??d(NmoT*tR^k=FTX04}=_s0r0aW2sxnB z)G<-yQRX*49*?=356{)eYE{F{{I%RWhWNhM|37Arn=hW|?ml2e$C_1mvoEBe*Gf1Z z#nWm0g{{`g?ntb{$zrs2lH$|BRnXaC=HV}wsfvBVEW~if(MFF7*>|3uvQ<tra!(uz zIVt%;C9*PiF7f<X#G;&BI1qx&Le4-SJXjfDfF3MJHYp(?0q!x-BLQs{Y*buYSXL8? zRGmrZiAnPWx*D-cZZR@<I4Ays1&e1hGc8;+31mN(pJ<WgK;0>Ay>L|CLi~yg9-Eef zJbrQ1F&nvJylx{LXq43|k2|Ohz?{HZCSH1NRZGziVGgS{zSadBICAr1@i-aRRr|rj zkCt-3GiOQkl@pb>1kh+iD7Q+iyA7$Tvnr&su33A!->y_dP(T)=O35hiYHE;A2OLgH zr9v}Xb+h_NpxLQc_FRNPesx_x(F(|gkm*zOS-z4q#sbcx3sUq1QP(un<@be2K*Put zLMwB*#h`KtVpc=%)MwPM5&}4yU_L~^T}B%j{Ja{DC`VjM_8XJwT>E`D&l{=KIpzft z3SFqhyqL;f)jGC`n1!S;A19&JhS-PeZ;na+-3k;nR}m%&B_y2b1Q9IxCVgcC(!BcC z_{FO7x71~%uHu<`=e*pq-&hU}{rX~}sHRjHa`-!zKFA|4J_32@w2-xx9SD=Ie*0hy zYFPWA9@}@bWD!sxQlQII8FPgjSTg)zwwjklVNm1loAQniKkulk*O23mC&L;I8rJob zJa;1p6W$KBfq|D+j2xe)Ni(~OHgG$+n;5DVEf*(%#$)jF=6ZN%%&*#7WYpBST%haP ziVOg{B{!R%X5Hle`6lo;+aO^fibHK;BRf@uBfkWzvC|tKg|k}l<K*wya!*gE93)YE z`8-oYr3p5EaJpoGL)|?bid__Ptm#YIv(xrNf4|ZW>qfU#>1r`qQ5oF?14fO6ie2zy z>Hx_0bTEqy9j~hTc+t{X@%pHc9if%(!&9WA`CH+TmvK8BLEuWBD0^nM!x(N})oU#f zzSNC72&!{x!U4F0_&>HWJk@Sxx}vD`7lEzo?_4cg;ziG7Kktu`1I}Og`3suUTLK=- zhZ-zHZ74T@Mh@)oaC>}tB|I!viZ#nM1H9@Z>`BLSnq9+uot-gge5VW<3~pzbH?SMW zp;@;|ZRG;+M^?F55h|MO@Qxc*!GT2@(d2=y@a$wjd5bEzVwlPvh{?AR!}a3%<!Q<T zRYY5uJ+b<^6v5zin&s3gI^U-=YdIP+>lk{WR4?bff`^COt6eq6t>ADOA~mIQEJ`=m zSx}4S4RpBq*DtZTWpZf2y!=1-;4aCf1b$Gr-X<biBxmN$H=m0-X`M>wPz;ZXz(iCh zPJP`bo}w70iQlk{=QwWHfo|7@7yPLrSesJ2Jz<n=LV>0lKyk2xB}EU;w^yu>RaYf5 z)KXi>UUBn<83~qbtfP)2v>s9ql~8gRa3nIADc~-e_cx_X;>vwGa#U*~Dh)MFO%7(J zuS0EB^{YiDb;WcINB?jmJL#e)r`oJnFzOS*I)#uN=siZUy&9glfK}g(bHMG8ZjEUe zoas&of?o>%f1q8xn1nTjTL+*L(u_r(1E)AZY}>MLx*VBjJuSA!*D2r&6q;COkL?$0 zt+ZSA!^lSkWugu^X_!cq3ZtPwk=G71g6o@gH8ZwVe4~QYjTai0Qqr=S)eM}YjCxBp zTkegiy%$bDqJ_dOy=&t-qkRj`xxmGlh)eX8(TAwq*(wOiWL@30+exwhz&C{hLWyC6 z2=xW->))fhfx-0Uh^j^jkxeaSTOqb+qDM)v;&><InhMP5YcE|+U8I03aW-K}2#?EC zw#g$+TEe!3_trB)>I9>ecW80xHqdvG`fpy}ivS1lz*|9i>PEy%_@+Xcu_C{GW>^km z>1~1Y1&t!s$KP($tE*y{^;@?v%H&cfvnq)@3C;wRi}9?891cT3f${`WvQ$!N0m*c5 zx<CATl_yd6^Rd~kkMHoL620yNwKvKf6-8IOl>lBFYb2h@qT=~8uhMvF7!)abT5E33 z-lVGzkh3|bLuTvZi!3=(7i2mk&Ae2gm!hoQ4w!<k8$2@9R?Dt0l~&y~3<j5IkW8r; z3NrAkyfl!(!K2E6F#sl4fOHZI1b0RNWv4*X)sg5K<3YkLwm)ktuZ|#$?k2q1$73Fh z$_|IdAf*~s6Z1+<>{QpS%I2~~MIzTu!nKmF`L}8?z)tq%m7Sn17=h(CIVxoE!`zpU zCtoj@z+?MOLDmgoGEV_OL4k7`FLT2Wj#ST})F)_q;JmX(OUE0N`wPjXV_WN4<q;Ms z6of*Y6NRS2^WK(4UB8P7%S5uEtLNwBP83#N8UVmDhjNpq`*h#J2z@(vta2pPMLA1k z)*YYeUu(H+<hL&jl7~?vOErGP8_6QpyQf%>9dyH03Iz>CPuav;n9_V(j#}P(Fz`=Y zvgWR(eB=m-Tw4;hcnC3~+&;zBn7~_t#Ix~6m=GPmm%)ls2fcaAJS?WWGwq}Jv&Vv` z;FEo_<@r@}Mg?3|mPQfpgmD(96XMT_5E~_R$Vc0<B$@KDx}&FvYvR>qYt&>a{dFb7 zZq^EvpsGsEI*yQtW>&1pN*Cv9i;0MB3L=L+S*#I2N6!xY4x8mrTA7=s3)XCD32ebD zkXe~wlIdE6p*|*EL_`jn<BVtlXdFsioXhTOJ09Nj?)6(uXH^}wXLg|7MXwc-AK?jv zy*!m(VJnf%#2!*r7N)Xk9Y;KEvT*4}VCU4fHN079`^JUB>8VDBNBGh@f(cM&%dk<e zjSQpNb$|=iM3&r@eBFJN@~A@_2g~&BBY0R5(>3ads{)B5u`v%m^Pq&GsfEeE1q&Id zFQx2pvlG>}k2XRplQkHx)48t<=WK>-oD&AtT+hQ7lFrmL-KrrjS|Kb;J$F2DOt=fe ztgtEDk>AJ+^Wt_;|F1c!_?W^}MR4HAs~{))(iErK9V&q}qB@(fn}5Cu{7ne-weJEh z2XwH64Of03QFEsjF*rqgv(lv^kLZwFzs84erA_oA6zY+*lhMh-y^yZmGiqAp*ezy= zDh>K5x|F=oH6+-LMxLm{J2$(OGjBGqltc;{PsPbgJry$m9t)@6=&?fNV&shvxYZJ* z!Rc;3pVFK%Wp4#>y!d{*4p8y>)C&Xb5#?Sn+Nk>LuI3i&VZEhmD-qoqZzgx4AGfAB zV4NClQ7@f2!uVq4LulG6N1Pu`b05RwwNMdjrv`dDDMxtBr~BjM1DqZeV%GAm7RvB! zxVa~sIs48dGTh4fBGRj#Y0hgPq<J2t2D!l)f>x|(EwdR^^#GY2f>BW?B1BG8jmCFN zTlMMm5D6;tGE$>|_jUP!PxFX)vM{_2Z=C~IbIyquY_rgRLC`XHH#mzSWX2z>{a}o8 zc|u7ms1ZD~K`FSB6t;>rK*Yqes+5yQ)m-x6+_HZW$%j0fhY_3DgfLYL4D5zVURI9> za^TeDKwY;z!=f$a>6e1d2b&uc=Q%N#4vI@h3JF6Set^q0TxCtfoMwFKIarYkWO<Qd zZ&<Zy;dkq|`zyb`{PrjP;#&iWiuJShCf-GpkX{l6ep46k6yCxG(iy>EG18Gy89JKn zvgmDQS%j8R4C6HaoTWS0O5bg*O6^%AjF;GrUilO&c_)WIWmXTEyE1Jh@`Vzw+$9+d zr`e9L{IMw&y#$W%y(qr*!dD7yV-*7FEnhEsaZ|EGl(WT-tc=5oOY8TEJWX@qqOn#6 z2@V<R8l>m{G&=W9Aj)cZDkQT)7ZnaU3yi78uPVyM+)UPiC4W||W%l2n*A|r9tjBY| zdc9(&iQ=du@bo9FKVBp}Pn+4?J?5@tB2dgv24=DT?}HZJjvd>Lscl9_h5R-JD7~6L z0^-L^X5Hp11Y$jXgF(o1`!ov)y<HlS%(^4?lhQ~n>{Pe*bx5#Al`2?L03}Ougn1_f z#4tU8r1o4rC;LKej<sB|jb~#}JKd2F1j0xg$w{@HT-(`s-7s@cAfBvVTPhj|4LFm> zEXcJ+S-&2zx{K3_C*VlrDK``?@Y<#Nby*P1I*cX=LibheK7u#-RO;<V@t{ygT3Dsi z{^aYYRDo7TY4|((-+tUOI_aDbK5U+*P=0|%(+k4jmT7a`eu7l>&-0Dvc-~z5NH=Te zT)^{1STr~DAKf-(@Qp$@199FYfuPPLrJ}uJ1wdADg%FnK1ZqOp42P!mu4k`-xSNgz z=28x%zEJ1#p6dJT)V2NI5Zz)xa{DoL^n-W=_;;Xi&r8JfVad0N$ape1{%~<DEXz|F z+?fc>hWm%vM^+a@(Qk&K;&~Es%;;j;(e5#_3l0Qfbf3;Kmr=WSnQQ6<!%@)gdS+b@ zdtW+rP+X{857(O`zhfrfX$Bg<x=qA@u`EBd?+@U3&S$h}=dhbI`whnvT>yfZNd#|Z z#JQhXbbZlvaW+l;*pc?bO|0s5BEeK-CVcw0jJvmA!#yoVsbv&G{3DfPBDABDRVQM7 zruf@KJj(nQcA%fU{R_!*C1Bq5Przz5tzsL7mLQ2L8A8HdVF_caHucGBKzN(Q?w#xx zz^kSeq?E|Dct?L~d9R8-!JJ0_DSxg8p$M!H^&NP>zRAvs?9qIki%}&lStB)UuS-N^ zO8YkUSN8=-57o$nZvtck#QcUM)irq?FWM#&eP1*fe%lVSw`wIf<z$jgqutzF8^?G@ zU0*CLZ=X`|tXbo4@A^s~{Q6X)03k7e`o`GeB086{DUK5Tl*_~}%>}@Uh?rq+V~keC z=t4j5#N4}YRRVI@;w3p)33R=586U8hty~UO&6!aMW@YSS`9ctL__ykpqKZUDXxD>= zoHYEu1{vE19pS=#Z70iZfK|@lqREW~=~W6a9g+RpMV|xi8@`tY<=(Xk7fa7vhlGYn z#x~}^c}#56$$3fc=l;qgR7?ccAT-^~EatoAyRPj)@IMegP`K8n9{kMfn+C87iQ97f zohxN0mC)h`$D#*!m-Qht)J6pPabp9th>Smz12=;(n!TsPC>09u-o9sHM40RfXa!gG zy@fNSH>loQ<_%vRKt(!~P1hs{MxvkzbS19~F9%OiofYf_A*gh@i}!j|#fd?8RzYCv z9Ybv`L?mldsuwwn({dTZLc#*rABO!;ncuRygyU#6*PRjQa_j{FTh*fa8B9*E5`w<M zOz=ts!gooZ$gNe+H$a;%7hd-O(pjzE0BC-yI&^k-;*AzV^U}H4UK7RJk47x}G4VuA z=c4UUPiKdoK#7b_Jn2(jj(<h+D}iBECECF7#R0~y(NnKF`-vgWCG-XwNR<+_z2C&j z>OnF)23%ozrD#9p{9YNtiAT~4dt|<y(Kuv_EQLeKm~!CcHxW@?J>IBFV19Iua~;qP z?kX>bd&ffR;!v?hx~70Bz$cShN+I)YhCCzb8c8L<Q?KshaW)@vJ9HhXf!sfDq~*Go zZ8;_BR5rWi7FHamtmRFbeC3n<okg(v<;NfWYYK~LHYU3+fms$Z&GQJ4<fdW$RPKY7 z|N3nhxYvJJBtWAZ3|EeA7>_oOG0_<-;pLd6Vg*$uaH!MJD}?urB;L8IVcgtEOaz#o z2$azpnY1HwyRm{fG7$j*Dr<pe>=40&<d@YeoNoUB03ZNKL_t(EODi~Q0*7e*?Ym;v z!SRF@o9EhIjV0C4;`mCw_1lfP7chW@wcOW@$L$M!Hdu!7AD9D~=R3`wUvg8<Z*kYf z$<A*_nBPQLSj<|?b^*aoEN(kEqc+8d=>kDFCaY^K;(it|W)SWEMf1;6!Pv?&g(gH% z+XfM?x-i@76;RPvi8V*wLEp-aA%dwcKk4RB`-1l945C)K9If-f@W0`!duHWj^}>EY zD0*`q0gZ9oCG$Ja0=_LxS4ByxcI%hJ3T42#`&n<f^WmG9Dq&nN<Ok&#WR!1?{6#-e z{rS@2uVWs&=i+SwluV@7=DLHdK8swZVA`ydE`Ia$?_A$AfP3qO{feu<Bsmm$`KF%+ zZ|u6#`V!ubcP|y?EW7dytNN(4fx%n~LZ(01tj6dQ>E+eGX5}W()^35MV7}j@rLH3J zjkdr)BZ<WU`U*8>=BiNgemDb1<i08V$I&HfOC)Fy=oR$NCs(Ke?gNC^O0!wr&%C0G z`$P_NqEt}dn4mZ2a_SL{y7rC^yYdJ9%N?bsn$(bAWx+5>P+SM3Szm_%oJ)kzt?Q_K z)SBnL!z;-|!DDJL_(cgg3}E5a_Of`q)OS52YhV+oE#grttqQ#&qPlu)c3L6C{Efg$ zes}DZPUNObRiH~j+E$d|C~qrjvA{Kp8+UyBYA5ba&y!O78?wYuhKbEtS1)9>H6Rg- zCE<whwj_F`Vxfx9%m;kQ51aFTySB99ZB{Mnc;Nr_m~5L0pV!i;oZ6=*zwyb#=s-jT z$Sa9ddS2L8qSmXy@@)}f6kT6o<agM={y6%S`3Kk5AtvUjI(_R3lfx(?vrGvT@113? zC3VTYD|td;u1%Y-^2DN(rC<N-_5`nA_Fz8)7k);6>)xKCkJ9(OZmmEb#5=Tcu+4oL zd?uxWxx3AXnKfwQsbf@grA@ZdOpf%8^J+I<Kj;7L(VI*ksFNiMWqS}A;>JYQYPC&) zCpQs>UYz!32VO2x*BSG_Ys34Eu`1utBfPE1X0>X@)`4UW9S<KQnCFTg^jnuiWDV!d zh>Q2rlpDpBK<T`G)7V|JZCoAP2k#0NJPf3nl+PC)tM)()mAJ)oB33lBS5Yx>I9l$- z#*un0a#!zPhVM@5Vkehu5kO#>eR-{tB?utza|vvU-|hT9{!qx(MjpqqGhaqNmSdts zqWKOwxO%_5ijJN*X%Cx{#ieya1DR{v$$(e(3p-+KZP<sWXKKqFZcefDP?AX6#9Qdf z?6N7!xI$IXZDhrqp(W}F&m-TMa-4vR8&cq>T;GfUe_2re3#Ei$`qM)bs4-h6iavEq z<vmwL3_=H--8GM#^4swPW(=N2!f#AOl-g@j%3ExqADm16!EByDC4i99ff~(bqZ;iQ z@ZR=oU3||=t%P$T^_#=S)i<8t&q13u0~D(3*Kgbbt%-D7HmjwxoUO3dX6(IP0b?aE zKP;QR0{FEUp9=)O8tn$RfLY?1cGYaKWfl(_yBUq~iaL7O<LzBcbX8pIGUtXP(%a_g zr7V%%!Jy^fw@smNU8}s|{iLeFN~K8$w&^k1<f@2=3+chcyBJic>U<P+Hs$Q6U5%fH z6m4?Y>RSQoQm6;O<kPV>2S?sZp!GMt?^;o%Ai4<5DZg?G-4bgRh8)hg;At8qW=dZi zFj1l>)oiQ&TMZk&n8+90yHz9Gv>?ZEUGano58Xf+vsPxwi#ac9e1S-=Su^hplP|cp zRY4Ftk9-_a6eUaU2m>kUr!v#xJxV{Ls;B<Bt7_yhx=Bl^YvHctg}m9eq0S(J2ypwZ zEQX(`p<8*56Q3C-(Y$@qO=PrBDi(K^-1Dpmts5w@Ppkt=2RDy~3)#T#50o??7MfY6 zg3HxsaF`tGyV(>z-=5g#GHjXO$FiW~cWW`CuiU>}Uh!_W)Z)}9ntRjh-PCjV3M(S1 z6#5(K28w#>aK$Xq+BJ$uHL`7erzv&mj_s?YUjVDJF|$Ut!s-uwp*^roQy$}6S?qlk zTqme{W}u2k?;X`csj+-4-Sb&oL`Pc1*tP;lZ7xRuR`*Z45T8?NOrT1MRz?0k>^eCe zc+tmw+9+IGc_A9Yq{k#sHb(iIp0e5y=)`BK3yxFMIu@cxmZX`aZljlY)#Y7B=aRQ* z>G$_IV?<`v_OjP=^%6rm$BG6Sb=>=P8Kk;j)ucS|k_GuWZ`>Zp-E!a(-e?Y%^=70S z$o8o1!{9OyfG3mN#uI4+N7q_+G4*q<Z$^McdhPt^%=1(|4~7WCfRy4Tas*jKg|b>% zj=qN~9lL}=J#Kv8>y_mnM0hehcoEE(iR`8<m0E`ht|M&X&NHK7M40R8Jd>Y`HbUvh zYiv?l)3<`U>Zu#ic1``9tlwC`P#Jq~yDGfZLyJ<L^<a^m?@`>GW`OrIoS3z_0!L6C zyhd7=R;w!d!I)+j<?1|R*+ANU8#C3#2m0A%oh>Tzm@5})9otyt#1W32=HWKscF3xU z><6`!8eb_cqev9?uLsv>kAAG5pxgp$DZ8k-dC#cvQ-KSs{dLx`N}z<dw~$syB<aV< z^-)NvvaroN$P#~Ltm|Xn9usqkL?J~^EFqWo6%*eQUKPxr8~~{RHLrGM93%L6eOGk} z-eT6*l5h27l>aWsgHE<kC#3h#eZ(PeIzQ+Sdtv+Ka@fwf1jP7u>t@v9mpZ8iqunPP z5kO(|_e$qsaj&fJs&bgrpwx?bry*()sLKgvQ+<KQN5+P6qX^L1J?Nx|b_hhd$<u`T zQ=qL-9{b0x2ydr2$VKNiya)|_vtu(-VQa2yxvIeLKDE%i+3W=`b~skgdHV|5kFZ{r zv*m(sK|Cb`<c-T$E|FxdaE9htcxkKY(Di#a-;0C-ZoQ*_slu}Y_K@Pqr?M%{Ubne) z-wKucsxisJ<QT`=%@kdguy^cBucZv9@ns@%??CiP800n)A}yUfnGcaIYo?sK5o?-I zve%H_Wq}z=sY5`=wm!>>+b}ga%jK`%3cPXDO`%$gDt@0Urj%KW)VFxDS_j~L<??^s zGEnOEz_zyPx<JUQJu>6A&F>kYzGNf{zi*zeBBzd|z@~tn-3rN%rIXq0?9m;(%N7t~ zJG1qwn9_fFHvl_kH3wcEPlUVc$q{2kq>I=jAsR0s-03VCGx6T2pVM5h&YtSQoc{2o zg<r^an>(JAiJ68nwAj2#c|fSVoh-)fzJO~H6)&Uqo{`?&59@O`%@4ZxqbZLzl55T~ z+X}*s?r@6sK;b-bUB3E_BLKdPh!+W6#J!o(`ga$fstS}pl|%H~*EicB-Rv|y!xy8` z`|oq<LHI*VO0_Tnpsj~&z%aqpSnBtnVYZGO;##XY<nIru*Ym#h|M&|p22+-p8rU1I zB}r-p_oAGyp3|gfv<H@<Ytsr%7GJi6Lvt{iIxcV4$x@-A^-Hm|F}rh-^RbGTb2rNv zCL^52t&f_;=nqi?o2{F$;hwyy#=R;^yRTZ?GR{f9OGFKVff-C2wL0s)qIj9mD&>uj znoAPi46(hu%wK0djZ0$oDh#{|HD`~gT~uT;;mYf!&4Ufh`h-qRC<#xqg-ww1=};|( z=VmcVrOP6dKzmAHnOa${PlOM4jlLaKv4qk?fhj{l%fPZEy$GCP)%VWon$X={51P{I z5{>MJm5CyuyC&KINeEf&ZcQs*znm5M6m24ZkW2dDYms3A;)x=>a28;^+D<u6o{m+^ zS%4d<Z^(@UruF)a9k#1Wr)F=7vK70_x`LMJG!!*@E#^#3w{(<}zWb&GAL8)0x%kDD zNz$pw8k^)9PnZ@aM9rdQo{|3-$?1CbEZ@y)jT2XS0x3laE#W=*UL`zA9I^#(?3&6! zIF*2<)-L+r^t3;Oiw>o2FEtv|&ebR~*~$cxZqYdEH;QM{tj+U69@fNNvpjp9^S7Fb zDmr{f*1ebF<SIZFi5jJi8-qD-N@niw&HbW?3>$6rN--T~t8G))3u<{7sMNV&1-g<D zB}&7zW=~Tt`IPr%#?)107R(54ICcQ|iz9teq-VRf-PEoJA=ZMojeaxDFYBdAKrblg zdcec`&y4QuI(}u2Lx+-yZpFj5$S1jzOtWfGoK>K|B4`;Hhd29i4|!DiYa*WOV?}Y& z3QSU2H@H4itg>OvoS9Z`#{ow{9j?=OkmW-yH`D^uxkMY%&PKN4_7R#%p}XnQ5Txu< zIRd?QbR9AM=WSDJan!irMtAY#&6Va>31%C=F89iQ<XtIIU=idb&{7Syap=K(hjTtJ zJ;F#3t94L`a8{{2AGHZ+47I?dlwA5)m7aV{R`7}<@^eNq<;Wz>wJgD2Vy=Tx<?R7e z{hbT--RqkW=)1(ge>WRg44z=Br^=59KihhK=wli2A5I}ugte_E&%?C}^tK1@<`Tll zw1lQMpR5u=s`G{2q_x9zt?4jEI?Y~&EDKE7y)sKZVv53QAr1mL_S+OxGtP-rU$S7S z2DZPGr=@;B`|@~ytP8vGe2cTkGB&-1QmYrvK4zzyS;QGO!{#dGGHga-RAxrR227n8 z1vT*%fJO1L7#8c?s+UBjlf|tDOh+QOUr;rkY&X;lm}M9BTJY-&Hy=x5d6YJxxCVao zq?mCL<o<zp&dj#7rQbibDs7jyKkB4FgX6XqwZkIXG;EiEA^^tDlvH_Znq&sY0$V$@ zejafB<dJtCmUp#M+J}$KMXS6V*$^Q+vQfP<C0F@+zLfNXz6c7YVCo~+Gv9KiO3DRO zSN3Jxwv4}qrf5>5()27VYyC|oj1}{dyOdVklZ_=@{q#?*fIO`=L#m(2F%jX4Xtt_} z3hFsqXs8Xw6?-RHmCd3>itb1~iUf0Btdi2sY<^WPJiW@g5U0tOJMhBif3jhN=w7p` zxTl)_$TBY48<OJ#7i&8E8I&6hbKE4Or7vKK<M@!X<Eapr&dt&cJX~(}+2yZZ-3Q@l z#NyM!+#V$OOxZH>jn%*4C3xLHX7SvoEHA{~xb!%|BBJ!v0_IeR6>9N<OJ5Sgxp)y0 zIgC_eYH8K+k)?M<7==YFgj2*TlPz7e|Jbyt#U9al!3OGvrkB+9XFOl&CTqzH4agPS zUF(&r7y1-#JVmo-J9K|HO^8VKeAW0+LRsBa;6tUgDL2ER7VtS-+}N7cyEP2?EIbRM zP=yc}n)4yYTXr++M99H+-HUBg9E-|)s61<8OwcVGBt<vs9vv}m5p&^CUTCBw4KIT> z@XYC#EwpJ|*78k^+Lz0|^Fp7$pvrBjK{3+iQ6~k>w<D9h^o*#z%(KudZ-tvdG4t>; z3tbAxAgQOmLK`Z3SyePh2%WrJXeJN%D|M&xgm&kGuiONO{m!bo+cCKv`E;o-6PKGp zkJwlp(9KuWL>oh@VtnDlm<^?BQU^E^{k)>X1P=?rfLC>*ZVY=>ujUvcI$whJ^9AsM zdX-87R(?>Uh+x@$orq|F`2!}Hj6gQ04_Mtrw3P*UEY3gc`iTaxutlSmGgU4rxK#W! zQx0w0ze<=02@c2BdVvoN;~8leJz=eYJ1EJl$ZnfUH*%~eS(KN;Wjx9kj{S4`ayG}z z%qKIcv+kFkt7#Uq#$y!j@$I2%0ubRo)R|l(ucEb2=IJ$^l@HN#rOVar8Q1rY4U#T) z<E-apK!ueF5aDbS8E}a_C^QA-9(aL_rrI!jT+$=6lu?X8MGAQ_H|sIseBORAfHfcK zkMN#Vo23lMxkfEZcH)(m@vK(GU}M&KPMUP9sk?aq*4R<6RGkBJrs1-#W9y4Ov2EM7 zZQHi_#kMoC%}Fw`or!Hul1Z{t=d4w=cUAv__pR=yyZY+;77^^uFX=c%$gv{c>hrWo zmc+DiIrVT)T?%ehW^ZLX&s(9iGnyj3u<qnLDz-?C33aTdlW+N9*UI+@dl8Adg(9Zs zMBP?ZtFacbT?)dXjA%`a0OeXsWm%IXX>a{eLG#5vAkC}0DaKI;+`wB*a=1jAg>7gJ zQe35tL1I}mp|}x45_Vm3KEujvrQSC0M52b*=tLg*lJ`)}D4b(>HP(&W!PsgeARBEm zzs94;bxbo|*aeq4=jpi$aPH%xoBcKa`IzQGVG)ypw>bihHPNIOQVP!@^jE<+?<QQx z-I7;reziwWblII$o}gaSNn8lSM5XI@6f6?7FNg-pfQxVefs*sCN}XI>Dr~Gnu%ND) z#0FN1KJJ=I?Mwk1cQIyF=j=i&rMMT%9oYn4Qh){Zvh@)Ubj2W#@eoP2%)q|^O_=~B zc&bbnWtY(3-~msPm1lS#2qe8^!6e|-fp{uk^(B5aPtDa!t$D(Cy(;kixww}E`n}c) z4&~HwQxNC}hYXc+`7+s6K?a(<E!Q0Y+!g;u3$+G6@R%}4^u*`XeKM-^b(Uz8Npu5T zeK}oXy~yGU%a}Ch!%~o#bdNlx)WQ|fEMovjw*TOnke*K-#rp8mza#V-+-;rgaIy}_ z-nP=A@mjo+WBTd3g?4sU4p_mNg&mX!EC|0cScvN1oJ&C$5PHlillIJiqpa4^bZaqE zbbg*qKxm>zM^cPE#<&DbPi-cizWpi>jsCS@a887L{>j$HOkf)Oj?}DaLFXn3W3y-p zEI<tE!8FbN7RY^Zv(F-29bb5x8rjl|eB}3T+Sv6I`jtVQn3Vi2sm&1bgypBY@|h|y z(8B{Q=iN{lIB94ik4{sS^Xcq=?{kR|=<Mle=h+RRiC>#aifS@j!@VPg=rS*+`%Hy| zXPK>0$zf?>8mInTuZ2BVU4cDk11klY7aJOiKz+}>K~HQ@9-3>`<kXD#L{1Z)f)DD} zb-oS~-u1PcYL068uiAK%Ws;>Zss#f(2lD9JRl^T<R+`pRdOrl(R-3@kof30XPhuF# zGqrOpF@S~nlg${DCEY(E%tTwZN;~wBpu{eeW;M42F*F$=fLP%(jrvQ-kWCf*vx%C{ zaH7(^rB1?;y0jn_Zq&}qo0NVsA|2M=KzpT+JZ-+cow;dI?E8AD&;^(c>bNFOy@Q_Q z&GZeZ6ij|D7{%X#GB<x@haW-j+sS$*K6GBV<0v+3CZ}jntv_sXV?wsw4x+JxsmA<u zClRK1RaRXV9RlyXKj74G_fIw`bw320xQ(b(a>Zy<$oPT0QZx!=ylALA<_%1phF)x0 zZ)OWsJhqRANa!07Be8RHO*3+YljK_5vctWNG1jMO3Dn08(Dj3N=>5E+W3Rd<=fzdu zi~xYogg}z=4X>(bn#3+-H0JuX=9!?Kg!|$iofopLjy3g(7M&Ko|El&DSXM-LhvC}} zxv(ySTqvGYi)E9wr!^Xk)_Omz?KZAfWL1+=rHe%`9$E>}LN<N&m59`uTvE0I%^?wH zT1Ovw3o%~E(9WdY4Z;0abP$mqJg`&AO@x+g)zIb!299w5r9EqxrG2sY`PKa5(BDQe z=C7q*&!5XZj1!ZJA$Bi{z!hXBolw*R3l)Mrp&Ih99`+vVkUqvPw(ST4NMMKxM5T@< zjy%ko<n|3ri>#ZhukPw^eO|W|qtHUUpE9uZH#DrSskty9`fV0!mI)eZ4W$=n*8D*E zGQe_o7-GDirC$z)+=15NoR0uc%m!kk)N%i2qAZ2pNGYT{RWH3|#AMg#8i+i{WJ82J zD<T6?>f1%nwHRT%3O7eeN||*N<PdW<9C3VBIKZ4GW_OGje-O2bqZ`%T9iNFQA+(Ko zlDFLL?tHhbvvIsC^D7CfAOXFMq>2pyk3w5ai8hK{4=DtA+D&B_v5&t%Lu4)yHT5XH zw7`~%Q$kxp=1eFq(+rUzDXf!nGj&N5Jv1u$BGJLiqSsGewpaP2gux0{V70?=P1sYg za#k$LaeXEzRNG4Xcs}VtQGti=WQ=<?gVl9I{kzgwAfsQ;ZQ78w#$2&9F$kv@!myQ9 zrbEVn9>xFQi@BVNjV5Up0iif#$%E2?YcOX(1`-;Cl;L3BmRUIw4<%DP=yzCv{iY}a zm|wz=JsY#p3Q-#QTL0W5KS_}&r0-;Shs~pb75&M@FCqT6oa{9yemAv39AGk`{`0eL zvUgCDrHRh0&N=n9^sgZ(oGQIa#q9(gZ|0FJHpd{-JbgFSQ>7;vINIJTXth2SsDj>8 zX5TRh2--Zh8@?PHR5uEj2r@1RUNM_<W#Z%15WXsGA*AbWbQJwKXf7DV7xCijx-ACI zat<=WdqPUO8IZLPL@NZ4i%w?gi$qmLl8GZ%=-=POnHw{P;AZHKm@E9l14)e>WkH6h zHZC(|(`}GbE6X-eVLUag7(gzRBBZ;Yitu@ffsQOSbEyd?fz|<rzk2Oc13~IS!ZwRq z91QDg6Mb*XOI&SeG@9Z~$~w(wNe$9H7lWW?nY>k(h6C`ey@WU)g8Fw+Lz~AH@j|2$ zDWuo2Q#6Ox9Oc>$8l0*>YC~L&LzW7AnAL@rnqCMFmxw|Oj{~JlTfJng(e2L3!ATMv zT~`VsXPWg#>2@o~E{9mQVGA+-irh44>GM7{??a4$;5Ep}Gs;9skh7oBPlO1Z*3~1- zE!FSl?l<^iFj#dl;!eitc~z%z?#KR_2iMfYbQ%n_ye2H`g)z|bJ?xr;JaI{!TjWWQ zY`|&i0W|GBB;w}TM3X9ZSu!_qjt)g5bv&2zz9@QgaHu&!mazJKeO}*=;ZCovLPC)f zI_t|^SZ-GlbG(od*Q4{MF;o*$9La}QKNav|&ytlwkqi&9D-@@-pZW0F5^!aSRBx3V z$RCahFgW+KJ;%U+&qaLHg91V8M}k9&@|EdkKn@X(E3_{6YU=^2jnEE&F%^J;L10l@ ztC9$~M!d_oUB7YN!c1|+GNIy%<ilPn3CPhii>iPk@pdzd@xlZvP!LD<CV}T+Z<!pF z;#2%K3E-vffTu$ey&nn{6U%GUTZQ_3K1V=>2i3HUtCB!Dir`r<tSf8<SQ5kn#i2n3 zc>fqOERCw~XA2`<r<@gE)+KxKkAggOr%Tk`DBmWi)>)7g0}>FR*vueV$Hvob)cJOD zNH4uTZgAD_HpSfj*w1J~2$5S-HdBENNwm=bZ?<+yAi1n(Vltce5klf+%T%LjwkEU# z`x&EA;aPqxtDa<GrPSMo9E$AIG;eH{!D}N-+v}Rb?vOrZdfM?G%mNvSEH=U?>T4~F zBt-J%66>C#)$JQLk7(cu+B45fpE1X?g~EP)(>JB2&NoUo)5shf2=3n-+N^NO+WJe* zI!{*B#7Y1Q4Zv!__X!tlTTF?0Z#We|Dhu!W7kz`$!~zAg!}GD&rQ;MbYi?RiuxtLh zhzHnF#KU>y2nSBT_)Y}3u*4h$%3A&7rE8>9){oaII5r05`ZJqRV~K118Pwh7o}v+U z?dY&tUF$b54#D4et%RQgtPK$5k7%+;n{87~&(Ww@<LL(g&ne6dQS8j*l)4m)H5hGs z69;qmaC1IDLkcSB(B;K5dvGU6^Cw)k<KC^aQ`(@Jn36YVQDBECj?6tZq`A5!n+$CV z1j2y&k49Ew>PHeN#J!r^MLStKkTFEu37G=Ws$y5T<lY5`o`$1_TVJG)(7|=E1$?){ zDRmY#g^H*nPnK0mX2+<cjLcE?Qk2eiEv$CI1+c3nJ|L#MXINw3NKH{!nlxR@RORwN z1=N2Pszn+YF2w-4z|I~yB|zz#cJ}XUsA(`W6!O@(TQV5s9FVwKy>o!q4~77&<xXFh za9AmnM#@MV1xqIy5gMwLczA+nMlC$)sMEo)D;L`^HKR;qHp#farzP{txqL>#5xXIS zhGP&2OaWj4wRhF5TpHQhxE|NGmaxDhm^(Y-i4)BjG=IKg{=n=CFG66%1hR1XWk}PK zhSx|>q7lI^93a<TVzgEWG{ADBsDj7HOf+hkR2=5qoWvl1^%;iIL7XEaH!tuxXXZ(= zcWpL8t}10_KT;^5QODDH*O-^DDWf?y04Duf2hu`uGXv%@I`7#J^O+|fX|M=9`&X&D zEeGV#)Z{O9Yx1oHa(i-?@o6oG{;KRB4p?kB%PM5q5~7uFwrh_PLsl$(4X${`1mOgO zk_oZ-FX(~iv)zvR)Lq=vw;)*h&Ga;ENV868a>`6!b%#JXY+f*Wh_JTwoVpoLTgF6C z257vWuhc>GC$TjXFHP1p)}gmT<EUl`z3bl!m$v?wg>ks+pNtvdhsPGP<dNX!x)3R9 zd1m#&lk5<yg^<a5F9=y?jc`|!TZx;U2Y+d2={qN~3Ww^%j<OVIS(KN<&7|{p<1p~l zlK*Ut6xA26;lT_Wq)xqnkK8xOJ$<{rn)24DCLPO;NV^pMt$K{jWTVW62gNFW@D#L$ z*=C{?VHGDu+uqU^Z*h50c;Cg#!KxC>E8S}x_tC8C{>@Rh40K&H*MEM4tCo!#$7ZfJ zU?5c85&<pS+F~itcXc=KUMiol#$bsN<5Ost3I+cCK=gnW@w#R?`8lEEqUy3k!u8}7 zzaAwTp7?^JVa;JHH2-f;I$L&n@ySV{@nu09G#f-MLyQZ3xp2BMPG$m59~uKzTHQ{= zj!+375N%%9?4&~jObtY=O)`pGL&t@&u^Z;=z_oz|C)g<>ue->4X@|5HeH_YtG-j9! zkP~8wnTPM>igO;M!=^$v7D#|=l!yPCYEn6A7N;$4c7FXuIKJ4z(x~-oW85+;17%0p zZZ&~YAa&qZ%NcljR(YG@sNVSEInK+P<evi-bLiZNYAmhJGcxxJ8&?repN<n%zdpy? z`R7&N?Hk+!56R1ghzDW0fe4gS9d5Y}5MC0QYa*q&v$pp?8_n_khIs^kQYUHDEJfJq z$y}0cSajOZK}G`yS-C96@%}Ay79cLkb*GrbNX-T}jWG0+qF57H`js7xzrTuLLDw(X zKIUeIPS{Oh6upc{^GMhQ6gKBras8JCP;h}GF>-B>!&?Q^;uo0k@DwWANp<CofS$&z z#ts11fLwg{sg@VE)ZUrS0$N?`A*!`Xm2-fsSJFy6i4_N~X7*K%GV5d`FfzA2rKh)K zthLl5Z%Ipo!R<I&$&?gktaynaPsm<(T|=ss+Kq7>#rK4(GE5`cS9?&wfI6@C%=Nl^ zh(2jaiS-AFoN?iOOolu6Rd5wWx}8?L6Lp-VByQbHzjF>(I;Q2Qa0LwoOyE-!^ThS3 zmL$Z19sqj{?AeX}cR-|HXC89Yb$-XF^srI0H-pap)IT50n^e@Ojmh)y0ltNL%uWh1 zk})}ZtcuhMTO~K`1v>sLxUE+6>prA?G!%MYJe5sm7W-2RiI!XJ8=5`1T?G8`S2AmX z&DE5Y{!srflc=rqL!}gHgdNk2@jc$v-hE?=vT@3ozHW1~U>x;+N)!|b0>TvX6U_}+ z_5si)mV_9Q3PDEuUh*std+v%i;}8*rr<a9rqy68&-P=;@T7leaRIFxOD$OVi;s*i6 zLQj>bGLH*Z^hukZ^A1;VDG}znlMfC&DVhBb$XHc;40oS%V1^HZt=A}A8``i3^ZLtX zyvTvBr!Lb6B-U&fAAx1R+Hd~jq=CtG>dKgX5{v<p;LzMA771Ms><CXFS7JW23!`%e zUP?3YW1!8-MKM#Psp)CBg-^NiZY@u22{M<nf=QBvjOBYHP^Y%Rz`8K|NUyc2!N;Am zrv2xM3#&ePvtd-G8Ynt1mpbG~ZH-NCWKh<zWhOBJ`2|HRDE?%4%xcKj;#ItBx;wE8 zr&~wDgZ)9bDLWddl50B7Ew)Fy=ObDbB7aOxCG+ufx4{>nJb$5Ch8M`J-ydp5aU&mF zcI(zV=jNhTL<G|wo|VKMv_#=S8mUOvrvUvRS8@dv?1qXMlSZMLCNqa=;S*9KLsO_@ z3^*O~@>*JG)_Rt#5R@z5@vLC%xnUB+;{eO~!JuZ5iTnhn*Z1y!p^u+a)x3oW+LguE zM>8QCjGUlfayWN=i~oC3J0wTJiht?ijr^>LS%w&!9^x8^X!Ss73)Zg$lHZt2xO9?6 zd16_6mv)r2$IX<UN>CT$M097A1B~qLIq~IS!;#DcGDI+Z=qtgDvhVKTDp2q+G87x2 z#G-R0`HZP(;(E@EjG+CE4beGYt1;k7A14Mr8U&T;>PdP4V)Pm7(r#Pq<fF_?3L`}J ztnfL1d>;q_={hT+(Pg=-c1PKkrq_T$%)Vg8a{cH@2g5zPTn>0;-#(MVWvd#TQdbq@ zes|cSQelMgDCg7|7RAt{`bMvAaKC0=8<&kxhEXisdlSN`Se(tk^AYmRZ5wEnZc%@a zl`=H*F}0s$LKYyn1YCHMxA#+uiHw=&0}@%7XwZOUmduj5;CoppPjk04IC5a?-}Xrs z#vtxsb<c{0w+?uXMl)LDz{9eO={(Y@L9;dWRJZ=;5JN(+9NWJ72|geeDv8pE`oFJi zlF?*L6~m>hcggwr(Z3q5eI~d>j%#9UK0%|Nxyg&>?&~P)`^ezhx-h{H(#T+?QsNSo zC)e^%GN@HtbTwp8J&SqE5xEk6mB|`g1y-;g?Y9ks<pgNG@<=s{7ujM{py?T`5H6Cz zCd}r#(m73bvpqjQ_HWF7-g^9ntpkUW(x@t*#hA&1!Iy^~w?aBho%h0S{{Ax8f!O?b zn_5lfScJ?9?GZ#wgQzw}GiIr#rKxu9a<in?DZfD$YOu4zopM&Lr#j!bqIr3Wk)ytx zqmCJV=MLXLQz#BaT5^M;VkSU10cefC8czlv7DIz{>ZT!QZ9Z-3e>4BWSfh%X)UJ1; zFT+0kU;)<lBYheEJQ#niI7M;T?eT3$g3^o`UH9L+HEli^<%}?iQZ@;NQ4%cP!n=nC z_LMloYP-17T#aSRf<2Q1Yjcv+T~_EE#3vgTU~E21!%}uN<&XbiFu&$q!e;p<{W4dZ z%Q-A33VQl>>uKk1|7j<*!suh3M?^+W?mTnbeu=41nTgp_)0ftNhULILf7g8Uh6^MV zs-g3NRx0vFRoLJj7b$8wEcm!npCKh!EFLNy)xZFN<l(1C%h@TAb{(xD>~fGk@4mjA zr9G2?{`K<l_0Hr+ClA`J9h}6E2f4nocpPc_HJi%H*0(V%a>DGTjtO(pfa(z02_K)U zfF%~OA;M*BS$s+O70U=I1G^(8&4oVu&lopf&U1-{yK_zZuUN$(f=*~SPs+mrSeMKT zphwAIZTa?-1XpoX!^Z80)Q=x>8bUy&>~I40*Q{*-!(ZnFN`JHABv=^pBg9OT9=I*2 z{rB+%-QyEGb+~^aE9{ZpOr_dGsij+WYsTLFQ2VJ@1ioyzsb)eV*&ow<y=349%w2yf zU)VGQhOqptM6x=7QzZ1HDC&B#5pgw=MMAReAh#ePj!-|r>b+qf7*$WODB*)ewEDJz zD`>Z_XTPHg85^!@K`<NWiwj>ss%EscTt1naDqR}MOOm<l9hif5&v>P@$Yk&7M^YCH z!YAbx)0LFGMGA3RNYxkhCalj<<dC=mOnD~M=ksqQbC)cjW@<T`E}4=I>oz6r^BdqI z2#ts_4d<@texltaFo8NA4Uc>_%8(I*bVHNbvFseZVW?g#ZyaoLUi|10l<P_lXc%7` zbu`P3de1y$DCNR>%rEf6=*8I#vrF$ZZ#;uReLsRWM&luy>Al++m^YAXTqi8Zn#}=< z3A5=kMgi01)wyelSrt}{3YA7)s#rG5>1tzjo*uPmNfsSA^an(4K={WJQ1~JogR7;A zXGkp9M3}-a8*NcfE52J(CK6!_g&xK6hK|uXo<J8t3Wu6oU)O;6*I5<K1z0JY%;MVm z$I@`lrVFjhKO+18_Lq{{)B9jfJdUe}^|lLRa7XJ8Fb@_Nq2DC$)E08|sgoh0=jYgF zq@@9IRN|+L_mA2*MNjivi!m+F<gYsCD#?!8&$+K=SZq_rq+#V5go5s<Una*wW)&m- z)GvQkIJAccTmD)I#twr4#VZ|&(A4`pHp4Oy>kf{}J3zL4QBZg0jnx_$)_Y8y)wRXn z)XO6>+OS{;5)FI%`21{aS;E5zp%ULkxEPe68JOX*U>h~U3#RPI>(B_0LPn!6)kMbU zo2t4>z;B}|Eq|!&R;P)wjnVsW!X-D${v`_&C>yy%QXc;0?oEpknset^h;{$ZQI<88 zmV5Ljo4bIk|FG^god4<DV}r)$IklDy9=iTa>=3}DkZP*R6-XhHwplC7HklBKFPqIh zJpJBwU=h~RfqBq|#^8;vdQXsNi$eqDBv2?<_msZ}k<BPC(xVBnU`rq7`b!IU6G_58 z1n)PJ?|kiK_LQgz59$jQEB2yaFfcd4<ZHwnv%MMz54D;km~bH{7=dMN*<;_a3-pJd z68%lV@j#)UlTmZlPom(Jv_>|4IOuwr8{ep+()3NfglIv{OmI$DW1O@`uV1$Mf3L%a zGj)IzknKzS=~&b7#Snd2OBFT`!q+lmM?ED*$aVSIKd8oTq6yG)G9}Hr;TMfy;N=2e zhp3x1#(ksFs5n8$U0bR(x-xZ^P!PM5EK&?3ibu2}YBY`d%btvu#3k~3nu$M==RjGT z*9Dcz)?HyQq+ehQ-M1}%z8cAb!t$aXj()$Uysp8~zd*)B$o>v7(;AZXYOZ0NO|A-7 z&|Z;od#LzhO4H>4e|NtQ(RWKO+gI>kTAqVU5%Ug{43Stt8M)T+x>!ovCkKq%8D|p; zC4w1?jc!k&!<L)rGRcZNJccPIO970^W^YS5+V(L!ktV|4D($kvX-ENEH?(y~XuRsD z?)M?K&T`LwGuH_LY%b?5wq^Ko)3O{4`2gx0+yx;yuQ<^o;S*HkvfljmKXvg=Ye*#@ zW=)<5&df6A5W0ui_pfG?fo%%0d{0<82$#~p1`9=L&{M_gkf6oFtS3g&a>ZzkB^SKC z;wCN1yG0FE=+y!)EG(H8aO@(#qHZLI?X`}CK3mEb_~3z~F$P7(;u_5BB$Teq9^WAf zV@(jGu#`y=T!l6b&Pt(yte+{GPpwkGfHYT)2=Ew%Gxu31&dxT^Wr%;SSWP`xg1QR% zXfBwYg!&hrZc_{}qMs&eF9fSzh}~v?Tz!*4{yk4){RntKEB0#`6&4(KFSsNoIm#B+ z{NX4}$2CGrrJSa7&gn@KymILp`rGJ^FruI2fL&aJt{ucprdO&dnFiY`0$mB;yf#Ex zf&#V)6rNC4KQ>ELwl*1F+2B4oDu3%cp-XvoAVIjoSz#Zphc+w*qWR6aGJyqjfw-9s z&rT2q(p~H@_AJjliik2^7Rj;#`{X!5{s7a#F%V%gWqd(%R8McFm)ZrTQpIrz-(8F~ zaSg>BW^!^%VToPEhRiyQHUY~f+w{^|ivyO?3*|i$uuF@S`<8V1fyx`;{OLT+g%K<$ zoe%7az_V=19vEkd9+e)FeE&~Ylg%b8?zY+Wy`dkO<aKmJ{$j<jI>apEAiCVAFc&I5 zBmw{yPIr3llX*0!bA77}7G$$LG(Y^UfwX)&vV_w47{c0QZ7KQEJ8U8N=cS`_P^=0v zatU+qWbu?920?)D(#HHPjFIppJyj1Tf1&ui8`@%D-nB3KEftxOlWqgklNO8CEu}o) zE~l?NWcNsVdCTeV4N9C$aNjZ(IZVa-<JeW&xxJFnMZ9+$4pQEfapvY#uxXWe1N2cx z<4)~~#!=HII|wY?#cg`GskcgQEhPP5Oz+HaDA|)t{(p+WL}2aR`4pPL-|8BJ#6TSy zQ<q<yvdw&0l~_@{XjVjNSafESZh0J|Et?vJyu_3%oj)ztV?xsX3i^^dd2W&A_}|Gs zev%sUbeKsk9!U*Fdp5PwogC=Ab7@<%P>VVq22l>VBqGRw_2<d9(&Npu><l`rUzh}2 zpSPiav4J4lc8MY5v}O4~&~g!RI>OY2c!zGQeb-U4o&Ap*xt#IFeU)wQ$D~^Z=R~~F zZiko?E-E$L*%IH@*-dsB{Y*Acu>JPXCQC0q`xg^pM4vS8{9m)fib`nWviU=D!|Uz| zh~334ED8ggDV>zo0wh8Wmpy0bboXVd4e=w<$)OEn$F96YMA%6hlsCNLWaEK|Jaq2F z>u!7EBu}|OSSDw18d=d_L4YxGE0+E!a-$q)8*5^5I9kny0dqCZ@Uo48Lfx85tX4HH zL2hoi<tk85^9%7Mm%yZY;Wz&(kbkd=Uj>SN4+R5Qxu5a-aNhB{pVG)CeP#b{zQKX6 zviKLJLsJ@U-CK#4SBS+${b(mW$$Kibl<Vg31p@Ex8517HQF^86`at+?v-<rY&rs1d z)YN8OKyS`v5V}$1dj!8|A^b7{$ipNhOE)_u028Ntj>ToWFBg|S*hI^EFr6VvDwfb# z(j>IlNN@sEG6EG%@d`nlsvhTj-JCE~Wlf#uPxPNDU=F{&apr-X6Btz49set`*(B26 zCQV`&jG!GM?T4YOL=Gz^3P*RBV>cs0eLysb1LfNSkE^=dHKua+-&xBReu{QFGjF+C z-KLUKNLU6PIvQ$Ll~+*YggsLlJ$yYYHMa7?-yE)Tvz`s5`n+@Va`+~zX%AIIDN29m zm)}`B5mIL=7T7YHCF-BtQ{rB|+rZAYXlA1cLDRcqAHW?*%ghOOmx#seLw`0$v^Z6M zEx6@a=o86|DgdMd7rMQTDE1|{aSQ8?-^LpblN6?oDBWYJyT9Jvzk+wlrgP>Wu{?H- zhF}EHi@3>vQ%>di2YWukp^<?4e73MeHt0H%Ek?3i>81}HN#^Mg*LJ4%h&!O+m}!)s zD|H_TJa>;>li;<)P0O&FQtaGBLmq)99=U$dA1>}$r|bqn!(FPY372TMx&twCn@(^b z+Mh-(nCBH%)wm{N@k1(BI$n_m>d_W2K-Uxk4C+U267^*kt8c{q7@C_(Z7jitn8ix- z1@}MIFsT$_mwErkho-G*s7(-Y?z&87-}ZilRY?)Dq*e;@K|h?{8glp+*Gdm5vFa;w z1Y%>Q7}#wg5VyjkqH}e)l(<Jx1~ikEU%<?2rd+OIeOl2Bf|sl*Mn}2BtWlgV!)ToP z$R(^%9Fq=tqH2(Hm_1ZJRXOFJbeuMM<=#krISdwr#cvZn{D~pbc&DE~(f;ae#6s-O ze!emGKX`uaK>r9x?e}PBn;BB<)zftqVq7H6xTF?4JUgDZKd>o(Qn}nSli5PKh_kkZ zFFFztW1tRjXD+r)xPu`Ueq;qnwzDk7kY++RE7{H(Y2(HopQy#!&xoIdItA0IgUCc) zTyJqJ5$?tzRl)Z>9*E~VxcwtbvH^>qdlk?kuU&p12|=4aVLsf`(Ih;H7}CfD+guao z({9N_(CkKlo>4s+ui%}vRlMYVsopNp+70oSVGM$(+0VZkua>KtE-^Z}kg2p_daU?5 z7`d%<Src<eYpAsTs3#~)aT$(msiqfvBymFe7JHm8gk?g#<&q{amvY5ROTm%w73khS zN!k7*1qTwvr#9S#YF6Uv#Dg{#A><K!MGg%&tM_!ytcOozW@Mis2A=9><|`969N)Zh zCNk>up&;;C^J}$#n{IKXsqS$X>^2oL!8#cTPT~x48L#}RIE*5eA7m*B-t=zcGbAqi z!=}nVo&?!QugI#xe(Uy<0#|qZ)K6Pvv1EhhHEkN;CU0V#a{b0h2R;tE!zM>|Jpqb~ zIl~|#-f9-c0K|n8f%3S@1l|>U=uYdiS-y*9qb;M7Z+I)O0-WF1`~<@d@UoO`Fs~85 zsoWAx?6(k(Ygw?Nz~U2wSIjoj-}0uriGSuZVf?G_k%i+kJA82mF^0K=*Nr>H_AxDR zkFzlJ`Wn~i5W&);Att-3qrT@IrvmF=Xwk*B5j$osyA6loyom7HMS|@KFxCk$afK55 z)&_X+`^W~G<SRk=1eQdRMa-MtSm;s%XFAs3T`EZQ9XNYKQ_z)QR(Oswii=i)pYs48 zLGoG%V7C-x)IF`T;Dc1QLOEx+7#(^_wNxn4AEb!1SZ(C5?qu*3ejIbh<-RjzzyECm zy63nFrEA`haY;w9H>&Vs5!b>TJeyEEo1kr|m=qFjw#DzEfWb*>sferwIe6G#etU=F zi3VCTH3TA(3`%ilG|jBLdL<2WrZKDoY@$46vZm&;FcD{TFj1l0>W7swqHXH`M&UOn zn}lNjEeHPN418(-ip?!4rs}QT=ROc-yK$kWJWrjd6M%YMCAt;|sH3~+Uo`09;I##7 zboXhM)oV?95Qly^&_bC7SGl;j%-Fj3hmf%tm#z=B*?pPji*-h7)C~$@D(FiJ|A`>; zZ_YDQ!ucx`N+jP;B=}6O5>D!QV}oHK2)#RSLDAM(c)_MTyd0-)E{fJ8yHThhEa8dn z46|EKH-h@27bL7MJu>`cy*kgrfcHF{LuuNg2Dcs~&o)O5J#CEkK-gkK8c<J;4j&SI zsD!c*2T8juiskZ81&73;?Zw)O&WxqzdLOAm>n{-wf&v6d9qlLq=p090FeHF$*2WZe z(TJ)N&wFO$E~{NF%>a{lu+=*^|2fn-4)fY52-Qq|S_?6*>@V@6xpxCO*r2uMCZLVi zmpEeYOm};qoMfD!AFy%x!ms+-hD;&WG5;wG@iV29n37}FT&dAsu9cbXn#8UJb04sV z1cuDZ#-?f0_QkyzH}o_QlR?-P_`>+PT7yHUYa}u?Y{mf|v}?*RNs#3`zC9v|hyi{h z$q^;5h{Vk3IH*wgM=dX*8&D{TS%D-s1~N~3{5mT(T>8g7$`0E{57nsvlxQA-QHT?A z=x2+tpI94XJu%S~&Ol~?1kSp2p2mEly>-Z#EA!K3+Qw=K!m#iu@x-UbX8IvDl!b(c zqNZzu8CQ?<uW!ri7|(+(y*6rDS!Tc!!Nk8rrATQO)Z+j@=|<j5Ro6)SRYU1p1$ZbT zVXgawM|3!<f?a~u2HQ!J{kiRi#(Q?HZ;g3x25aswQ=fn2DOtxs8$nsKTcJ-($SpT8 zsJa!eM;k4)>MRtrGT6Cgg=~H-YBAy8*j5X*d|I$qm~Iv~#Q8fCRzalHE(>f262rC5 ztA*S_slhGgL#@Ph!)Yz<Tiubk^|Wzv)UG)G@AbVkmGwq3iJD@d#P6UQdMj<snD@Ma zA2z=suTT-mVAK4KR^JG{kgv+zg9N|M5(EGB27cjvt^c9?y{fCg+zrEJr)T96P4@^^ z<>Dk6?jLIdy9XaE-PACf@aN<6VK>5@OgfuqZ}OZbcL|&DU~maiO>`Ne0g!14TLLIx z<_FJCwRK}IbdR+X9}qdLnO3q!^$iln<T7m?_L_^*FhW&601qO&N%vw=R$yZ8`_bX? zY|E8@pTw{Cn+%GG0>fvX8wv}_R2@XotL&_R3y$P{XG1T=g7UL97pH7REUOywg#|_3 zvoF4;$dU_!Pp&3EeDz9As<UilL`Nm9!)T60Ad2?93Se4B0_1N&BU{W?E4ik0`{deh zokM6bx5+N<0KJX4Eo_bOfisO6InHF8#&N#8NHGq~bRl+7e4^|Nm1w%lY7+!$nVZ7^ zl}>D1P0wVfv5acopWAg|da5rfb*fPh_EK@tzX$ymXBdC|W8)#df8(f$P!;fz2Q&7F z)3ZceNldz+HfkJ(zUM+Vp4sfuCa=?+9P9<1C13am*v7*~SO{=Zg6!<5`8w$Tv=n^Z zdwF}QnBHS$J3MykCg*@15z872*#6tz(LIKsv_vOE<J~1;Q$#=XIXqm05(x&e`&@qI zPs5K41RUo<@L)>sRpW8+3yHDBZt`1)M4|_@f(h;W=UuY>X#DLv7`2mVppNAQf})<J zx;}<a>~}h`pAyTct1IPaoTb?tv_EuY^JKAAgsBt$q$bLEmemr&IANihTd_ykTMZ`a zq1yC1Hg$|?#9pf0q$NBZE>gafH>f5t<QLVESf<Y?(}PT0F1o8S5H6>EM-MQ+AZH+3 zRQMR0R8%mc<Nu~s!Ga5A{v=3co5)%;<r)J-H`(JLWo#NPNh*ycZhZnLP2C37sJ75U zvaVn}Ag45cF?bVR;r_~vbhP76VArmb6r?VCNoX=7;5HS<*NPXUU*mg!*grz)@o@M) zPaGCSp4ubG&oE^{^mX_)q$gtpTPq^!5|Mi(yM}g{u;O?eIs?AncZg#4?0KbawZ2u2 z)fA{gu$%6BvZj+YbbCghoQ2^B#|QP-n@BNY1Vx`x2EGRVP)zK<d-?o4+5=zAP;A^K zYv#`XqBCmv!#z4F^))jD`%H0uVP)6&ah&+Q?No>R$z7A^6J9&7Wf#?jGMA#&KFE`K zfX{>`SBYj$t5Au+52CC!tU&Qj8J7(*7`~=Y9*|+@AqI-fRo&<gE!M;3yH-Y8i(M)j zi)Ua*9FN&B+h7Mtm5qodryc7VD<u(nlpNQM0$(s90nM%qMiAaHC9pqt^UUA#fLb<l z?<Wz;r!Pt<t7b9Lv}a)=>uE+S^4lQyj;0&aA?)%^ofrg?!Ez%6Dach-E=jv+sB})> zuS}Ur5gHeVWj{vcK}67>>LPnpScL?L>8GQUb9u{CC-g9xdAW~n#3_sWZH55xFg14Y zB)E^DAR6kcd~!6<7bc4g^fE_k0{;pYKb8}_>m7HPV17Iu*EkV6o}o;yVepmfyvU>8 zKun+L5II(_d|9coKlqhRwS8p$PC_Ll#KnoTR_b8cF_IUZoG@2fc|Pl5wPxJlFwfgz zTPjOq`IOlI<B#9d&F9e%efNNbGEzKzzx=&SM<qB+=kmeMy_m+I%xlJUmG4RdEMuo` z0l2c^1Y)LL^p&@U#jE2KlgC692`3!t!TIbtrpDt*mzH3Z5VgQ&TWBiUkloM-GdQ07 zXt&P<fUYpR=F|$vl?w4CLR^El3!KH`_GOeyBkROB*A&2m7mv5PLndyttIpJ)(Z9BX zcna#;Q(k$TTh+bm)Vi4Q?{!XhL;+2kz5I#BNMWJ~H?-kapPF&hoGg^9dQh<$$gLO! z`^v7`@}?}=7^B6GRh8!XEhb=8>|vqkpk}Bi?cb<HLEQp9hFToURiokWfhi_kRD|_m zTo^|eot2-uheVnm@SDpm%2L{=7n>}lvEvA0Y+S!}HK!Plc9T1<_?=v7!Jlr|Vtqr; znv3!`-V%um974}=P+hHHQ!hMg6{CGO=Bjt}i6EsSZ=&!<R7yYw!31UCTlkSUCBD?0 zt8sp?1`(JSp@x)VNxx@K?RFZjzf;r#KVMtVfHY?OSuFJo?`TsniRDw@rZ38Ob~N|D z#jX~7{1yC|4Lmt;{NSMmoLQ-%0Hkd?#lO);xo%0DB5D=j2sTm{7epM)0p~0#dUbri zDFXWz!$@X7ydE9{QN)~;&C}T?DVeAqXuY>>o{-#?PGxzv`W|3Ql&qxqNWw(3G7P-b zhrn^zZeA8H4Tc;MImRFf%`l8)IGFj!gglSPA0A}kARzf<$6n@5-~z&>eYk;&tu^~C zk<yQZ1Hp@qp-MGjfZ<mm42uqQ$-QdPc4sx|)CPO&c^UZv{)Zlv0(HGLZU~>p4D-){ zF;;vLu$_r~8>&Mpb=s!a?L~SzQvh|HV(?t5c$l9I=25gzS^-Ldw{!#q9bL`bINM<+ zc{X46l+o#X_kNWOdFX;x&AY&~DByt@h3f-9BVoE*IHRgNI)ZTOljlC2AQ<Wal#t2I z<gp~lB0suD#^@zcY7MQe9;nSf&yS`V0Z`1dS9QdpLZ!r=F@0-Ruwc@6N<!-DLT3Kq z`%Bi0GQS&OtQM%qK;uGSDi@q`I;>}&C1zjEkvBXSz#|rthMFbKqF=E8Wsu(3>HoYM z`0Dmt^YC95;3V*0f6wdv!;|ZWxFO1r<db259JDfZ3ivo?tNq>T?l2MK?)Q$x_N}4b z`SH3w;E=sK!^^UHq2{=@-Z?*EI8xqhev8L3S^(miPe+Nyb=Ubd#cIr(#?Tvk7C+|c zz6XB`O5L16uh)*VS9Wr@+Z1L!)CVMV%0AqOV$*cx4-GBR?{ea~uxx0jhe@l&pb_ZL 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 literal 0 HcmV?d00001 From e8661e6d31ba0ceaefa8c3d69e9f4513a6d99804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= <matejbaco2000@gmail.com> Date: Tue, 20 May 2025 15:10:37 +0200 Subject: [PATCH 034/219] Fix starter template for flutter --- app/config/templates/site.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/config/templates/site.php b/app/config/templates/site.php index 27b2cd7c0c..a853955a97 100644 --- a/app/config/templates/site.php +++ b/app/config/templates/site.php @@ -478,7 +478,7 @@ return [ 'frameworks' => [ getFramework('FLUTTER', [ 'providerRootDirectory' => './', - 'buildCommand' => 'bash prepare.sh && bash build.sh', + 'buildCommand' => 'bash build.sh', ]), ], 'vcsProvider' => 'github', From bc34f95646043aa10224e1015ec7122b2135800c Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Wed, 21 May 2025 01:13:08 +1200 Subject: [PATCH 035/219] Update lock --- app/controllers/api/databases.php | 2 +- composer.lock | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 138428ef75..ec402333e4 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -3790,7 +3790,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen } catch (QueryException $e) { throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - + if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); } diff --git a/composer.lock b/composer.lock index 432676ca3e..557b61f36c 100644 --- a/composer.lock +++ b/composer.lock @@ -4059,16 +4059,16 @@ }, { "name": "utopia-php/platform", - "version": "0.7.6", + "version": "0.7.7", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "6bc7fbb43ec2b7f9ee5bdef5d4b5e4a81860950b" + "reference": "8c43cd866148a7c4c495e3401268429e338004b3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/6bc7fbb43ec2b7f9ee5bdef5d4b5e4a81860950b", - "reference": "6bc7fbb43ec2b7f9ee5bdef5d4b5e4a81860950b", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/8c43cd866148a7c4c495e3401268429e338004b3", + "reference": "8c43cd866148a7c4c495e3401268429e338004b3", "shasum": "" }, "require": { @@ -4103,9 +4103,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.7.6" + "source": "https://github.com/utopia-php/platform/tree/0.7.7" }, - "time": "2025-05-18T20:31:24+00:00" + "time": "2025-05-20T09:23:44+00:00" }, { "name": "utopia-php/pools", From 9f14f1152a0da7fd839f979366da84387df6b8b4 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Wed, 21 May 2025 02:22:51 +1200 Subject: [PATCH 036/219] Update app/controllers/api/databases.php --- app/controllers/api/databases.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 03016d8e2e..8883e245b6 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4205,7 +4205,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId') ->desc('Upsert document') ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].update') + ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].upsert') ->label('scope', 'documents.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'document.upsert') From 3335f56cf6303f0fa77a6a14c234fc5964f698ab Mon Sep 17 00:00:00 2001 From: Khushboo Verma <khush.vv@gmail.com> Date: Tue, 20 May 2025 21:15:05 +0530 Subject: [PATCH 037/219] Append build error to build logs --- .../Modules/Functions/Workers/Builds.php | 2 +- .../Services/Sites/SitesCustomServerTest.php | 42 +++++++++++++++++++ 2 files changed, 43 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 27c6e59128..257d596779 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -1222,7 +1222,7 @@ class Builds extends Action $deployment->setAttribute('buildEndedAt', $endTime); $deployment->setAttribute('buildDuration', \intval(\ceil($durationEnd - $durationStart))); $deployment->setAttribute('status', 'failed'); - $deployment->setAttribute('buildLogs', $message); + $deployment->setAttribute('buildLogs', $deployment->getAttribute('buildLogs', '') . "\n" . $message); $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment); diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index dd4efa5932..d3b4922b87 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -2651,4 +2651,46 @@ class SitesCustomServerTest extends Scope $this->cleanupSite($siteId); } + + public function testBuildErrorLogs(): void + { + $siteId = $this->setupSite([ + 'siteId' => ID::unique(), + 'name' => 'Astro SSR site', + 'framework' => 'astro', + 'buildRuntime' => 'node-22', + 'outputDirectory' => './dist', + 'buildCommand' => 'npm run build', + 'installCommand' => 'echo "custom error" && npm install', + 'adapter' => 'ssr', + ]); + $this->assertNotEmpty($siteId); + + $site = $this->getSite($siteId); + $this->assertEquals('200', $site['headers']['status-code']); + + $domain = $this->setupSiteDomain($siteId); + $this->assertNotEmpty($domain); + + $deployment = $this->createDeployment($siteId, [ + 'code' => $this->packageSite('astro-static'), + 'activate' => true + ]); + $this->assertEquals(202, $deployment['headers']['status-code']); + + $deploymentId = $deployment['body']['$id']; + $this->assertNotEmpty($deploymentId); + + $this->assertEventually(function () use ($siteId, $deploymentId) { + $deployment = $this->getDeployment($siteId, $deploymentId); + $this->assertEquals('failed', $deployment['body']['status'], 'Deployment status is failed, deployment: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT)); + }, 100000, 500); + + $deployment = $this->getDeployment($siteId, $deploymentId); + $this->assertEquals(200, $deployment['headers']['status-code']); + $this->assertStringContainsString('custom error', $deployment['body']['buildLogs']); + $this->assertStringContainsString('Adapter mismatch', $deployment['body']['buildLogs']); + + $this->cleanupSite($siteId); + } } From dde0dd221840eb3af211de14f975c46c5deefca2 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Tue, 20 May 2025 23:05:48 +0100 Subject: [PATCH 038/219] feat: add dev key to clients --- src/Appwrite/Platform/Tasks/Specs.php | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/Appwrite/Platform/Tasks/Specs.php b/src/Appwrite/Platform/Tasks/Specs.php index 76c9db079a..4876e8d96c 100644 --- a/src/Appwrite/Platform/Tasks/Specs.php +++ b/src/Appwrite/Platform/Tasks/Specs.php @@ -101,6 +101,12 @@ class Specs extends Action 'name' => 'X-Appwrite-Session', 'description' => 'The user session to authenticate with', 'in' => 'header', + ], + 'DevKey' => [ + 'type' => 'apiKey', + 'name' => 'X-Appwrite-Dev-Key', + 'description' => 'Your secret dev API key', + 'in' => 'header', ] ], APP_PLATFORM_SERVER => [ From ac8105dea2f6dabf3f62fb0ba114a49f8e2b2885 Mon Sep 17 00:00:00 2001 From: Steven Nguyen <stnguyen90@users.noreply.github.com> Date: Mon, 19 May 2025 16:21:31 -0700 Subject: [PATCH 039/219] Bump appwrite version to 1.7.2 --- README-CN.md | 6 +++--- README.md | 6 +++--- app/init/constants.php | 2 +- src/Appwrite/Migration/Migration.php | 2 ++ 4 files changed, 9 insertions(+), 7 deletions(-) diff --git a/README-CN.md b/README-CN.md index c79e0a1db4..811fe6435c 100644 --- a/README-CN.md +++ b/README-CN.md @@ -72,7 +72,7 @@ docker run -it --rm \ --volume /var/run/docker.sock:/var/run/docker.sock \ --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \ --entrypoint="install" \ - appwrite/appwrite:1.7.0 + appwrite/appwrite:1.7.2 ``` ### Windows @@ -84,7 +84,7 @@ docker run -it --rm ^ --volume //var/run/docker.sock:/var/run/docker.sock ^ --volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^ --entrypoint="install" ^ - appwrite/appwrite:1.7.0 + appwrite/appwrite:1.7.2 ``` #### PowerShell @@ -94,7 +94,7 @@ docker run -it --rm ` --volume /var/run/docker.sock:/var/run/docker.sock ` --volume ${pwd}/appwrite:/usr/src/code/appwrite:rw ` --entrypoint="install" ` - appwrite/appwrite:1.7.0 + appwrite/appwrite:1.7.2 ``` 运行后,可以在浏览器上访问 http://localhost 找到 Appwrite 控制台。在非 Linux 的本机主机上完成安装后,服务器可能需要几分钟才能启动。 diff --git a/README.md b/README.md index 435a2efd87..f29be0bd61 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ docker run -it --rm \ --volume /var/run/docker.sock:/var/run/docker.sock \ --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \ --entrypoint="install" \ - appwrite/appwrite:1.7.0 + appwrite/appwrite:1.7.2 ``` ### Windows @@ -90,7 +90,7 @@ docker run -it --rm ^ --volume //var/run/docker.sock:/var/run/docker.sock ^ --volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^ --entrypoint="install" ^ - appwrite/appwrite:1.7.0 + appwrite/appwrite:1.7.2 ``` #### PowerShell @@ -100,7 +100,7 @@ docker run -it --rm ` --volume /var/run/docker.sock:/var/run/docker.sock ` --volume ${pwd}/appwrite:/usr/src/code/appwrite:rw ` --entrypoint="install" ` - appwrite/appwrite:1.7.0 + appwrite/appwrite:1.7.2 ``` Once the Docker installation is complete, go to http://localhost to access the Appwrite console from your browser. Please note that on non-Linux native hosts, the server might take a few minutes to start after completing the installation. diff --git a/app/init/constants.php b/app/init/constants.php index 7686759719..86787e3bab 100644 --- a/app/init/constants.php +++ b/app/init/constants.php @@ -38,7 +38,7 @@ const APP_RESOURCE_TOKEN_ACCESS = 24 * 60 * 60; // 24 hours const APP_FILE_ACCESS = 24 * 60 * 60; // 24 hours const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours const APP_CACHE_BUSTER = 4319; -const APP_VERSION_STABLE = '1.7.0'; +const APP_VERSION_STABLE = '1.7.2'; const APP_DATABASE_ATTRIBUTE_EMAIL = 'email'; const APP_DATABASE_ATTRIBUTE_ENUM = 'enum'; const APP_DATABASE_ATTRIBUTE_IP = 'ip'; diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 0b1e462d8e..81ea1ef263 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -85,6 +85,8 @@ abstract class Migration '1.6.2' => 'V21', '1.7.0-RC1' => 'V22', '1.7.0' => 'V22', + '1.7.1' => 'V22', + '1.7.2' => 'V22', ]; /** From d30271875756c30e984e8bd88c99c796f88b4745 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Wed, 21 May 2025 05:19:31 +0000 Subject: [PATCH 040/219] chore: update sdks --- app/config/platforms.php | 14 +- app/config/specs/open-api3-1.7.x-client.json | 212 +++-- app/config/specs/open-api3-1.7.x-console.json | 756 ++++++++++-------- app/config/specs/open-api3-1.7.x-server.json | 546 +++++++------ app/config/specs/open-api3-latest-client.json | 212 +++-- .../specs/open-api3-latest-console.json | 756 ++++++++++-------- app/config/specs/open-api3-latest-server.json | 546 +++++++------ app/config/specs/swagger2-1.7.x-client.json | 208 +++-- app/config/specs/swagger2-1.7.x-console.json | 752 +++++++++-------- app/config/specs/swagger2-1.7.x-server.json | 542 +++++++------ app/config/specs/swagger2-latest-client.json | 208 +++-- app/config/specs/swagger2-latest-console.json | 752 +++++++++-------- app/config/specs/swagger2-latest-server.json | 542 +++++++------ .../java/databases/upsert-document.md | 26 + .../kotlin/databases/upsert-document.md | 17 + .../examples/databases/upsert-document.md | 16 + .../examples/databases/upsert-document.md | 15 + .../examples/databases/upsert-document.md | 17 + .../examples/databases/upsert-document.md | 17 + .../examples/databases/upsert-document.md | 12 + .../examples/databases/upsert-document.md | 17 + docs/sdks/flutter/CHANGELOG.md | 5 + 22 files changed, 3685 insertions(+), 2503 deletions(-) create mode 100644 docs/examples/1.7.x/client-android/java/databases/upsert-document.md create mode 100644 docs/examples/1.7.x/client-android/kotlin/databases/upsert-document.md create mode 100644 docs/examples/1.7.x/client-apple/examples/databases/upsert-document.md create mode 100644 docs/examples/1.7.x/client-flutter/examples/databases/upsert-document.md create mode 100644 docs/examples/1.7.x/client-graphql/examples/databases/upsert-document.md create mode 100644 docs/examples/1.7.x/client-react-native/examples/databases/upsert-document.md create mode 100644 docs/examples/1.7.x/client-rest/examples/databases/upsert-document.md create mode 100644 docs/examples/1.7.x/client-web/examples/databases/upsert-document.md diff --git a/app/config/platforms.php b/app/config/platforms.php index ac6c4a6214..11479f23ad 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -11,7 +11,7 @@ return [ [ 'key' => 'web', 'name' => 'Web', - 'version' => '18.0.0', + 'version' => '18.0.1', 'url' => 'https://github.com/appwrite/sdk-for-web', 'package' => 'https://www.npmjs.com/package/appwrite', 'enabled' => true, @@ -59,7 +59,7 @@ return [ [ 'key' => 'flutter', 'name' => 'Flutter', - 'version' => '16.0.0', + 'version' => '16.0.1', 'url' => 'https://github.com/appwrite/sdk-for-flutter', 'package' => 'https://pub.dev/packages/appwrite', 'enabled' => true, @@ -77,7 +77,7 @@ return [ [ 'key' => 'apple', 'name' => 'Apple', - 'version' => '10.0.0', + 'version' => '10.0.1', 'url' => 'https://github.com/appwrite/sdk-for-apple', 'package' => 'https://github.com/appwrite/sdk-for-apple', 'enabled' => true, @@ -112,7 +112,7 @@ return [ [ 'key' => 'android', 'name' => 'Android', - 'version' => '8.0.0', + 'version' => '8.0.1', 'url' => 'https://github.com/appwrite/sdk-for-android', 'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-android', 'enabled' => true, @@ -134,7 +134,7 @@ return [ [ 'key' => 'react-native', 'name' => 'React Native', - 'version' => '0.9.0', + 'version' => '0.9.1', 'url' => 'https://github.com/appwrite/sdk-for-react-native', 'package' => 'https://npmjs.com/package/react-native-appwrite', 'enabled' => true, @@ -199,7 +199,7 @@ return [ [ 'key' => 'web', 'name' => 'Console', - 'version' => '1.3.0', + 'version' => '1.7.0', 'url' => 'https://github.com/appwrite/sdk-for-console', 'package' => '', 'enabled' => true, @@ -353,7 +353,7 @@ return [ [ 'key' => 'dotnet', 'name' => '.NET', - 'version' => '0.15.0', + 'version' => '0.13.0', 'url' => 'https://github.com/appwrite/sdk-for-dotnet', 'package' => 'https://www.nuget.org/packages/Appwrite', 'enabled' => true, diff --git a/app/config/specs/open-api3-1.7.x-client.json b/app/config/specs/open-api3-1.7.x-client.json index 341eaa1eac..abeab8a56f 100644 --- a/app/config/specs/open-api3-1.7.x-client.json +++ b/app/config/specs/open-api3-1.7.x-client.json @@ -4490,29 +4490,6 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." - }, - { - "name": "createDocuments", - "auth": { - "Key": [] - }, - "parameters": [ - "databaseId", - "collectionId", - "documents" - ], - "required": [ - "databaseId", - "collectionId", - "documents" - ], - "responses": [ - { - "code": 201, - "model": "#\/components\/schemas\/documentList" - } - ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -4683,6 +4660,115 @@ } ] }, + "put": { + "summary": "Upsert document", + "operationId": "databasesUpsertDocument", + "tags": [ + "databases" + ], + "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "upsertDocument", + "group": "documents", + "weight": 114, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DOCUMENT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include all required attributes of the document to be created or updated.", + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "data" + ] + } + } + } + } + }, "patch": { "summary": "Update document", "operationId": "databasesUpdateDocument", @@ -4804,7 +4890,7 @@ "x-appwrite": { "method": "deleteDocument", "group": "documents", - "weight": 116, + "weight": 117, "cookies": false, "type": "", "deprecated": false, @@ -4888,7 +4974,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 391, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -4963,7 +5049,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 389, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -5078,7 +5164,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 390, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -5152,7 +5238,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 305, + "weight": 306, "cookies": false, "type": "graphql", "deprecated": false, @@ -5204,7 +5290,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 304, + "weight": 305, "cookies": false, "type": "graphql", "deprecated": false, @@ -5256,7 +5342,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 121, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -5308,7 +5394,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 122, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -5360,7 +5446,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 126, + "weight": 127, "cookies": false, "type": "", "deprecated": false, @@ -5412,7 +5498,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 123, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -5464,7 +5550,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 124, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -5516,7 +5602,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 125, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -5568,7 +5654,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 127, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -5620,7 +5706,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 128, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -5672,7 +5758,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 351, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -5755,7 +5841,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 355, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -5830,7 +5916,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 211, + "weight": 212, "cookies": false, "type": "", "deprecated": false, @@ -5916,7 +6002,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 210, + "weight": 211, "cookies": false, "type": "upload", "deprecated": false, @@ -6014,7 +6100,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 212, + "weight": 213, "cookies": false, "type": "", "deprecated": false, @@ -6086,7 +6172,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 217, + "weight": 218, "cookies": false, "type": "", "deprecated": false, @@ -6175,7 +6261,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 218, + "weight": 219, "cookies": false, "type": "", "deprecated": false, @@ -6242,7 +6328,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 214, + "weight": 215, "cookies": false, "type": "location", "deprecated": false, @@ -6320,7 +6406,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 213, + "weight": 214, "cookies": false, "type": "location", "deprecated": false, @@ -6547,7 +6633,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 215, + "weight": 216, "cookies": false, "type": "location", "deprecated": false, @@ -6632,7 +6718,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 222, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -6708,7 +6794,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 221, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -6793,7 +6879,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 223, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -6855,7 +6941,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 225, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -6929,7 +7015,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 227, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -6993,7 +7079,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 229, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -7079,7 +7165,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 228, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -7190,7 +7276,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 230, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -7262,7 +7348,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 231, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -7349,7 +7435,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 233, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -7423,7 +7509,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 232, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -7521,7 +7607,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 224, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -7582,7 +7668,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 226, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -9775,6 +9861,12 @@ "name": "X-Appwrite-Session", "description": "The user session to authenticate with", "in": "header" + }, + "DevKey": { + "type": "apiKey", + "name": "X-Appwrite-Dev-Key", + "description": "Your secret dev API key", + "in": "header" } } }, diff --git a/app/config/specs/open-api3-1.7.x-console.json b/app/config/specs/open-api3-1.7.x-console.json index 6c003e8283..19ce78915c 100644 --- a/app/config/specs/open-api3-1.7.x-console.json +++ b/app/config/specs/open-api3-1.7.x-console.json @@ -4359,7 +4359,7 @@ "x-appwrite": { "method": "chat", "group": "console", - "weight": 307, + "weight": 308, "cookies": false, "type": "", "deprecated": false, @@ -4419,7 +4419,7 @@ "x-appwrite": { "method": "getResource", "group": null, - "weight": 431, + "weight": 432, "cookies": false, "type": "", "deprecated": false, @@ -4494,7 +4494,7 @@ "x-appwrite": { "method": "variables", "group": "console", - "weight": 306, + "weight": 307, "cookies": false, "type": "", "deprecated": false, @@ -4694,7 +4694,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 118, + "weight": 119, "cookies": false, "type": "", "deprecated": false, @@ -8049,29 +8049,6 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." - }, - { - "name": "createDocuments", - "auth": { - "Key": [] - }, - "parameters": [ - "databaseId", - "collectionId", - "documents" - ], - "required": [ - "databaseId", - "collectionId", - "documents" - ], - "responses": [ - { - "code": 201, - "model": "#\/components\/schemas\/documentList" - } - ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -8167,7 +8144,7 @@ "x-appwrite": { "method": "upsertDocuments", "group": "documents", - "weight": 115, + "weight": 116, "cookies": false, "type": "", "deprecated": false, @@ -8255,7 +8232,7 @@ "x-appwrite": { "method": "updateDocuments", "group": "documents", - "weight": 114, + "weight": 115, "cookies": false, "type": "", "deprecated": false, @@ -8348,7 +8325,7 @@ "x-appwrite": { "method": "deleteDocuments", "group": "documents", - "weight": 117, + "weight": 118, "cookies": false, "type": "", "deprecated": false, @@ -8511,6 +8488,115 @@ } ] }, + "put": { + "summary": "Upsert document", + "operationId": "databasesUpsertDocument", + "tags": [ + "databases" + ], + "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "upsertDocument", + "group": "documents", + "weight": 114, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DOCUMENT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include all required attributes of the document to be created or updated.", + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "data" + ] + } + } + } + } + }, "patch": { "summary": "Update document", "operationId": "databasesUpdateDocument", @@ -8632,7 +8718,7 @@ "x-appwrite": { "method": "deleteDocument", "group": "documents", - "weight": 116, + "weight": 117, "cookies": false, "type": "", "deprecated": false, @@ -9253,7 +9339,7 @@ "x-appwrite": { "method": "getCollectionUsage", "group": null, - "weight": 120, + "weight": 121, "cookies": false, "type": "", "deprecated": false, @@ -9418,7 +9504,7 @@ "x-appwrite": { "method": "getDatabaseUsage", "group": null, - "weight": 119, + "weight": 120, "cookies": false, "type": "", "deprecated": false, @@ -9500,7 +9586,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 375, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -9573,7 +9659,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 372, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -9804,7 +9890,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 377, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -9853,7 +9939,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 378, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -9903,7 +9989,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 401, + "weight": 402, "cookies": false, "type": "", "deprecated": false, @@ -10003,7 +10089,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 400, + "weight": 401, "cookies": false, "type": "", "deprecated": false, @@ -10063,7 +10149,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 394, + "weight": 395, "cookies": false, "type": "", "deprecated": false, @@ -10135,7 +10221,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 373, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -10194,7 +10280,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 374, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -10422,7 +10508,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 376, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -10483,7 +10569,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 381, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -10563,7 +10649,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 382, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -10646,7 +10732,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 379, + "weight": 380, "cookies": false, "type": "upload", "deprecated": false, @@ -10742,7 +10828,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 387, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -10827,7 +10913,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 384, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -10930,7 +11016,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 385, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -11027,7 +11113,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 380, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -11089,7 +11175,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 383, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -11153,7 +11239,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 386, + "weight": 387, "cookies": false, "type": "location", "deprecated": false, @@ -11243,7 +11329,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 388, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -11314,7 +11400,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 391, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -11389,7 +11475,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 389, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -11504,7 +11590,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 390, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -11569,7 +11655,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 392, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -11640,7 +11726,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 393, + "weight": 394, "cookies": false, "type": "", "deprecated": false, @@ -11722,7 +11808,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 397, + "weight": 398, "cookies": false, "type": "", "deprecated": false, @@ -11781,7 +11867,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 395, + "weight": 396, "cookies": false, "type": "", "deprecated": false, @@ -11872,7 +11958,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 396, + "weight": 397, "cookies": false, "type": "", "deprecated": false, @@ -11941,7 +12027,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 398, + "weight": 399, "cookies": false, "type": "", "deprecated": false, @@ -12032,7 +12118,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 399, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -12103,7 +12189,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 305, + "weight": 306, "cookies": false, "type": "graphql", "deprecated": false, @@ -12155,7 +12241,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 304, + "weight": 305, "cookies": false, "type": "graphql", "deprecated": false, @@ -12207,7 +12293,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 129, + "weight": 130, "cookies": false, "type": "", "deprecated": false, @@ -12256,7 +12342,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 150, + "weight": 151, "cookies": false, "type": "", "deprecated": false, @@ -12305,7 +12391,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 132, + "weight": 133, "cookies": false, "type": "", "deprecated": false, @@ -12354,7 +12440,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 137, + "weight": 138, "cookies": false, "type": "", "deprecated": false, @@ -12414,7 +12500,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 131, + "weight": 132, "cookies": false, "type": "", "deprecated": false, @@ -12463,7 +12549,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 133, + "weight": 134, "cookies": false, "type": "", "deprecated": false, @@ -12512,7 +12598,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 139, + "weight": 140, "cookies": false, "type": "", "deprecated": false, @@ -12574,7 +12660,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 138, + "weight": 139, "cookies": false, "type": "", "deprecated": false, @@ -12636,7 +12722,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 140, + "weight": 141, "cookies": false, "type": "", "deprecated": false, @@ -12709,7 +12795,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 141, + "weight": 142, "cookies": false, "type": "", "deprecated": false, @@ -12771,7 +12857,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 151, + "weight": 152, "cookies": false, "type": "", "deprecated": false, @@ -12859,7 +12945,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 145, + "weight": 146, "cookies": false, "type": "", "deprecated": false, @@ -12921,7 +13007,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 136, + "weight": 137, "cookies": false, "type": "", "deprecated": false, @@ -12983,7 +13069,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 142, + "weight": 143, "cookies": false, "type": "", "deprecated": false, @@ -13045,7 +13131,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 143, + "weight": 144, "cookies": false, "type": "", "deprecated": false, @@ -13107,7 +13193,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 144, + "weight": 145, "cookies": false, "type": "", "deprecated": false, @@ -13169,7 +13255,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 146, + "weight": 147, "cookies": false, "type": "", "deprecated": false, @@ -13231,7 +13317,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 147, + "weight": 148, "cookies": false, "type": "", "deprecated": false, @@ -13293,7 +13379,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 135, + "weight": 136, "cookies": false, "type": "", "deprecated": false, @@ -13355,7 +13441,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 149, + "weight": 150, "cookies": false, "type": "", "deprecated": false, @@ -13404,7 +13490,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 148, + "weight": 149, "cookies": false, "type": "", "deprecated": false, @@ -13453,7 +13539,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 134, + "weight": 135, "cookies": false, "type": "", "deprecated": false, @@ -13502,7 +13588,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 121, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -13554,7 +13640,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 122, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -13606,7 +13692,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 126, + "weight": 127, "cookies": false, "type": "", "deprecated": false, @@ -13658,7 +13744,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 123, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -13710,7 +13796,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 124, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -13762,7 +13848,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 125, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -13814,7 +13900,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 127, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -13866,7 +13952,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 128, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -13918,7 +14004,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 359, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -13994,7 +14080,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 356, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -14138,7 +14224,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 363, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -14284,7 +14370,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 358, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -14458,7 +14544,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 365, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -14636,7 +14722,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 357, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -14745,7 +14831,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 364, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -14857,7 +14943,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 362, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -14910,7 +14996,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 366, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -14972,7 +15058,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 360, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -15047,7 +15133,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 361, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -15122,7 +15208,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 331, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -15198,7 +15284,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 330, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -15303,7 +15389,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 343, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -15411,7 +15497,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 329, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -15496,7 +15582,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 342, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -15584,7 +15670,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 321, + "weight": 322, "cookies": false, "type": "", "deprecated": false, @@ -15699,7 +15785,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 334, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -15817,7 +15903,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 324, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -15912,7 +15998,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 337, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -16010,7 +16096,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 322, + "weight": 323, "cookies": false, "type": "", "deprecated": false, @@ -16115,7 +16201,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 335, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -16223,7 +16309,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 323, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -16366,7 +16452,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 336, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -16511,7 +16597,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 325, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -16606,7 +16692,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 338, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -16704,7 +16790,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 326, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -16799,7 +16885,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 339, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -16897,7 +16983,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 327, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -16992,7 +17078,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 340, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -17090,7 +17176,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 328, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -17185,7 +17271,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 341, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -17283,7 +17369,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 333, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -17336,7 +17422,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 344, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -17398,7 +17484,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 332, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -17473,7 +17559,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 353, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -17548,7 +17634,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 346, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -17622,7 +17708,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 345, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -17705,7 +17791,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 348, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -17765,7 +17851,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 349, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -17842,7 +17928,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 350, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -17904,7 +17990,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 347, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -17979,7 +18065,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 352, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -18063,7 +18149,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 351, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -18153,7 +18239,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 354, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -18216,7 +18302,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 355, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -18291,7 +18377,7 @@ "x-appwrite": { "method": "list", "group": null, - "weight": 313, + "weight": 314, "cookies": false, "type": "", "deprecated": false, @@ -18365,7 +18451,7 @@ "x-appwrite": { "method": "createAppwriteMigration", "group": null, - "weight": 308, + "weight": 309, "cookies": false, "type": "", "deprecated": false, @@ -18453,7 +18539,7 @@ "x-appwrite": { "method": "getAppwriteReport", "group": null, - "weight": 315, + "weight": 316, "cookies": false, "type": "", "deprecated": false, @@ -18546,7 +18632,7 @@ "x-appwrite": { "method": "createCsvMigration", "group": null, - "weight": 312, + "weight": 313, "cookies": false, "type": "", "deprecated": false, @@ -18625,7 +18711,7 @@ "x-appwrite": { "method": "createFirebaseMigration", "group": null, - "weight": 309, + "weight": 310, "cookies": false, "type": "", "deprecated": false, @@ -18701,7 +18787,7 @@ "x-appwrite": { "method": "getFirebaseReport", "group": null, - "weight": 316, + "weight": 317, "cookies": false, "type": "", "deprecated": false, @@ -18773,7 +18859,7 @@ "x-appwrite": { "method": "createNHostMigration", "group": null, - "weight": 311, + "weight": 312, "cookies": false, "type": "", "deprecated": false, @@ -18884,7 +18970,7 @@ "x-appwrite": { "method": "getNHostReport", "group": null, - "weight": 318, + "weight": 319, "cookies": false, "type": "", "deprecated": false, @@ -19017,7 +19103,7 @@ "x-appwrite": { "method": "createSupabaseMigration", "group": null, - "weight": 310, + "weight": 311, "cookies": false, "type": "", "deprecated": false, @@ -19122,7 +19208,7 @@ "x-appwrite": { "method": "getSupabaseReport", "group": null, - "weight": 317, + "weight": 318, "cookies": false, "type": "", "deprecated": false, @@ -19246,7 +19332,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 314, + "weight": 315, "cookies": false, "type": "", "deprecated": false, @@ -19304,7 +19390,7 @@ "x-appwrite": { "method": "retry", "group": null, - "weight": 319, + "weight": 320, "cookies": false, "type": "", "deprecated": false, @@ -19355,7 +19441,7 @@ "x-appwrite": { "method": "delete", "group": null, - "weight": 320, + "weight": 321, "cookies": false, "type": "", "deprecated": false, @@ -19415,7 +19501,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 199, + "weight": 200, "cookies": false, "type": "", "deprecated": false, @@ -19503,7 +19589,7 @@ "x-appwrite": { "method": "listVariables", "group": null, - "weight": 201, + "weight": 202, "cookies": false, "type": "", "deprecated": false, @@ -19549,7 +19635,7 @@ "x-appwrite": { "method": "createVariable", "group": null, - "weight": 200, + "weight": 201, "cookies": false, "type": "", "deprecated": false, @@ -19627,7 +19713,7 @@ "x-appwrite": { "method": "getVariable", "group": null, - "weight": 202, + "weight": 203, "cookies": false, "type": "", "deprecated": false, @@ -19685,7 +19771,7 @@ "x-appwrite": { "method": "updateVariable", "group": null, - "weight": 203, + "weight": 204, "cookies": false, "type": "", "deprecated": false, @@ -19765,7 +19851,7 @@ "x-appwrite": { "method": "deleteVariable", "group": null, - "weight": 204, + "weight": 205, "cookies": false, "type": "", "deprecated": false, @@ -19825,7 +19911,7 @@ "x-appwrite": { "method": "list", "group": "projects", - "weight": 154, + "weight": 155, "cookies": false, "type": "", "deprecated": false, @@ -19897,7 +19983,7 @@ "x-appwrite": { "method": "create", "group": "projects", - "weight": 153, + "weight": 154, "cookies": false, "type": "", "deprecated": false, @@ -20031,7 +20117,7 @@ "x-appwrite": { "method": "get", "group": "projects", - "weight": 155, + "weight": 156, "cookies": false, "type": "", "deprecated": false, @@ -20089,7 +20175,7 @@ "x-appwrite": { "method": "update", "group": "projects", - "weight": 156, + "weight": 157, "cookies": false, "type": "", "deprecated": false, @@ -20204,7 +20290,7 @@ "x-appwrite": { "method": "delete", "group": "projects", - "weight": 173, + "weight": 174, "cookies": false, "type": "", "deprecated": false, @@ -20264,7 +20350,7 @@ "x-appwrite": { "method": "updateApiStatus", "group": "projects", - "weight": 160, + "weight": 161, "cookies": false, "type": "", "deprecated": false, @@ -20356,7 +20442,7 @@ "x-appwrite": { "method": "updateApiStatusAll", "group": "projects", - "weight": 161, + "weight": 162, "cookies": false, "type": "", "deprecated": false, @@ -20435,7 +20521,7 @@ "x-appwrite": { "method": "updateAuthDuration", "group": "auth", - "weight": 166, + "weight": 167, "cookies": false, "type": "", "deprecated": false, @@ -20514,7 +20600,7 @@ "x-appwrite": { "method": "updateAuthLimit", "group": "auth", - "weight": 165, + "weight": 166, "cookies": false, "type": "", "deprecated": false, @@ -20593,7 +20679,7 @@ "x-appwrite": { "method": "updateAuthSessionsLimit", "group": "auth", - "weight": 171, + "weight": 172, "cookies": false, "type": "", "deprecated": false, @@ -20672,7 +20758,7 @@ "x-appwrite": { "method": "updateMembershipsPrivacy", "group": "auth", - "weight": 164, + "weight": 165, "cookies": false, "type": "", "deprecated": false, @@ -20763,7 +20849,7 @@ "x-appwrite": { "method": "updateMockNumbers", "group": "auth", - "weight": 172, + "weight": 173, "cookies": false, "type": "", "deprecated": false, @@ -20845,7 +20931,7 @@ "x-appwrite": { "method": "updateAuthPasswordDictionary", "group": "auth", - "weight": 169, + "weight": 170, "cookies": false, "type": "", "deprecated": false, @@ -20924,7 +21010,7 @@ "x-appwrite": { "method": "updateAuthPasswordHistory", "group": "auth", - "weight": 168, + "weight": 169, "cookies": false, "type": "", "deprecated": false, @@ -21003,7 +21089,7 @@ "x-appwrite": { "method": "updatePersonalDataCheck", "group": "auth", - "weight": 170, + "weight": 171, "cookies": false, "type": "", "deprecated": false, @@ -21082,7 +21168,7 @@ "x-appwrite": { "method": "updateSessionAlerts", "group": "auth", - "weight": 163, + "weight": 164, "cookies": false, "type": "", "deprecated": false, @@ -21161,7 +21247,7 @@ "x-appwrite": { "method": "updateAuthStatus", "group": "auth", - "weight": 167, + "weight": 168, "cookies": false, "type": "", "deprecated": false, @@ -21261,7 +21347,7 @@ "x-appwrite": { "method": "listDevKeys", "group": "devKeys", - "weight": 370, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -21329,7 +21415,7 @@ "x-appwrite": { "method": "createDevKey", "group": "devKeys", - "weight": 367, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -21414,7 +21500,7 @@ "x-appwrite": { "method": "getDevKey", "group": "devKeys", - "weight": 369, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -21482,7 +21568,7 @@ "x-appwrite": { "method": "updateDevKey", "group": "devKeys", - "weight": 368, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -21568,7 +21654,7 @@ "x-appwrite": { "method": "deleteDevKey", "group": "devKeys", - "weight": 371, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -21638,7 +21724,7 @@ "x-appwrite": { "method": "createJWT", "group": "auth", - "weight": 185, + "weight": 186, "cookies": false, "type": "", "deprecated": false, @@ -21725,7 +21811,7 @@ "x-appwrite": { "method": "listKeys", "group": "keys", - "weight": 181, + "weight": 182, "cookies": false, "type": "", "deprecated": false, @@ -21783,7 +21869,7 @@ "x-appwrite": { "method": "createKey", "group": "keys", - "weight": 180, + "weight": 181, "cookies": false, "type": "", "deprecated": false, @@ -21876,7 +21962,7 @@ "x-appwrite": { "method": "getKey", "group": "keys", - "weight": 182, + "weight": 183, "cookies": false, "type": "", "deprecated": false, @@ -21944,7 +22030,7 @@ "x-appwrite": { "method": "updateKey", "group": "keys", - "weight": 183, + "weight": 184, "cookies": false, "type": "", "deprecated": false, @@ -22038,7 +22124,7 @@ "x-appwrite": { "method": "deleteKey", "group": "keys", - "weight": 184, + "weight": 185, "cookies": false, "type": "", "deprecated": false, @@ -22108,7 +22194,7 @@ "x-appwrite": { "method": "updateOAuth2", "group": "auth", - "weight": 162, + "weight": 163, "cookies": false, "type": "", "deprecated": false, @@ -22246,7 +22332,7 @@ "x-appwrite": { "method": "listPlatforms", "group": "platforms", - "weight": 187, + "weight": 188, "cookies": false, "type": "", "deprecated": false, @@ -22304,7 +22390,7 @@ "x-appwrite": { "method": "createPlatform", "group": "platforms", - "weight": 186, + "weight": 187, "cookies": false, "type": "", "deprecated": false, @@ -22423,7 +22509,7 @@ "x-appwrite": { "method": "getPlatform", "group": "platforms", - "weight": 188, + "weight": 189, "cookies": false, "type": "", "deprecated": false, @@ -22491,7 +22577,7 @@ "x-appwrite": { "method": "updatePlatform", "group": "platforms", - "weight": 189, + "weight": 190, "cookies": false, "type": "", "deprecated": false, @@ -22586,7 +22672,7 @@ "x-appwrite": { "method": "deletePlatform", "group": "platforms", - "weight": 190, + "weight": 191, "cookies": false, "type": "", "deprecated": false, @@ -22656,7 +22742,7 @@ "x-appwrite": { "method": "updateServiceStatus", "group": "projects", - "weight": 158, + "weight": 159, "cookies": false, "type": "", "deprecated": false, @@ -22757,7 +22843,7 @@ "x-appwrite": { "method": "updateServiceStatusAll", "group": "projects", - "weight": 159, + "weight": 160, "cookies": false, "type": "", "deprecated": false, @@ -22836,7 +22922,7 @@ "x-appwrite": { "method": "updateSmtp", "group": "templates", - "weight": 191, + "weight": 192, "cookies": false, "type": "", "deprecated": false, @@ -22954,7 +23040,7 @@ "x-appwrite": { "method": "createSmtpTest", "group": "templates", - "weight": 192, + "weight": 193, "cookies": false, "type": "", "deprecated": false, @@ -23085,7 +23171,7 @@ "x-appwrite": { "method": "updateTeam", "group": "projects", - "weight": 157, + "weight": 158, "cookies": false, "type": "", "deprecated": false, @@ -23164,7 +23250,7 @@ "x-appwrite": { "method": "getEmailTemplate", "group": "templates", - "weight": 194, + "weight": 195, "cookies": false, "type": "", "deprecated": false, @@ -23388,7 +23474,7 @@ "x-appwrite": { "method": "updateEmailTemplate", "group": "templates", - "weight": 196, + "weight": 197, "cookies": false, "type": "", "deprecated": false, @@ -23652,7 +23738,7 @@ "x-appwrite": { "method": "deleteEmailTemplate", "group": "templates", - "weight": 198, + "weight": 199, "cookies": false, "type": "", "deprecated": false, @@ -23878,7 +23964,7 @@ "x-appwrite": { "method": "getSmsTemplate", "group": "templates", - "weight": 193, + "weight": 194, "cookies": false, "type": "", "deprecated": false, @@ -24099,7 +24185,7 @@ "x-appwrite": { "method": "updateSmsTemplate", "group": "templates", - "weight": 195, + "weight": 196, "cookies": false, "type": "", "deprecated": false, @@ -24339,7 +24425,7 @@ "x-appwrite": { "method": "deleteSmsTemplate", "group": "templates", - "weight": 197, + "weight": 198, "cookies": false, "type": "", "deprecated": false, @@ -24562,7 +24648,7 @@ "x-appwrite": { "method": "listWebhooks", "group": "webhooks", - "weight": 175, + "weight": 176, "cookies": false, "type": "", "deprecated": false, @@ -24620,7 +24706,7 @@ "x-appwrite": { "method": "createWebhook", "group": "webhooks", - "weight": 174, + "weight": 175, "cookies": false, "type": "", "deprecated": false, @@ -24735,7 +24821,7 @@ "x-appwrite": { "method": "getWebhook", "group": "webhooks", - "weight": 176, + "weight": 177, "cookies": false, "type": "", "deprecated": false, @@ -24803,7 +24889,7 @@ "x-appwrite": { "method": "updateWebhook", "group": "webhooks", - "weight": 177, + "weight": 178, "cookies": false, "type": "", "deprecated": false, @@ -24919,7 +25005,7 @@ "x-appwrite": { "method": "deleteWebhook", "group": "webhooks", - "weight": 179, + "weight": 180, "cookies": false, "type": "", "deprecated": false, @@ -24989,7 +25075,7 @@ "x-appwrite": { "method": "updateWebhookSignature", "group": "webhooks", - "weight": 178, + "weight": 179, "cookies": false, "type": "", "deprecated": false, @@ -25059,7 +25145,7 @@ "x-appwrite": { "method": "listRules", "group": null, - "weight": 291, + "weight": 292, "cookies": false, "type": "", "deprecated": false, @@ -25133,7 +25219,7 @@ "x-appwrite": { "method": "createAPIRule", "group": null, - "weight": 432, + "weight": 433, "cookies": false, "type": "", "deprecated": false, @@ -25200,7 +25286,7 @@ "x-appwrite": { "method": "createFunctionRule", "group": null, - "weight": 434, + "weight": 435, "cookies": false, "type": "", "deprecated": false, @@ -25278,7 +25364,7 @@ "x-appwrite": { "method": "createRedirectRule", "group": null, - "weight": 435, + "weight": 436, "cookies": false, "type": "", "deprecated": false, @@ -25370,7 +25456,7 @@ "x-appwrite": { "method": "createSiteRule", "group": null, - "weight": 433, + "weight": 434, "cookies": false, "type": "", "deprecated": false, @@ -25448,7 +25534,7 @@ "x-appwrite": { "method": "getRule", "group": null, - "weight": 292, + "weight": 293, "cookies": false, "type": "", "deprecated": false, @@ -25499,7 +25585,7 @@ "x-appwrite": { "method": "deleteRule", "group": null, - "weight": 293, + "weight": 294, "cookies": false, "type": "", "deprecated": false, @@ -25559,7 +25645,7 @@ "x-appwrite": { "method": "updateRuleVerification", "group": null, - "weight": 294, + "weight": 295, "cookies": false, "type": "", "deprecated": false, @@ -25619,7 +25705,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 404, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -25689,7 +25775,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 402, + "weight": 403, "cookies": false, "type": "", "deprecated": false, @@ -25936,7 +26022,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 407, + "weight": 408, "cookies": false, "type": "", "deprecated": false, @@ -25985,7 +26071,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 430, + "weight": 431, "cookies": false, "type": "", "deprecated": false, @@ -26035,7 +26121,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 426, + "weight": 427, "cookies": false, "type": "", "deprecated": false, @@ -26135,7 +26221,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 427, + "weight": 428, "cookies": false, "type": "", "deprecated": false, @@ -26195,7 +26281,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 428, + "weight": 429, "cookies": false, "type": "", "deprecated": false, @@ -26267,7 +26353,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 403, + "weight": 404, "cookies": false, "type": "", "deprecated": false, @@ -26326,7 +26412,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 405, + "weight": 406, "cookies": false, "type": "", "deprecated": false, @@ -26569,7 +26655,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 406, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -26630,7 +26716,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 413, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -26710,7 +26796,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 412, + "weight": 413, "cookies": false, "type": "", "deprecated": false, @@ -26793,7 +26879,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 408, + "weight": 409, "cookies": false, "type": "upload", "deprecated": false, @@ -26894,7 +26980,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 416, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -26974,7 +27060,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 409, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -27077,7 +27163,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 410, + "weight": 411, "cookies": false, "type": "", "deprecated": false, @@ -27175,7 +27261,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 411, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -27237,7 +27323,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 414, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -27301,7 +27387,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 415, + "weight": 416, "cookies": false, "type": "location", "deprecated": false, @@ -27391,7 +27477,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 417, + "weight": 418, "cookies": false, "type": "", "deprecated": false, @@ -27462,7 +27548,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 419, + "weight": 420, "cookies": false, "type": "", "deprecated": false, @@ -27533,7 +27619,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 418, + "weight": 419, "cookies": false, "type": "", "deprecated": false, @@ -27595,7 +27681,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 420, + "weight": 421, "cookies": false, "type": "", "deprecated": false, @@ -27666,7 +27752,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 429, + "weight": 430, "cookies": false, "type": "", "deprecated": false, @@ -27748,7 +27834,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 423, + "weight": 424, "cookies": false, "type": "", "deprecated": false, @@ -27807,7 +27893,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 421, + "weight": 422, "cookies": false, "type": "", "deprecated": false, @@ -27898,7 +27984,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 422, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -27967,7 +28053,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 424, + "weight": 425, "cookies": false, "type": "", "deprecated": false, @@ -28058,7 +28144,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 425, + "weight": 426, "cookies": false, "type": "", "deprecated": false, @@ -28129,7 +28215,7 @@ "x-appwrite": { "method": "listBuckets", "group": "buckets", - "weight": 206, + "weight": 207, "cookies": false, "type": "", "deprecated": false, @@ -28202,7 +28288,7 @@ "x-appwrite": { "method": "createBucket", "group": "buckets", - "weight": 205, + "weight": 206, "cookies": false, "type": "", "deprecated": false, @@ -28329,7 +28415,7 @@ "x-appwrite": { "method": "getBucket", "group": "buckets", - "weight": 207, + "weight": 208, "cookies": false, "type": "", "deprecated": false, @@ -28388,7 +28474,7 @@ "x-appwrite": { "method": "updateBucket", "group": "buckets", - "weight": 208, + "weight": 209, "cookies": false, "type": "", "deprecated": false, @@ -28512,7 +28598,7 @@ "x-appwrite": { "method": "deleteBucket", "group": "buckets", - "weight": 209, + "weight": 210, "cookies": false, "type": "", "deprecated": false, @@ -28573,7 +28659,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 211, + "weight": 212, "cookies": false, "type": "", "deprecated": false, @@ -28659,7 +28745,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 210, + "weight": 211, "cookies": false, "type": "upload", "deprecated": false, @@ -28757,7 +28843,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 212, + "weight": 213, "cookies": false, "type": "", "deprecated": false, @@ -28829,7 +28915,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 217, + "weight": 218, "cookies": false, "type": "", "deprecated": false, @@ -28918,7 +29004,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 218, + "weight": 219, "cookies": false, "type": "", "deprecated": false, @@ -28985,7 +29071,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 214, + "weight": 215, "cookies": false, "type": "location", "deprecated": false, @@ -29063,7 +29149,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 213, + "weight": 214, "cookies": false, "type": "location", "deprecated": false, @@ -29290,7 +29376,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 215, + "weight": 216, "cookies": false, "type": "location", "deprecated": false, @@ -29375,7 +29461,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 219, + "weight": 220, "cookies": false, "type": "", "deprecated": false, @@ -29447,7 +29533,7 @@ "x-appwrite": { "method": "getBucketUsage", "group": null, - "weight": 220, + "weight": 221, "cookies": false, "type": "", "deprecated": false, @@ -29529,7 +29615,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 222, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -29605,7 +29691,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 221, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -29690,7 +29776,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 223, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -29752,7 +29838,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 225, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -29826,7 +29912,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 227, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -29890,7 +29976,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 234, + "weight": 235, "cookies": false, "type": "", "deprecated": false, @@ -29963,7 +30049,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 229, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -30049,7 +30135,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 228, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -30160,7 +30246,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 230, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -30232,7 +30318,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 231, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -30319,7 +30405,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 233, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -30393,7 +30479,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 232, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -30490,7 +30576,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 224, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -30550,7 +30636,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 226, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -30631,7 +30717,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 438, + "weight": 439, "cookies": false, "type": "", "deprecated": false, @@ -30711,7 +30797,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 436, + "weight": 437, "cookies": false, "type": "", "deprecated": false, @@ -30800,7 +30886,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 437, + "weight": 438, "cookies": false, "type": "", "deprecated": false, @@ -30860,7 +30946,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 439, + "weight": 440, "cookies": false, "type": "", "deprecated": false, @@ -30930,7 +31016,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 440, + "weight": 441, "cookies": false, "type": "", "deprecated": false, @@ -30992,7 +31078,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 244, + "weight": 245, "cookies": false, "type": "", "deprecated": false, @@ -31065,7 +31151,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 235, + "weight": 236, "cookies": false, "type": "", "deprecated": false, @@ -31153,7 +31239,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 238, + "weight": 239, "cookies": false, "type": "", "deprecated": false, @@ -31238,7 +31324,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 236, + "weight": 237, "cookies": false, "type": "", "deprecated": false, @@ -31323,7 +31409,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 252, + "weight": 253, "cookies": false, "type": "", "deprecated": false, @@ -31391,7 +31477,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 275, + "weight": 276, "cookies": false, "type": "", "deprecated": false, @@ -31452,7 +31538,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 237, + "weight": 238, "cookies": false, "type": "", "deprecated": false, @@ -31537,7 +31623,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 240, + "weight": 241, "cookies": false, "type": "", "deprecated": false, @@ -31622,7 +31708,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 241, + "weight": 242, "cookies": false, "type": "", "deprecated": false, @@ -31737,7 +31823,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 242, + "weight": 243, "cookies": false, "type": "", "deprecated": false, @@ -31840,7 +31926,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 239, + "weight": 240, "cookies": false, "type": "", "deprecated": false, @@ -31945,7 +32031,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 277, + "weight": 278, "cookies": false, "type": "", "deprecated": false, @@ -32017,7 +32103,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 245, + "weight": 246, "cookies": false, "type": "", "deprecated": false, @@ -32069,7 +32155,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 273, + "weight": 274, "cookies": false, "type": "", "deprecated": false, @@ -32130,7 +32216,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 258, + "weight": 259, "cookies": false, "type": "", "deprecated": false, @@ -32210,7 +32296,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 276, + "weight": 277, "cookies": false, "type": "", "deprecated": false, @@ -32292,7 +32378,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 254, + "weight": 255, "cookies": false, "type": "", "deprecated": false, @@ -32375,7 +32461,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 250, + "weight": 251, "cookies": false, "type": "", "deprecated": false, @@ -32449,7 +32535,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 249, + "weight": 250, "cookies": false, "type": "", "deprecated": false, @@ -32534,7 +32620,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 263, + "weight": 264, "cookies": false, "type": "", "deprecated": false, @@ -32607,7 +32693,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 268, + "weight": 269, "cookies": false, "type": "", "deprecated": false, @@ -32683,7 +32769,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 264, + "weight": 265, "cookies": false, "type": "", "deprecated": false, @@ -32744,7 +32830,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 265, + "weight": 266, "cookies": false, "type": "", "deprecated": false, @@ -32803,7 +32889,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 267, + "weight": 268, "cookies": false, "type": "", "deprecated": false, @@ -32862,7 +32948,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 266, + "weight": 267, "cookies": false, "type": "", "deprecated": false, @@ -32923,7 +33009,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 256, + "weight": 257, "cookies": false, "type": "", "deprecated": false, @@ -33003,7 +33089,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 257, + "weight": 258, "cookies": false, "type": "", "deprecated": false, @@ -33083,7 +33169,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 259, + "weight": 260, "cookies": false, "type": "", "deprecated": false, @@ -33163,7 +33249,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 246, + "weight": 247, "cookies": false, "type": "", "deprecated": false, @@ -33222,7 +33308,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 261, + "weight": 262, "cookies": false, "type": "", "deprecated": false, @@ -33302,7 +33388,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 248, + "weight": 249, "cookies": false, "type": "", "deprecated": false, @@ -33361,7 +33447,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 269, + "weight": 270, "cookies": false, "type": "", "deprecated": false, @@ -33413,7 +33499,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 272, + "weight": 273, "cookies": false, "type": "", "deprecated": false, @@ -33467,7 +33553,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 271, + "weight": 272, "cookies": false, "type": "", "deprecated": false, @@ -33538,7 +33624,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 253, + "weight": 254, "cookies": false, "type": "", "deprecated": false, @@ -33618,7 +33704,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 251, + "weight": 252, "cookies": false, "type": "", "deprecated": false, @@ -33691,7 +33777,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 243, + "weight": 244, "cookies": false, "type": "", "deprecated": false, @@ -33801,7 +33887,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 247, + "weight": 248, "cookies": false, "type": "", "deprecated": false, @@ -33871,7 +33957,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 262, + "weight": 263, "cookies": false, "type": "", "deprecated": false, @@ -33960,7 +34046,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 274, + "weight": 275, "cookies": false, "type": "", "deprecated": false, @@ -34032,7 +34118,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 270, + "weight": 271, "cookies": false, "type": "", "deprecated": false, @@ -34114,7 +34200,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 260, + "weight": 261, "cookies": false, "type": "", "deprecated": false, @@ -34194,7 +34280,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 255, + "weight": 256, "cookies": false, "type": "", "deprecated": false, @@ -34274,7 +34360,7 @@ "x-appwrite": { "method": "createRepositoryDetection", "group": "repositories", - "weight": 281, + "weight": 282, "cookies": false, "type": "", "deprecated": false, @@ -34370,7 +34456,7 @@ "x-appwrite": { "method": "listRepositories", "group": "repositories", - "weight": 282, + "weight": 283, "cookies": false, "type": "", "deprecated": false, @@ -34455,7 +34541,7 @@ "x-appwrite": { "method": "createRepository", "group": "repositories", - "weight": 283, + "weight": 284, "cookies": false, "type": "", "deprecated": false, @@ -34540,7 +34626,7 @@ "x-appwrite": { "method": "getRepository", "group": "repositories", - "weight": 284, + "weight": 285, "cookies": false, "type": "", "deprecated": false, @@ -34610,7 +34696,7 @@ "x-appwrite": { "method": "listRepositoryBranches", "group": "repositories", - "weight": 285, + "weight": 286, "cookies": false, "type": "", "deprecated": false, @@ -34680,7 +34766,7 @@ "x-appwrite": { "method": "getRepositoryContents", "group": "repositories", - "weight": 280, + "weight": 281, "cookies": false, "type": "", "deprecated": false, @@ -34754,7 +34840,7 @@ "x-appwrite": { "method": "updateExternalDeployments", "group": "repositories", - "weight": 290, + "weight": 291, "cookies": false, "type": "", "deprecated": false, @@ -34843,7 +34929,7 @@ "x-appwrite": { "method": "listInstallations", "group": "installations", - "weight": 287, + "weight": 288, "cookies": false, "type": "", "deprecated": false, @@ -34917,7 +35003,7 @@ "x-appwrite": { "method": "getInstallation", "group": "installations", - "weight": 288, + "weight": 289, "cookies": false, "type": "", "deprecated": false, @@ -34968,7 +35054,7 @@ "x-appwrite": { "method": "deleteInstallation", "group": "installations", - "weight": 289, + "weight": 290, "cookies": false, "type": "", "deprecated": false, diff --git a/app/config/specs/open-api3-1.7.x-server.json b/app/config/specs/open-api3-1.7.x-server.json index 216ab3e21d..db615d642c 100644 --- a/app/config/specs/open-api3-1.7.x-server.json +++ b/app/config/specs/open-api3-1.7.x-server.json @@ -7530,29 +7530,6 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." - }, - { - "name": "createDocuments", - "auth": { - "Key": [] - }, - "parameters": [ - "databaseId", - "collectionId", - "documents" - ], - "required": [ - "databaseId", - "collectionId", - "documents" - ], - "responses": [ - { - "code": 201, - "model": "#\/components\/schemas\/documentList" - } - ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -7650,7 +7627,7 @@ "x-appwrite": { "method": "upsertDocuments", "group": "documents", - "weight": 115, + "weight": 116, "cookies": false, "type": "", "deprecated": false, @@ -7739,7 +7716,7 @@ "x-appwrite": { "method": "updateDocuments", "group": "documents", - "weight": 114, + "weight": 115, "cookies": false, "type": "", "deprecated": false, @@ -7833,7 +7810,7 @@ "x-appwrite": { "method": "deleteDocuments", "group": "documents", - "weight": 117, + "weight": 118, "cookies": false, "type": "", "deprecated": false, @@ -7999,6 +7976,117 @@ } ] }, + "put": { + "summary": "Upsert document", + "operationId": "databasesUpsertDocument", + "tags": [ + "databases" + ], + "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "upsertDocument", + "group": "documents", + "weight": 114, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DOCUMENT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include all required attributes of the document to be created or updated.", + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "data" + ] + } + } + } + } + }, "patch": { "summary": "Update document", "operationId": "databasesUpdateDocument", @@ -8122,7 +8210,7 @@ "x-appwrite": { "method": "deleteDocument", "group": "documents", - "weight": 116, + "weight": 117, "cookies": false, "type": "", "deprecated": false, @@ -8573,7 +8661,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 375, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -8647,7 +8735,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 372, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -8879,7 +8967,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 377, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -8929,7 +9017,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 378, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -8980,7 +9068,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 373, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -9040,7 +9128,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 374, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -9269,7 +9357,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 376, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -9331,7 +9419,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 381, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -9412,7 +9500,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 382, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -9496,7 +9584,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 379, + "weight": 380, "cookies": false, "type": "upload", "deprecated": false, @@ -9593,7 +9681,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 387, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -9679,7 +9767,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 384, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -9783,7 +9871,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 385, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -9881,7 +9969,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 380, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -9944,7 +10032,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 383, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -10009,7 +10097,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 386, + "weight": 387, "cookies": false, "type": "location", "deprecated": false, @@ -10100,7 +10188,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 388, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -10172,7 +10260,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 391, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -10249,7 +10337,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 389, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -10366,7 +10454,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 390, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -10433,7 +10521,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 392, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -10505,7 +10593,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 397, + "weight": 398, "cookies": false, "type": "", "deprecated": false, @@ -10565,7 +10653,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 395, + "weight": 396, "cookies": false, "type": "", "deprecated": false, @@ -10657,7 +10745,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 396, + "weight": 397, "cookies": false, "type": "", "deprecated": false, @@ -10727,7 +10815,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 398, + "weight": 399, "cookies": false, "type": "", "deprecated": false, @@ -10819,7 +10907,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 399, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -10891,7 +10979,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 305, + "weight": 306, "cookies": false, "type": "graphql", "deprecated": false, @@ -10945,7 +11033,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 304, + "weight": 305, "cookies": false, "type": "graphql", "deprecated": false, @@ -10999,7 +11087,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 129, + "weight": 130, "cookies": false, "type": "", "deprecated": false, @@ -11049,7 +11137,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 150, + "weight": 151, "cookies": false, "type": "", "deprecated": false, @@ -11099,7 +11187,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 132, + "weight": 133, "cookies": false, "type": "", "deprecated": false, @@ -11149,7 +11237,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 137, + "weight": 138, "cookies": false, "type": "", "deprecated": false, @@ -11210,7 +11298,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 131, + "weight": 132, "cookies": false, "type": "", "deprecated": false, @@ -11260,7 +11348,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 133, + "weight": 134, "cookies": false, "type": "", "deprecated": false, @@ -11310,7 +11398,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 139, + "weight": 140, "cookies": false, "type": "", "deprecated": false, @@ -11373,7 +11461,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 138, + "weight": 139, "cookies": false, "type": "", "deprecated": false, @@ -11436,7 +11524,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 140, + "weight": 141, "cookies": false, "type": "", "deprecated": false, @@ -11510,7 +11598,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 141, + "weight": 142, "cookies": false, "type": "", "deprecated": false, @@ -11573,7 +11661,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 151, + "weight": 152, "cookies": false, "type": "", "deprecated": false, @@ -11662,7 +11750,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 145, + "weight": 146, "cookies": false, "type": "", "deprecated": false, @@ -11725,7 +11813,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 136, + "weight": 137, "cookies": false, "type": "", "deprecated": false, @@ -11788,7 +11876,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 142, + "weight": 143, "cookies": false, "type": "", "deprecated": false, @@ -11851,7 +11939,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 143, + "weight": 144, "cookies": false, "type": "", "deprecated": false, @@ -11914,7 +12002,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 144, + "weight": 145, "cookies": false, "type": "", "deprecated": false, @@ -11977,7 +12065,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 146, + "weight": 147, "cookies": false, "type": "", "deprecated": false, @@ -12040,7 +12128,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 147, + "weight": 148, "cookies": false, "type": "", "deprecated": false, @@ -12103,7 +12191,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 135, + "weight": 136, "cookies": false, "type": "", "deprecated": false, @@ -12166,7 +12254,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 149, + "weight": 150, "cookies": false, "type": "", "deprecated": false, @@ -12216,7 +12304,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 148, + "weight": 149, "cookies": false, "type": "", "deprecated": false, @@ -12266,7 +12354,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 134, + "weight": 135, "cookies": false, "type": "", "deprecated": false, @@ -12316,7 +12404,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 121, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -12370,7 +12458,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 122, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -12424,7 +12512,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 126, + "weight": 127, "cookies": false, "type": "", "deprecated": false, @@ -12478,7 +12566,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 123, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -12532,7 +12620,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 124, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -12586,7 +12674,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 125, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -12640,7 +12728,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 127, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -12694,7 +12782,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 128, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -12748,7 +12836,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 359, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -12825,7 +12913,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 356, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -12970,7 +13058,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 363, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -13117,7 +13205,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 358, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -13292,7 +13380,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 365, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -13471,7 +13559,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 357, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -13581,7 +13669,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 364, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -13694,7 +13782,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 362, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -13748,7 +13836,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 366, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -13811,7 +13899,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 360, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -13887,7 +13975,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 361, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -13963,7 +14051,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 331, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -14040,7 +14128,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 330, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -14146,7 +14234,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 343, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -14255,7 +14343,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 329, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -14341,7 +14429,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 342, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -14430,7 +14518,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 321, + "weight": 322, "cookies": false, "type": "", "deprecated": false, @@ -14546,7 +14634,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 334, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -14665,7 +14753,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 324, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -14761,7 +14849,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 337, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -14860,7 +14948,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 322, + "weight": 323, "cookies": false, "type": "", "deprecated": false, @@ -14966,7 +15054,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 335, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -15075,7 +15163,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 323, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -15219,7 +15307,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 336, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -15365,7 +15453,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 325, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -15461,7 +15549,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 338, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -15560,7 +15648,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 326, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -15656,7 +15744,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 339, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -15755,7 +15843,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 327, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -15851,7 +15939,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 340, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -15950,7 +16038,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 328, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -16046,7 +16134,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 341, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -16145,7 +16233,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 333, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -16199,7 +16287,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 344, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -16262,7 +16350,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 332, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -16338,7 +16426,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 353, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -16414,7 +16502,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 346, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -16489,7 +16577,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 345, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -16573,7 +16661,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 348, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -16634,7 +16722,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 349, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -16712,7 +16800,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 350, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -16775,7 +16863,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 347, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -16851,7 +16939,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 352, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -16936,7 +17024,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 351, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -17028,7 +17116,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 354, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -17092,7 +17180,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 355, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -17169,7 +17257,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 404, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -17240,7 +17328,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 402, + "weight": 403, "cookies": false, "type": "", "deprecated": false, @@ -17488,7 +17576,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 407, + "weight": 408, "cookies": false, "type": "", "deprecated": false, @@ -17538,7 +17626,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 430, + "weight": 431, "cookies": false, "type": "", "deprecated": false, @@ -17589,7 +17677,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 403, + "weight": 404, "cookies": false, "type": "", "deprecated": false, @@ -17649,7 +17737,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 405, + "weight": 406, "cookies": false, "type": "", "deprecated": false, @@ -17893,7 +17981,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 406, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -17955,7 +18043,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 413, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -18036,7 +18124,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 412, + "weight": 413, "cookies": false, "type": "", "deprecated": false, @@ -18120,7 +18208,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 408, + "weight": 409, "cookies": false, "type": "upload", "deprecated": false, @@ -18222,7 +18310,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 416, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -18303,7 +18391,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 409, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -18407,7 +18495,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 410, + "weight": 411, "cookies": false, "type": "", "deprecated": false, @@ -18506,7 +18594,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 411, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -18569,7 +18657,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 414, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -18634,7 +18722,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 415, + "weight": 416, "cookies": false, "type": "location", "deprecated": false, @@ -18725,7 +18813,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 417, + "weight": 418, "cookies": false, "type": "", "deprecated": false, @@ -18797,7 +18885,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 419, + "weight": 420, "cookies": false, "type": "", "deprecated": false, @@ -18869,7 +18957,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 418, + "weight": 419, "cookies": false, "type": "", "deprecated": false, @@ -18932,7 +19020,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 420, + "weight": 421, "cookies": false, "type": "", "deprecated": false, @@ -19004,7 +19092,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 423, + "weight": 424, "cookies": false, "type": "", "deprecated": false, @@ -19064,7 +19152,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 421, + "weight": 422, "cookies": false, "type": "", "deprecated": false, @@ -19156,7 +19244,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 422, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -19226,7 +19314,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 424, + "weight": 425, "cookies": false, "type": "", "deprecated": false, @@ -19318,7 +19406,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 425, + "weight": 426, "cookies": false, "type": "", "deprecated": false, @@ -19390,7 +19478,7 @@ "x-appwrite": { "method": "listBuckets", "group": "buckets", - "weight": 206, + "weight": 207, "cookies": false, "type": "", "deprecated": false, @@ -19464,7 +19552,7 @@ "x-appwrite": { "method": "createBucket", "group": "buckets", - "weight": 205, + "weight": 206, "cookies": false, "type": "", "deprecated": false, @@ -19592,7 +19680,7 @@ "x-appwrite": { "method": "getBucket", "group": "buckets", - "weight": 207, + "weight": 208, "cookies": false, "type": "", "deprecated": false, @@ -19652,7 +19740,7 @@ "x-appwrite": { "method": "updateBucket", "group": "buckets", - "weight": 208, + "weight": 209, "cookies": false, "type": "", "deprecated": false, @@ -19777,7 +19865,7 @@ "x-appwrite": { "method": "deleteBucket", "group": "buckets", - "weight": 209, + "weight": 210, "cookies": false, "type": "", "deprecated": false, @@ -19839,7 +19927,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 211, + "weight": 212, "cookies": false, "type": "", "deprecated": false, @@ -19927,7 +20015,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 210, + "weight": 211, "cookies": false, "type": "upload", "deprecated": false, @@ -20027,7 +20115,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 212, + "weight": 213, "cookies": false, "type": "", "deprecated": false, @@ -20101,7 +20189,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 217, + "weight": 218, "cookies": false, "type": "", "deprecated": false, @@ -20192,7 +20280,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 218, + "weight": 219, "cookies": false, "type": "", "deprecated": false, @@ -20261,7 +20349,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 214, + "weight": 215, "cookies": false, "type": "location", "deprecated": false, @@ -20341,7 +20429,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 213, + "weight": 214, "cookies": false, "type": "location", "deprecated": false, @@ -20570,7 +20658,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 215, + "weight": 216, "cookies": false, "type": "location", "deprecated": false, @@ -20657,7 +20745,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 222, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -20735,7 +20823,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 221, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -20822,7 +20910,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 223, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -20886,7 +20974,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 225, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -20962,7 +21050,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 227, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -21028,7 +21116,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 229, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -21116,7 +21204,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 228, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -21229,7 +21317,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 230, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -21303,7 +21391,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 231, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -21392,7 +21480,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 233, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -21468,7 +21556,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 232, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -21567,7 +21655,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 224, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -21629,7 +21717,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 226, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -21712,7 +21800,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 438, + "weight": 439, "cookies": false, "type": "", "deprecated": false, @@ -21793,7 +21881,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 436, + "weight": 437, "cookies": false, "type": "", "deprecated": false, @@ -21883,7 +21971,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 437, + "weight": 438, "cookies": false, "type": "", "deprecated": false, @@ -21944,7 +22032,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 439, + "weight": 440, "cookies": false, "type": "", "deprecated": false, @@ -22015,7 +22103,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 440, + "weight": 441, "cookies": false, "type": "", "deprecated": false, @@ -22078,7 +22166,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 244, + "weight": 245, "cookies": false, "type": "", "deprecated": false, @@ -22152,7 +22240,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 235, + "weight": 236, "cookies": false, "type": "", "deprecated": false, @@ -22241,7 +22329,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 238, + "weight": 239, "cookies": false, "type": "", "deprecated": false, @@ -22327,7 +22415,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 236, + "weight": 237, "cookies": false, "type": "", "deprecated": false, @@ -22413,7 +22501,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 252, + "weight": 253, "cookies": false, "type": "", "deprecated": false, @@ -22482,7 +22570,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 275, + "weight": 276, "cookies": false, "type": "", "deprecated": false, @@ -22544,7 +22632,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 237, + "weight": 238, "cookies": false, "type": "", "deprecated": false, @@ -22630,7 +22718,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 240, + "weight": 241, "cookies": false, "type": "", "deprecated": false, @@ -22716,7 +22804,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 241, + "weight": 242, "cookies": false, "type": "", "deprecated": false, @@ -22832,7 +22920,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 242, + "weight": 243, "cookies": false, "type": "", "deprecated": false, @@ -22936,7 +23024,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 239, + "weight": 240, "cookies": false, "type": "", "deprecated": false, @@ -23042,7 +23130,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 245, + "weight": 246, "cookies": false, "type": "", "deprecated": false, @@ -23095,7 +23183,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 273, + "weight": 274, "cookies": false, "type": "", "deprecated": false, @@ -23157,7 +23245,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 258, + "weight": 259, "cookies": false, "type": "", "deprecated": false, @@ -23238,7 +23326,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 276, + "weight": 277, "cookies": false, "type": "", "deprecated": false, @@ -23321,7 +23409,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 254, + "weight": 255, "cookies": false, "type": "", "deprecated": false, @@ -23405,7 +23493,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 250, + "weight": 251, "cookies": false, "type": "", "deprecated": false, @@ -23480,7 +23568,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 249, + "weight": 250, "cookies": false, "type": "", "deprecated": false, @@ -23566,7 +23654,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 263, + "weight": 264, "cookies": false, "type": "", "deprecated": false, @@ -23640,7 +23728,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 268, + "weight": 269, "cookies": false, "type": "", "deprecated": false, @@ -23717,7 +23805,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 264, + "weight": 265, "cookies": false, "type": "", "deprecated": false, @@ -23779,7 +23867,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 265, + "weight": 266, "cookies": false, "type": "", "deprecated": false, @@ -23839,7 +23927,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 267, + "weight": 268, "cookies": false, "type": "", "deprecated": false, @@ -23899,7 +23987,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 266, + "weight": 267, "cookies": false, "type": "", "deprecated": false, @@ -23961,7 +24049,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 256, + "weight": 257, "cookies": false, "type": "", "deprecated": false, @@ -24042,7 +24130,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 257, + "weight": 258, "cookies": false, "type": "", "deprecated": false, @@ -24123,7 +24211,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 259, + "weight": 260, "cookies": false, "type": "", "deprecated": false, @@ -24204,7 +24292,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 246, + "weight": 247, "cookies": false, "type": "", "deprecated": false, @@ -24264,7 +24352,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 261, + "weight": 262, "cookies": false, "type": "", "deprecated": false, @@ -24345,7 +24433,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 248, + "weight": 249, "cookies": false, "type": "", "deprecated": false, @@ -24405,7 +24493,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 269, + "weight": 270, "cookies": false, "type": "", "deprecated": false, @@ -24458,7 +24546,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 272, + "weight": 273, "cookies": false, "type": "", "deprecated": false, @@ -24513,7 +24601,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 271, + "weight": 272, "cookies": false, "type": "", "deprecated": false, @@ -24585,7 +24673,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 253, + "weight": 254, "cookies": false, "type": "", "deprecated": false, @@ -24666,7 +24754,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 251, + "weight": 252, "cookies": false, "type": "", "deprecated": false, @@ -24740,7 +24828,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 243, + "weight": 244, "cookies": false, "type": "", "deprecated": false, @@ -24851,7 +24939,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 247, + "weight": 248, "cookies": false, "type": "", "deprecated": false, @@ -24922,7 +25010,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 262, + "weight": 263, "cookies": false, "type": "", "deprecated": false, @@ -25012,7 +25100,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 274, + "weight": 275, "cookies": false, "type": "", "deprecated": false, @@ -25085,7 +25173,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 270, + "weight": 271, "cookies": false, "type": "", "deprecated": false, @@ -25168,7 +25256,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 260, + "weight": 261, "cookies": false, "type": "", "deprecated": false, @@ -25249,7 +25337,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 255, + "weight": 256, "cookies": false, "type": "", "deprecated": false, diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index 341eaa1eac..abeab8a56f 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -4490,29 +4490,6 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." - }, - { - "name": "createDocuments", - "auth": { - "Key": [] - }, - "parameters": [ - "databaseId", - "collectionId", - "documents" - ], - "required": [ - "databaseId", - "collectionId", - "documents" - ], - "responses": [ - { - "code": 201, - "model": "#\/components\/schemas\/documentList" - } - ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -4683,6 +4660,115 @@ } ] }, + "put": { + "summary": "Upsert document", + "operationId": "databasesUpsertDocument", + "tags": [ + "databases" + ], + "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "upsertDocument", + "group": "documents", + "weight": 114, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DOCUMENT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include all required attributes of the document to be created or updated.", + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "data" + ] + } + } + } + } + }, "patch": { "summary": "Update document", "operationId": "databasesUpdateDocument", @@ -4804,7 +4890,7 @@ "x-appwrite": { "method": "deleteDocument", "group": "documents", - "weight": 116, + "weight": 117, "cookies": false, "type": "", "deprecated": false, @@ -4888,7 +4974,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 391, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -4963,7 +5049,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 389, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -5078,7 +5164,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 390, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -5152,7 +5238,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 305, + "weight": 306, "cookies": false, "type": "graphql", "deprecated": false, @@ -5204,7 +5290,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 304, + "weight": 305, "cookies": false, "type": "graphql", "deprecated": false, @@ -5256,7 +5342,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 121, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -5308,7 +5394,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 122, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -5360,7 +5446,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 126, + "weight": 127, "cookies": false, "type": "", "deprecated": false, @@ -5412,7 +5498,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 123, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -5464,7 +5550,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 124, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -5516,7 +5602,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 125, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -5568,7 +5654,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 127, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -5620,7 +5706,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 128, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -5672,7 +5758,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 351, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -5755,7 +5841,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 355, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -5830,7 +5916,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 211, + "weight": 212, "cookies": false, "type": "", "deprecated": false, @@ -5916,7 +6002,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 210, + "weight": 211, "cookies": false, "type": "upload", "deprecated": false, @@ -6014,7 +6100,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 212, + "weight": 213, "cookies": false, "type": "", "deprecated": false, @@ -6086,7 +6172,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 217, + "weight": 218, "cookies": false, "type": "", "deprecated": false, @@ -6175,7 +6261,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 218, + "weight": 219, "cookies": false, "type": "", "deprecated": false, @@ -6242,7 +6328,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 214, + "weight": 215, "cookies": false, "type": "location", "deprecated": false, @@ -6320,7 +6406,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 213, + "weight": 214, "cookies": false, "type": "location", "deprecated": false, @@ -6547,7 +6633,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 215, + "weight": 216, "cookies": false, "type": "location", "deprecated": false, @@ -6632,7 +6718,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 222, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -6708,7 +6794,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 221, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -6793,7 +6879,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 223, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -6855,7 +6941,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 225, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -6929,7 +7015,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 227, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -6993,7 +7079,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 229, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -7079,7 +7165,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 228, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -7190,7 +7276,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 230, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -7262,7 +7348,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 231, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -7349,7 +7435,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 233, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -7423,7 +7509,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 232, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -7521,7 +7607,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 224, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -7582,7 +7668,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 226, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -9775,6 +9861,12 @@ "name": "X-Appwrite-Session", "description": "The user session to authenticate with", "in": "header" + }, + "DevKey": { + "type": "apiKey", + "name": "X-Appwrite-Dev-Key", + "description": "Your secret dev API key", + "in": "header" } } }, diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 6c003e8283..19ce78915c 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -4359,7 +4359,7 @@ "x-appwrite": { "method": "chat", "group": "console", - "weight": 307, + "weight": 308, "cookies": false, "type": "", "deprecated": false, @@ -4419,7 +4419,7 @@ "x-appwrite": { "method": "getResource", "group": null, - "weight": 431, + "weight": 432, "cookies": false, "type": "", "deprecated": false, @@ -4494,7 +4494,7 @@ "x-appwrite": { "method": "variables", "group": "console", - "weight": 306, + "weight": 307, "cookies": false, "type": "", "deprecated": false, @@ -4694,7 +4694,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 118, + "weight": 119, "cookies": false, "type": "", "deprecated": false, @@ -8049,29 +8049,6 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." - }, - { - "name": "createDocuments", - "auth": { - "Key": [] - }, - "parameters": [ - "databaseId", - "collectionId", - "documents" - ], - "required": [ - "databaseId", - "collectionId", - "documents" - ], - "responses": [ - { - "code": 201, - "model": "#\/components\/schemas\/documentList" - } - ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -8167,7 +8144,7 @@ "x-appwrite": { "method": "upsertDocuments", "group": "documents", - "weight": 115, + "weight": 116, "cookies": false, "type": "", "deprecated": false, @@ -8255,7 +8232,7 @@ "x-appwrite": { "method": "updateDocuments", "group": "documents", - "weight": 114, + "weight": 115, "cookies": false, "type": "", "deprecated": false, @@ -8348,7 +8325,7 @@ "x-appwrite": { "method": "deleteDocuments", "group": "documents", - "weight": 117, + "weight": 118, "cookies": false, "type": "", "deprecated": false, @@ -8511,6 +8488,115 @@ } ] }, + "put": { + "summary": "Upsert document", + "operationId": "databasesUpsertDocument", + "tags": [ + "databases" + ], + "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "upsertDocument", + "group": "documents", + "weight": 114, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DOCUMENT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include all required attributes of the document to be created or updated.", + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "data" + ] + } + } + } + } + }, "patch": { "summary": "Update document", "operationId": "databasesUpdateDocument", @@ -8632,7 +8718,7 @@ "x-appwrite": { "method": "deleteDocument", "group": "documents", - "weight": 116, + "weight": 117, "cookies": false, "type": "", "deprecated": false, @@ -9253,7 +9339,7 @@ "x-appwrite": { "method": "getCollectionUsage", "group": null, - "weight": 120, + "weight": 121, "cookies": false, "type": "", "deprecated": false, @@ -9418,7 +9504,7 @@ "x-appwrite": { "method": "getDatabaseUsage", "group": null, - "weight": 119, + "weight": 120, "cookies": false, "type": "", "deprecated": false, @@ -9500,7 +9586,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 375, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -9573,7 +9659,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 372, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -9804,7 +9890,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 377, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -9853,7 +9939,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 378, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -9903,7 +9989,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 401, + "weight": 402, "cookies": false, "type": "", "deprecated": false, @@ -10003,7 +10089,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 400, + "weight": 401, "cookies": false, "type": "", "deprecated": false, @@ -10063,7 +10149,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 394, + "weight": 395, "cookies": false, "type": "", "deprecated": false, @@ -10135,7 +10221,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 373, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -10194,7 +10280,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 374, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -10422,7 +10508,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 376, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -10483,7 +10569,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 381, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -10563,7 +10649,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 382, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -10646,7 +10732,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 379, + "weight": 380, "cookies": false, "type": "upload", "deprecated": false, @@ -10742,7 +10828,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 387, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -10827,7 +10913,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 384, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -10930,7 +11016,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 385, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -11027,7 +11113,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 380, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -11089,7 +11175,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 383, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -11153,7 +11239,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 386, + "weight": 387, "cookies": false, "type": "location", "deprecated": false, @@ -11243,7 +11329,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 388, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -11314,7 +11400,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 391, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -11389,7 +11475,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 389, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -11504,7 +11590,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 390, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -11569,7 +11655,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 392, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -11640,7 +11726,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 393, + "weight": 394, "cookies": false, "type": "", "deprecated": false, @@ -11722,7 +11808,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 397, + "weight": 398, "cookies": false, "type": "", "deprecated": false, @@ -11781,7 +11867,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 395, + "weight": 396, "cookies": false, "type": "", "deprecated": false, @@ -11872,7 +11958,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 396, + "weight": 397, "cookies": false, "type": "", "deprecated": false, @@ -11941,7 +12027,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 398, + "weight": 399, "cookies": false, "type": "", "deprecated": false, @@ -12032,7 +12118,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 399, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -12103,7 +12189,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 305, + "weight": 306, "cookies": false, "type": "graphql", "deprecated": false, @@ -12155,7 +12241,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 304, + "weight": 305, "cookies": false, "type": "graphql", "deprecated": false, @@ -12207,7 +12293,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 129, + "weight": 130, "cookies": false, "type": "", "deprecated": false, @@ -12256,7 +12342,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 150, + "weight": 151, "cookies": false, "type": "", "deprecated": false, @@ -12305,7 +12391,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 132, + "weight": 133, "cookies": false, "type": "", "deprecated": false, @@ -12354,7 +12440,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 137, + "weight": 138, "cookies": false, "type": "", "deprecated": false, @@ -12414,7 +12500,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 131, + "weight": 132, "cookies": false, "type": "", "deprecated": false, @@ -12463,7 +12549,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 133, + "weight": 134, "cookies": false, "type": "", "deprecated": false, @@ -12512,7 +12598,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 139, + "weight": 140, "cookies": false, "type": "", "deprecated": false, @@ -12574,7 +12660,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 138, + "weight": 139, "cookies": false, "type": "", "deprecated": false, @@ -12636,7 +12722,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 140, + "weight": 141, "cookies": false, "type": "", "deprecated": false, @@ -12709,7 +12795,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 141, + "weight": 142, "cookies": false, "type": "", "deprecated": false, @@ -12771,7 +12857,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 151, + "weight": 152, "cookies": false, "type": "", "deprecated": false, @@ -12859,7 +12945,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 145, + "weight": 146, "cookies": false, "type": "", "deprecated": false, @@ -12921,7 +13007,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 136, + "weight": 137, "cookies": false, "type": "", "deprecated": false, @@ -12983,7 +13069,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 142, + "weight": 143, "cookies": false, "type": "", "deprecated": false, @@ -13045,7 +13131,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 143, + "weight": 144, "cookies": false, "type": "", "deprecated": false, @@ -13107,7 +13193,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 144, + "weight": 145, "cookies": false, "type": "", "deprecated": false, @@ -13169,7 +13255,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 146, + "weight": 147, "cookies": false, "type": "", "deprecated": false, @@ -13231,7 +13317,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 147, + "weight": 148, "cookies": false, "type": "", "deprecated": false, @@ -13293,7 +13379,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 135, + "weight": 136, "cookies": false, "type": "", "deprecated": false, @@ -13355,7 +13441,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 149, + "weight": 150, "cookies": false, "type": "", "deprecated": false, @@ -13404,7 +13490,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 148, + "weight": 149, "cookies": false, "type": "", "deprecated": false, @@ -13453,7 +13539,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 134, + "weight": 135, "cookies": false, "type": "", "deprecated": false, @@ -13502,7 +13588,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 121, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -13554,7 +13640,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 122, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -13606,7 +13692,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 126, + "weight": 127, "cookies": false, "type": "", "deprecated": false, @@ -13658,7 +13744,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 123, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -13710,7 +13796,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 124, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -13762,7 +13848,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 125, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -13814,7 +13900,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 127, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -13866,7 +13952,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 128, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -13918,7 +14004,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 359, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -13994,7 +14080,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 356, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -14138,7 +14224,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 363, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -14284,7 +14370,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 358, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -14458,7 +14544,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 365, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -14636,7 +14722,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 357, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -14745,7 +14831,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 364, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -14857,7 +14943,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 362, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -14910,7 +14996,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 366, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -14972,7 +15058,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 360, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -15047,7 +15133,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 361, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -15122,7 +15208,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 331, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -15198,7 +15284,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 330, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -15303,7 +15389,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 343, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -15411,7 +15497,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 329, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -15496,7 +15582,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 342, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -15584,7 +15670,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 321, + "weight": 322, "cookies": false, "type": "", "deprecated": false, @@ -15699,7 +15785,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 334, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -15817,7 +15903,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 324, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -15912,7 +15998,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 337, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -16010,7 +16096,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 322, + "weight": 323, "cookies": false, "type": "", "deprecated": false, @@ -16115,7 +16201,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 335, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -16223,7 +16309,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 323, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -16366,7 +16452,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 336, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -16511,7 +16597,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 325, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -16606,7 +16692,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 338, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -16704,7 +16790,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 326, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -16799,7 +16885,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 339, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -16897,7 +16983,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 327, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -16992,7 +17078,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 340, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -17090,7 +17176,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 328, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -17185,7 +17271,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 341, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -17283,7 +17369,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 333, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -17336,7 +17422,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 344, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -17398,7 +17484,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 332, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -17473,7 +17559,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 353, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -17548,7 +17634,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 346, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -17622,7 +17708,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 345, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -17705,7 +17791,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 348, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -17765,7 +17851,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 349, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -17842,7 +17928,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 350, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -17904,7 +17990,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 347, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -17979,7 +18065,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 352, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -18063,7 +18149,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 351, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -18153,7 +18239,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 354, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -18216,7 +18302,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 355, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -18291,7 +18377,7 @@ "x-appwrite": { "method": "list", "group": null, - "weight": 313, + "weight": 314, "cookies": false, "type": "", "deprecated": false, @@ -18365,7 +18451,7 @@ "x-appwrite": { "method": "createAppwriteMigration", "group": null, - "weight": 308, + "weight": 309, "cookies": false, "type": "", "deprecated": false, @@ -18453,7 +18539,7 @@ "x-appwrite": { "method": "getAppwriteReport", "group": null, - "weight": 315, + "weight": 316, "cookies": false, "type": "", "deprecated": false, @@ -18546,7 +18632,7 @@ "x-appwrite": { "method": "createCsvMigration", "group": null, - "weight": 312, + "weight": 313, "cookies": false, "type": "", "deprecated": false, @@ -18625,7 +18711,7 @@ "x-appwrite": { "method": "createFirebaseMigration", "group": null, - "weight": 309, + "weight": 310, "cookies": false, "type": "", "deprecated": false, @@ -18701,7 +18787,7 @@ "x-appwrite": { "method": "getFirebaseReport", "group": null, - "weight": 316, + "weight": 317, "cookies": false, "type": "", "deprecated": false, @@ -18773,7 +18859,7 @@ "x-appwrite": { "method": "createNHostMigration", "group": null, - "weight": 311, + "weight": 312, "cookies": false, "type": "", "deprecated": false, @@ -18884,7 +18970,7 @@ "x-appwrite": { "method": "getNHostReport", "group": null, - "weight": 318, + "weight": 319, "cookies": false, "type": "", "deprecated": false, @@ -19017,7 +19103,7 @@ "x-appwrite": { "method": "createSupabaseMigration", "group": null, - "weight": 310, + "weight": 311, "cookies": false, "type": "", "deprecated": false, @@ -19122,7 +19208,7 @@ "x-appwrite": { "method": "getSupabaseReport", "group": null, - "weight": 317, + "weight": 318, "cookies": false, "type": "", "deprecated": false, @@ -19246,7 +19332,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 314, + "weight": 315, "cookies": false, "type": "", "deprecated": false, @@ -19304,7 +19390,7 @@ "x-appwrite": { "method": "retry", "group": null, - "weight": 319, + "weight": 320, "cookies": false, "type": "", "deprecated": false, @@ -19355,7 +19441,7 @@ "x-appwrite": { "method": "delete", "group": null, - "weight": 320, + "weight": 321, "cookies": false, "type": "", "deprecated": false, @@ -19415,7 +19501,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 199, + "weight": 200, "cookies": false, "type": "", "deprecated": false, @@ -19503,7 +19589,7 @@ "x-appwrite": { "method": "listVariables", "group": null, - "weight": 201, + "weight": 202, "cookies": false, "type": "", "deprecated": false, @@ -19549,7 +19635,7 @@ "x-appwrite": { "method": "createVariable", "group": null, - "weight": 200, + "weight": 201, "cookies": false, "type": "", "deprecated": false, @@ -19627,7 +19713,7 @@ "x-appwrite": { "method": "getVariable", "group": null, - "weight": 202, + "weight": 203, "cookies": false, "type": "", "deprecated": false, @@ -19685,7 +19771,7 @@ "x-appwrite": { "method": "updateVariable", "group": null, - "weight": 203, + "weight": 204, "cookies": false, "type": "", "deprecated": false, @@ -19765,7 +19851,7 @@ "x-appwrite": { "method": "deleteVariable", "group": null, - "weight": 204, + "weight": 205, "cookies": false, "type": "", "deprecated": false, @@ -19825,7 +19911,7 @@ "x-appwrite": { "method": "list", "group": "projects", - "weight": 154, + "weight": 155, "cookies": false, "type": "", "deprecated": false, @@ -19897,7 +19983,7 @@ "x-appwrite": { "method": "create", "group": "projects", - "weight": 153, + "weight": 154, "cookies": false, "type": "", "deprecated": false, @@ -20031,7 +20117,7 @@ "x-appwrite": { "method": "get", "group": "projects", - "weight": 155, + "weight": 156, "cookies": false, "type": "", "deprecated": false, @@ -20089,7 +20175,7 @@ "x-appwrite": { "method": "update", "group": "projects", - "weight": 156, + "weight": 157, "cookies": false, "type": "", "deprecated": false, @@ -20204,7 +20290,7 @@ "x-appwrite": { "method": "delete", "group": "projects", - "weight": 173, + "weight": 174, "cookies": false, "type": "", "deprecated": false, @@ -20264,7 +20350,7 @@ "x-appwrite": { "method": "updateApiStatus", "group": "projects", - "weight": 160, + "weight": 161, "cookies": false, "type": "", "deprecated": false, @@ -20356,7 +20442,7 @@ "x-appwrite": { "method": "updateApiStatusAll", "group": "projects", - "weight": 161, + "weight": 162, "cookies": false, "type": "", "deprecated": false, @@ -20435,7 +20521,7 @@ "x-appwrite": { "method": "updateAuthDuration", "group": "auth", - "weight": 166, + "weight": 167, "cookies": false, "type": "", "deprecated": false, @@ -20514,7 +20600,7 @@ "x-appwrite": { "method": "updateAuthLimit", "group": "auth", - "weight": 165, + "weight": 166, "cookies": false, "type": "", "deprecated": false, @@ -20593,7 +20679,7 @@ "x-appwrite": { "method": "updateAuthSessionsLimit", "group": "auth", - "weight": 171, + "weight": 172, "cookies": false, "type": "", "deprecated": false, @@ -20672,7 +20758,7 @@ "x-appwrite": { "method": "updateMembershipsPrivacy", "group": "auth", - "weight": 164, + "weight": 165, "cookies": false, "type": "", "deprecated": false, @@ -20763,7 +20849,7 @@ "x-appwrite": { "method": "updateMockNumbers", "group": "auth", - "weight": 172, + "weight": 173, "cookies": false, "type": "", "deprecated": false, @@ -20845,7 +20931,7 @@ "x-appwrite": { "method": "updateAuthPasswordDictionary", "group": "auth", - "weight": 169, + "weight": 170, "cookies": false, "type": "", "deprecated": false, @@ -20924,7 +21010,7 @@ "x-appwrite": { "method": "updateAuthPasswordHistory", "group": "auth", - "weight": 168, + "weight": 169, "cookies": false, "type": "", "deprecated": false, @@ -21003,7 +21089,7 @@ "x-appwrite": { "method": "updatePersonalDataCheck", "group": "auth", - "weight": 170, + "weight": 171, "cookies": false, "type": "", "deprecated": false, @@ -21082,7 +21168,7 @@ "x-appwrite": { "method": "updateSessionAlerts", "group": "auth", - "weight": 163, + "weight": 164, "cookies": false, "type": "", "deprecated": false, @@ -21161,7 +21247,7 @@ "x-appwrite": { "method": "updateAuthStatus", "group": "auth", - "weight": 167, + "weight": 168, "cookies": false, "type": "", "deprecated": false, @@ -21261,7 +21347,7 @@ "x-appwrite": { "method": "listDevKeys", "group": "devKeys", - "weight": 370, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -21329,7 +21415,7 @@ "x-appwrite": { "method": "createDevKey", "group": "devKeys", - "weight": 367, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -21414,7 +21500,7 @@ "x-appwrite": { "method": "getDevKey", "group": "devKeys", - "weight": 369, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -21482,7 +21568,7 @@ "x-appwrite": { "method": "updateDevKey", "group": "devKeys", - "weight": 368, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -21568,7 +21654,7 @@ "x-appwrite": { "method": "deleteDevKey", "group": "devKeys", - "weight": 371, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -21638,7 +21724,7 @@ "x-appwrite": { "method": "createJWT", "group": "auth", - "weight": 185, + "weight": 186, "cookies": false, "type": "", "deprecated": false, @@ -21725,7 +21811,7 @@ "x-appwrite": { "method": "listKeys", "group": "keys", - "weight": 181, + "weight": 182, "cookies": false, "type": "", "deprecated": false, @@ -21783,7 +21869,7 @@ "x-appwrite": { "method": "createKey", "group": "keys", - "weight": 180, + "weight": 181, "cookies": false, "type": "", "deprecated": false, @@ -21876,7 +21962,7 @@ "x-appwrite": { "method": "getKey", "group": "keys", - "weight": 182, + "weight": 183, "cookies": false, "type": "", "deprecated": false, @@ -21944,7 +22030,7 @@ "x-appwrite": { "method": "updateKey", "group": "keys", - "weight": 183, + "weight": 184, "cookies": false, "type": "", "deprecated": false, @@ -22038,7 +22124,7 @@ "x-appwrite": { "method": "deleteKey", "group": "keys", - "weight": 184, + "weight": 185, "cookies": false, "type": "", "deprecated": false, @@ -22108,7 +22194,7 @@ "x-appwrite": { "method": "updateOAuth2", "group": "auth", - "weight": 162, + "weight": 163, "cookies": false, "type": "", "deprecated": false, @@ -22246,7 +22332,7 @@ "x-appwrite": { "method": "listPlatforms", "group": "platforms", - "weight": 187, + "weight": 188, "cookies": false, "type": "", "deprecated": false, @@ -22304,7 +22390,7 @@ "x-appwrite": { "method": "createPlatform", "group": "platforms", - "weight": 186, + "weight": 187, "cookies": false, "type": "", "deprecated": false, @@ -22423,7 +22509,7 @@ "x-appwrite": { "method": "getPlatform", "group": "platforms", - "weight": 188, + "weight": 189, "cookies": false, "type": "", "deprecated": false, @@ -22491,7 +22577,7 @@ "x-appwrite": { "method": "updatePlatform", "group": "platforms", - "weight": 189, + "weight": 190, "cookies": false, "type": "", "deprecated": false, @@ -22586,7 +22672,7 @@ "x-appwrite": { "method": "deletePlatform", "group": "platforms", - "weight": 190, + "weight": 191, "cookies": false, "type": "", "deprecated": false, @@ -22656,7 +22742,7 @@ "x-appwrite": { "method": "updateServiceStatus", "group": "projects", - "weight": 158, + "weight": 159, "cookies": false, "type": "", "deprecated": false, @@ -22757,7 +22843,7 @@ "x-appwrite": { "method": "updateServiceStatusAll", "group": "projects", - "weight": 159, + "weight": 160, "cookies": false, "type": "", "deprecated": false, @@ -22836,7 +22922,7 @@ "x-appwrite": { "method": "updateSmtp", "group": "templates", - "weight": 191, + "weight": 192, "cookies": false, "type": "", "deprecated": false, @@ -22954,7 +23040,7 @@ "x-appwrite": { "method": "createSmtpTest", "group": "templates", - "weight": 192, + "weight": 193, "cookies": false, "type": "", "deprecated": false, @@ -23085,7 +23171,7 @@ "x-appwrite": { "method": "updateTeam", "group": "projects", - "weight": 157, + "weight": 158, "cookies": false, "type": "", "deprecated": false, @@ -23164,7 +23250,7 @@ "x-appwrite": { "method": "getEmailTemplate", "group": "templates", - "weight": 194, + "weight": 195, "cookies": false, "type": "", "deprecated": false, @@ -23388,7 +23474,7 @@ "x-appwrite": { "method": "updateEmailTemplate", "group": "templates", - "weight": 196, + "weight": 197, "cookies": false, "type": "", "deprecated": false, @@ -23652,7 +23738,7 @@ "x-appwrite": { "method": "deleteEmailTemplate", "group": "templates", - "weight": 198, + "weight": 199, "cookies": false, "type": "", "deprecated": false, @@ -23878,7 +23964,7 @@ "x-appwrite": { "method": "getSmsTemplate", "group": "templates", - "weight": 193, + "weight": 194, "cookies": false, "type": "", "deprecated": false, @@ -24099,7 +24185,7 @@ "x-appwrite": { "method": "updateSmsTemplate", "group": "templates", - "weight": 195, + "weight": 196, "cookies": false, "type": "", "deprecated": false, @@ -24339,7 +24425,7 @@ "x-appwrite": { "method": "deleteSmsTemplate", "group": "templates", - "weight": 197, + "weight": 198, "cookies": false, "type": "", "deprecated": false, @@ -24562,7 +24648,7 @@ "x-appwrite": { "method": "listWebhooks", "group": "webhooks", - "weight": 175, + "weight": 176, "cookies": false, "type": "", "deprecated": false, @@ -24620,7 +24706,7 @@ "x-appwrite": { "method": "createWebhook", "group": "webhooks", - "weight": 174, + "weight": 175, "cookies": false, "type": "", "deprecated": false, @@ -24735,7 +24821,7 @@ "x-appwrite": { "method": "getWebhook", "group": "webhooks", - "weight": 176, + "weight": 177, "cookies": false, "type": "", "deprecated": false, @@ -24803,7 +24889,7 @@ "x-appwrite": { "method": "updateWebhook", "group": "webhooks", - "weight": 177, + "weight": 178, "cookies": false, "type": "", "deprecated": false, @@ -24919,7 +25005,7 @@ "x-appwrite": { "method": "deleteWebhook", "group": "webhooks", - "weight": 179, + "weight": 180, "cookies": false, "type": "", "deprecated": false, @@ -24989,7 +25075,7 @@ "x-appwrite": { "method": "updateWebhookSignature", "group": "webhooks", - "weight": 178, + "weight": 179, "cookies": false, "type": "", "deprecated": false, @@ -25059,7 +25145,7 @@ "x-appwrite": { "method": "listRules", "group": null, - "weight": 291, + "weight": 292, "cookies": false, "type": "", "deprecated": false, @@ -25133,7 +25219,7 @@ "x-appwrite": { "method": "createAPIRule", "group": null, - "weight": 432, + "weight": 433, "cookies": false, "type": "", "deprecated": false, @@ -25200,7 +25286,7 @@ "x-appwrite": { "method": "createFunctionRule", "group": null, - "weight": 434, + "weight": 435, "cookies": false, "type": "", "deprecated": false, @@ -25278,7 +25364,7 @@ "x-appwrite": { "method": "createRedirectRule", "group": null, - "weight": 435, + "weight": 436, "cookies": false, "type": "", "deprecated": false, @@ -25370,7 +25456,7 @@ "x-appwrite": { "method": "createSiteRule", "group": null, - "weight": 433, + "weight": 434, "cookies": false, "type": "", "deprecated": false, @@ -25448,7 +25534,7 @@ "x-appwrite": { "method": "getRule", "group": null, - "weight": 292, + "weight": 293, "cookies": false, "type": "", "deprecated": false, @@ -25499,7 +25585,7 @@ "x-appwrite": { "method": "deleteRule", "group": null, - "weight": 293, + "weight": 294, "cookies": false, "type": "", "deprecated": false, @@ -25559,7 +25645,7 @@ "x-appwrite": { "method": "updateRuleVerification", "group": null, - "weight": 294, + "weight": 295, "cookies": false, "type": "", "deprecated": false, @@ -25619,7 +25705,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 404, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -25689,7 +25775,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 402, + "weight": 403, "cookies": false, "type": "", "deprecated": false, @@ -25936,7 +26022,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 407, + "weight": 408, "cookies": false, "type": "", "deprecated": false, @@ -25985,7 +26071,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 430, + "weight": 431, "cookies": false, "type": "", "deprecated": false, @@ -26035,7 +26121,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 426, + "weight": 427, "cookies": false, "type": "", "deprecated": false, @@ -26135,7 +26221,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 427, + "weight": 428, "cookies": false, "type": "", "deprecated": false, @@ -26195,7 +26281,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 428, + "weight": 429, "cookies": false, "type": "", "deprecated": false, @@ -26267,7 +26353,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 403, + "weight": 404, "cookies": false, "type": "", "deprecated": false, @@ -26326,7 +26412,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 405, + "weight": 406, "cookies": false, "type": "", "deprecated": false, @@ -26569,7 +26655,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 406, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -26630,7 +26716,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 413, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -26710,7 +26796,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 412, + "weight": 413, "cookies": false, "type": "", "deprecated": false, @@ -26793,7 +26879,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 408, + "weight": 409, "cookies": false, "type": "upload", "deprecated": false, @@ -26894,7 +26980,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 416, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -26974,7 +27060,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 409, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -27077,7 +27163,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 410, + "weight": 411, "cookies": false, "type": "", "deprecated": false, @@ -27175,7 +27261,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 411, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -27237,7 +27323,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 414, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -27301,7 +27387,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 415, + "weight": 416, "cookies": false, "type": "location", "deprecated": false, @@ -27391,7 +27477,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 417, + "weight": 418, "cookies": false, "type": "", "deprecated": false, @@ -27462,7 +27548,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 419, + "weight": 420, "cookies": false, "type": "", "deprecated": false, @@ -27533,7 +27619,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 418, + "weight": 419, "cookies": false, "type": "", "deprecated": false, @@ -27595,7 +27681,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 420, + "weight": 421, "cookies": false, "type": "", "deprecated": false, @@ -27666,7 +27752,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 429, + "weight": 430, "cookies": false, "type": "", "deprecated": false, @@ -27748,7 +27834,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 423, + "weight": 424, "cookies": false, "type": "", "deprecated": false, @@ -27807,7 +27893,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 421, + "weight": 422, "cookies": false, "type": "", "deprecated": false, @@ -27898,7 +27984,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 422, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -27967,7 +28053,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 424, + "weight": 425, "cookies": false, "type": "", "deprecated": false, @@ -28058,7 +28144,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 425, + "weight": 426, "cookies": false, "type": "", "deprecated": false, @@ -28129,7 +28215,7 @@ "x-appwrite": { "method": "listBuckets", "group": "buckets", - "weight": 206, + "weight": 207, "cookies": false, "type": "", "deprecated": false, @@ -28202,7 +28288,7 @@ "x-appwrite": { "method": "createBucket", "group": "buckets", - "weight": 205, + "weight": 206, "cookies": false, "type": "", "deprecated": false, @@ -28329,7 +28415,7 @@ "x-appwrite": { "method": "getBucket", "group": "buckets", - "weight": 207, + "weight": 208, "cookies": false, "type": "", "deprecated": false, @@ -28388,7 +28474,7 @@ "x-appwrite": { "method": "updateBucket", "group": "buckets", - "weight": 208, + "weight": 209, "cookies": false, "type": "", "deprecated": false, @@ -28512,7 +28598,7 @@ "x-appwrite": { "method": "deleteBucket", "group": "buckets", - "weight": 209, + "weight": 210, "cookies": false, "type": "", "deprecated": false, @@ -28573,7 +28659,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 211, + "weight": 212, "cookies": false, "type": "", "deprecated": false, @@ -28659,7 +28745,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 210, + "weight": 211, "cookies": false, "type": "upload", "deprecated": false, @@ -28757,7 +28843,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 212, + "weight": 213, "cookies": false, "type": "", "deprecated": false, @@ -28829,7 +28915,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 217, + "weight": 218, "cookies": false, "type": "", "deprecated": false, @@ -28918,7 +29004,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 218, + "weight": 219, "cookies": false, "type": "", "deprecated": false, @@ -28985,7 +29071,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 214, + "weight": 215, "cookies": false, "type": "location", "deprecated": false, @@ -29063,7 +29149,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 213, + "weight": 214, "cookies": false, "type": "location", "deprecated": false, @@ -29290,7 +29376,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 215, + "weight": 216, "cookies": false, "type": "location", "deprecated": false, @@ -29375,7 +29461,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 219, + "weight": 220, "cookies": false, "type": "", "deprecated": false, @@ -29447,7 +29533,7 @@ "x-appwrite": { "method": "getBucketUsage", "group": null, - "weight": 220, + "weight": 221, "cookies": false, "type": "", "deprecated": false, @@ -29529,7 +29615,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 222, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -29605,7 +29691,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 221, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -29690,7 +29776,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 223, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -29752,7 +29838,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 225, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -29826,7 +29912,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 227, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -29890,7 +29976,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 234, + "weight": 235, "cookies": false, "type": "", "deprecated": false, @@ -29963,7 +30049,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 229, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -30049,7 +30135,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 228, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -30160,7 +30246,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 230, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -30232,7 +30318,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 231, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -30319,7 +30405,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 233, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -30393,7 +30479,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 232, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -30490,7 +30576,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 224, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -30550,7 +30636,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 226, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -30631,7 +30717,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 438, + "weight": 439, "cookies": false, "type": "", "deprecated": false, @@ -30711,7 +30797,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 436, + "weight": 437, "cookies": false, "type": "", "deprecated": false, @@ -30800,7 +30886,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 437, + "weight": 438, "cookies": false, "type": "", "deprecated": false, @@ -30860,7 +30946,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 439, + "weight": 440, "cookies": false, "type": "", "deprecated": false, @@ -30930,7 +31016,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 440, + "weight": 441, "cookies": false, "type": "", "deprecated": false, @@ -30992,7 +31078,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 244, + "weight": 245, "cookies": false, "type": "", "deprecated": false, @@ -31065,7 +31151,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 235, + "weight": 236, "cookies": false, "type": "", "deprecated": false, @@ -31153,7 +31239,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 238, + "weight": 239, "cookies": false, "type": "", "deprecated": false, @@ -31238,7 +31324,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 236, + "weight": 237, "cookies": false, "type": "", "deprecated": false, @@ -31323,7 +31409,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 252, + "weight": 253, "cookies": false, "type": "", "deprecated": false, @@ -31391,7 +31477,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 275, + "weight": 276, "cookies": false, "type": "", "deprecated": false, @@ -31452,7 +31538,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 237, + "weight": 238, "cookies": false, "type": "", "deprecated": false, @@ -31537,7 +31623,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 240, + "weight": 241, "cookies": false, "type": "", "deprecated": false, @@ -31622,7 +31708,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 241, + "weight": 242, "cookies": false, "type": "", "deprecated": false, @@ -31737,7 +31823,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 242, + "weight": 243, "cookies": false, "type": "", "deprecated": false, @@ -31840,7 +31926,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 239, + "weight": 240, "cookies": false, "type": "", "deprecated": false, @@ -31945,7 +32031,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 277, + "weight": 278, "cookies": false, "type": "", "deprecated": false, @@ -32017,7 +32103,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 245, + "weight": 246, "cookies": false, "type": "", "deprecated": false, @@ -32069,7 +32155,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 273, + "weight": 274, "cookies": false, "type": "", "deprecated": false, @@ -32130,7 +32216,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 258, + "weight": 259, "cookies": false, "type": "", "deprecated": false, @@ -32210,7 +32296,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 276, + "weight": 277, "cookies": false, "type": "", "deprecated": false, @@ -32292,7 +32378,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 254, + "weight": 255, "cookies": false, "type": "", "deprecated": false, @@ -32375,7 +32461,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 250, + "weight": 251, "cookies": false, "type": "", "deprecated": false, @@ -32449,7 +32535,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 249, + "weight": 250, "cookies": false, "type": "", "deprecated": false, @@ -32534,7 +32620,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 263, + "weight": 264, "cookies": false, "type": "", "deprecated": false, @@ -32607,7 +32693,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 268, + "weight": 269, "cookies": false, "type": "", "deprecated": false, @@ -32683,7 +32769,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 264, + "weight": 265, "cookies": false, "type": "", "deprecated": false, @@ -32744,7 +32830,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 265, + "weight": 266, "cookies": false, "type": "", "deprecated": false, @@ -32803,7 +32889,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 267, + "weight": 268, "cookies": false, "type": "", "deprecated": false, @@ -32862,7 +32948,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 266, + "weight": 267, "cookies": false, "type": "", "deprecated": false, @@ -32923,7 +33009,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 256, + "weight": 257, "cookies": false, "type": "", "deprecated": false, @@ -33003,7 +33089,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 257, + "weight": 258, "cookies": false, "type": "", "deprecated": false, @@ -33083,7 +33169,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 259, + "weight": 260, "cookies": false, "type": "", "deprecated": false, @@ -33163,7 +33249,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 246, + "weight": 247, "cookies": false, "type": "", "deprecated": false, @@ -33222,7 +33308,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 261, + "weight": 262, "cookies": false, "type": "", "deprecated": false, @@ -33302,7 +33388,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 248, + "weight": 249, "cookies": false, "type": "", "deprecated": false, @@ -33361,7 +33447,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 269, + "weight": 270, "cookies": false, "type": "", "deprecated": false, @@ -33413,7 +33499,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 272, + "weight": 273, "cookies": false, "type": "", "deprecated": false, @@ -33467,7 +33553,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 271, + "weight": 272, "cookies": false, "type": "", "deprecated": false, @@ -33538,7 +33624,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 253, + "weight": 254, "cookies": false, "type": "", "deprecated": false, @@ -33618,7 +33704,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 251, + "weight": 252, "cookies": false, "type": "", "deprecated": false, @@ -33691,7 +33777,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 243, + "weight": 244, "cookies": false, "type": "", "deprecated": false, @@ -33801,7 +33887,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 247, + "weight": 248, "cookies": false, "type": "", "deprecated": false, @@ -33871,7 +33957,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 262, + "weight": 263, "cookies": false, "type": "", "deprecated": false, @@ -33960,7 +34046,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 274, + "weight": 275, "cookies": false, "type": "", "deprecated": false, @@ -34032,7 +34118,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 270, + "weight": 271, "cookies": false, "type": "", "deprecated": false, @@ -34114,7 +34200,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 260, + "weight": 261, "cookies": false, "type": "", "deprecated": false, @@ -34194,7 +34280,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 255, + "weight": 256, "cookies": false, "type": "", "deprecated": false, @@ -34274,7 +34360,7 @@ "x-appwrite": { "method": "createRepositoryDetection", "group": "repositories", - "weight": 281, + "weight": 282, "cookies": false, "type": "", "deprecated": false, @@ -34370,7 +34456,7 @@ "x-appwrite": { "method": "listRepositories", "group": "repositories", - "weight": 282, + "weight": 283, "cookies": false, "type": "", "deprecated": false, @@ -34455,7 +34541,7 @@ "x-appwrite": { "method": "createRepository", "group": "repositories", - "weight": 283, + "weight": 284, "cookies": false, "type": "", "deprecated": false, @@ -34540,7 +34626,7 @@ "x-appwrite": { "method": "getRepository", "group": "repositories", - "weight": 284, + "weight": 285, "cookies": false, "type": "", "deprecated": false, @@ -34610,7 +34696,7 @@ "x-appwrite": { "method": "listRepositoryBranches", "group": "repositories", - "weight": 285, + "weight": 286, "cookies": false, "type": "", "deprecated": false, @@ -34680,7 +34766,7 @@ "x-appwrite": { "method": "getRepositoryContents", "group": "repositories", - "weight": 280, + "weight": 281, "cookies": false, "type": "", "deprecated": false, @@ -34754,7 +34840,7 @@ "x-appwrite": { "method": "updateExternalDeployments", "group": "repositories", - "weight": 290, + "weight": 291, "cookies": false, "type": "", "deprecated": false, @@ -34843,7 +34929,7 @@ "x-appwrite": { "method": "listInstallations", "group": "installations", - "weight": 287, + "weight": 288, "cookies": false, "type": "", "deprecated": false, @@ -34917,7 +35003,7 @@ "x-appwrite": { "method": "getInstallation", "group": "installations", - "weight": 288, + "weight": 289, "cookies": false, "type": "", "deprecated": false, @@ -34968,7 +35054,7 @@ "x-appwrite": { "method": "deleteInstallation", "group": "installations", - "weight": 289, + "weight": 290, "cookies": false, "type": "", "deprecated": false, diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 216ab3e21d..db615d642c 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -7530,29 +7530,6 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." - }, - { - "name": "createDocuments", - "auth": { - "Key": [] - }, - "parameters": [ - "databaseId", - "collectionId", - "documents" - ], - "required": [ - "databaseId", - "collectionId", - "documents" - ], - "responses": [ - { - "code": 201, - "model": "#\/components\/schemas\/documentList" - } - ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -7650,7 +7627,7 @@ "x-appwrite": { "method": "upsertDocuments", "group": "documents", - "weight": 115, + "weight": 116, "cookies": false, "type": "", "deprecated": false, @@ -7739,7 +7716,7 @@ "x-appwrite": { "method": "updateDocuments", "group": "documents", - "weight": 114, + "weight": 115, "cookies": false, "type": "", "deprecated": false, @@ -7833,7 +7810,7 @@ "x-appwrite": { "method": "deleteDocuments", "group": "documents", - "weight": 117, + "weight": 118, "cookies": false, "type": "", "deprecated": false, @@ -7999,6 +7976,117 @@ } ] }, + "put": { + "summary": "Upsert document", + "operationId": "databasesUpsertDocument", + "tags": [ + "databases" + ], + "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "upsertDocument", + "group": "documents", + "weight": 114, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DOCUMENT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include all required attributes of the document to be created or updated.", + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "data" + ] + } + } + } + } + }, "patch": { "summary": "Update document", "operationId": "databasesUpdateDocument", @@ -8122,7 +8210,7 @@ "x-appwrite": { "method": "deleteDocument", "group": "documents", - "weight": 116, + "weight": 117, "cookies": false, "type": "", "deprecated": false, @@ -8573,7 +8661,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 375, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -8647,7 +8735,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 372, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -8879,7 +8967,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 377, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -8929,7 +9017,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 378, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -8980,7 +9068,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 373, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -9040,7 +9128,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 374, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -9269,7 +9357,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 376, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -9331,7 +9419,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 381, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -9412,7 +9500,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 382, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -9496,7 +9584,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 379, + "weight": 380, "cookies": false, "type": "upload", "deprecated": false, @@ -9593,7 +9681,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 387, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -9679,7 +9767,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 384, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -9783,7 +9871,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 385, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -9881,7 +9969,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 380, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -9944,7 +10032,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 383, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -10009,7 +10097,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 386, + "weight": 387, "cookies": false, "type": "location", "deprecated": false, @@ -10100,7 +10188,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 388, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -10172,7 +10260,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 391, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -10249,7 +10337,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 389, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -10366,7 +10454,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 390, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -10433,7 +10521,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 392, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -10505,7 +10593,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 397, + "weight": 398, "cookies": false, "type": "", "deprecated": false, @@ -10565,7 +10653,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 395, + "weight": 396, "cookies": false, "type": "", "deprecated": false, @@ -10657,7 +10745,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 396, + "weight": 397, "cookies": false, "type": "", "deprecated": false, @@ -10727,7 +10815,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 398, + "weight": 399, "cookies": false, "type": "", "deprecated": false, @@ -10819,7 +10907,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 399, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -10891,7 +10979,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 305, + "weight": 306, "cookies": false, "type": "graphql", "deprecated": false, @@ -10945,7 +11033,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 304, + "weight": 305, "cookies": false, "type": "graphql", "deprecated": false, @@ -10999,7 +11087,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 129, + "weight": 130, "cookies": false, "type": "", "deprecated": false, @@ -11049,7 +11137,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 150, + "weight": 151, "cookies": false, "type": "", "deprecated": false, @@ -11099,7 +11187,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 132, + "weight": 133, "cookies": false, "type": "", "deprecated": false, @@ -11149,7 +11237,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 137, + "weight": 138, "cookies": false, "type": "", "deprecated": false, @@ -11210,7 +11298,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 131, + "weight": 132, "cookies": false, "type": "", "deprecated": false, @@ -11260,7 +11348,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 133, + "weight": 134, "cookies": false, "type": "", "deprecated": false, @@ -11310,7 +11398,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 139, + "weight": 140, "cookies": false, "type": "", "deprecated": false, @@ -11373,7 +11461,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 138, + "weight": 139, "cookies": false, "type": "", "deprecated": false, @@ -11436,7 +11524,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 140, + "weight": 141, "cookies": false, "type": "", "deprecated": false, @@ -11510,7 +11598,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 141, + "weight": 142, "cookies": false, "type": "", "deprecated": false, @@ -11573,7 +11661,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 151, + "weight": 152, "cookies": false, "type": "", "deprecated": false, @@ -11662,7 +11750,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 145, + "weight": 146, "cookies": false, "type": "", "deprecated": false, @@ -11725,7 +11813,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 136, + "weight": 137, "cookies": false, "type": "", "deprecated": false, @@ -11788,7 +11876,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 142, + "weight": 143, "cookies": false, "type": "", "deprecated": false, @@ -11851,7 +11939,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 143, + "weight": 144, "cookies": false, "type": "", "deprecated": false, @@ -11914,7 +12002,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 144, + "weight": 145, "cookies": false, "type": "", "deprecated": false, @@ -11977,7 +12065,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 146, + "weight": 147, "cookies": false, "type": "", "deprecated": false, @@ -12040,7 +12128,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 147, + "weight": 148, "cookies": false, "type": "", "deprecated": false, @@ -12103,7 +12191,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 135, + "weight": 136, "cookies": false, "type": "", "deprecated": false, @@ -12166,7 +12254,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 149, + "weight": 150, "cookies": false, "type": "", "deprecated": false, @@ -12216,7 +12304,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 148, + "weight": 149, "cookies": false, "type": "", "deprecated": false, @@ -12266,7 +12354,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 134, + "weight": 135, "cookies": false, "type": "", "deprecated": false, @@ -12316,7 +12404,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 121, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -12370,7 +12458,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 122, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -12424,7 +12512,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 126, + "weight": 127, "cookies": false, "type": "", "deprecated": false, @@ -12478,7 +12566,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 123, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -12532,7 +12620,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 124, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -12586,7 +12674,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 125, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -12640,7 +12728,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 127, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -12694,7 +12782,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 128, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -12748,7 +12836,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 359, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -12825,7 +12913,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 356, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -12970,7 +13058,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 363, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -13117,7 +13205,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 358, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -13292,7 +13380,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 365, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -13471,7 +13559,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 357, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -13581,7 +13669,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 364, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -13694,7 +13782,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 362, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -13748,7 +13836,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 366, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -13811,7 +13899,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 360, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -13887,7 +13975,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 361, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -13963,7 +14051,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 331, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -14040,7 +14128,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 330, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -14146,7 +14234,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 343, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -14255,7 +14343,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 329, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -14341,7 +14429,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 342, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -14430,7 +14518,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 321, + "weight": 322, "cookies": false, "type": "", "deprecated": false, @@ -14546,7 +14634,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 334, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -14665,7 +14753,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 324, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -14761,7 +14849,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 337, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -14860,7 +14948,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 322, + "weight": 323, "cookies": false, "type": "", "deprecated": false, @@ -14966,7 +15054,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 335, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -15075,7 +15163,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 323, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -15219,7 +15307,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 336, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -15365,7 +15453,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 325, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -15461,7 +15549,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 338, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -15560,7 +15648,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 326, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -15656,7 +15744,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 339, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -15755,7 +15843,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 327, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -15851,7 +15939,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 340, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -15950,7 +16038,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 328, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -16046,7 +16134,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 341, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -16145,7 +16233,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 333, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -16199,7 +16287,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 344, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -16262,7 +16350,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 332, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -16338,7 +16426,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 353, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -16414,7 +16502,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 346, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -16489,7 +16577,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 345, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -16573,7 +16661,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 348, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -16634,7 +16722,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 349, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -16712,7 +16800,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 350, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -16775,7 +16863,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 347, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -16851,7 +16939,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 352, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -16936,7 +17024,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 351, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -17028,7 +17116,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 354, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -17092,7 +17180,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 355, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -17169,7 +17257,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 404, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -17240,7 +17328,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 402, + "weight": 403, "cookies": false, "type": "", "deprecated": false, @@ -17488,7 +17576,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 407, + "weight": 408, "cookies": false, "type": "", "deprecated": false, @@ -17538,7 +17626,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 430, + "weight": 431, "cookies": false, "type": "", "deprecated": false, @@ -17589,7 +17677,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 403, + "weight": 404, "cookies": false, "type": "", "deprecated": false, @@ -17649,7 +17737,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 405, + "weight": 406, "cookies": false, "type": "", "deprecated": false, @@ -17893,7 +17981,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 406, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -17955,7 +18043,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 413, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -18036,7 +18124,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 412, + "weight": 413, "cookies": false, "type": "", "deprecated": false, @@ -18120,7 +18208,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 408, + "weight": 409, "cookies": false, "type": "upload", "deprecated": false, @@ -18222,7 +18310,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 416, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -18303,7 +18391,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 409, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -18407,7 +18495,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 410, + "weight": 411, "cookies": false, "type": "", "deprecated": false, @@ -18506,7 +18594,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 411, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -18569,7 +18657,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 414, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -18634,7 +18722,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 415, + "weight": 416, "cookies": false, "type": "location", "deprecated": false, @@ -18725,7 +18813,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 417, + "weight": 418, "cookies": false, "type": "", "deprecated": false, @@ -18797,7 +18885,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 419, + "weight": 420, "cookies": false, "type": "", "deprecated": false, @@ -18869,7 +18957,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 418, + "weight": 419, "cookies": false, "type": "", "deprecated": false, @@ -18932,7 +19020,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 420, + "weight": 421, "cookies": false, "type": "", "deprecated": false, @@ -19004,7 +19092,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 423, + "weight": 424, "cookies": false, "type": "", "deprecated": false, @@ -19064,7 +19152,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 421, + "weight": 422, "cookies": false, "type": "", "deprecated": false, @@ -19156,7 +19244,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 422, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -19226,7 +19314,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 424, + "weight": 425, "cookies": false, "type": "", "deprecated": false, @@ -19318,7 +19406,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 425, + "weight": 426, "cookies": false, "type": "", "deprecated": false, @@ -19390,7 +19478,7 @@ "x-appwrite": { "method": "listBuckets", "group": "buckets", - "weight": 206, + "weight": 207, "cookies": false, "type": "", "deprecated": false, @@ -19464,7 +19552,7 @@ "x-appwrite": { "method": "createBucket", "group": "buckets", - "weight": 205, + "weight": 206, "cookies": false, "type": "", "deprecated": false, @@ -19592,7 +19680,7 @@ "x-appwrite": { "method": "getBucket", "group": "buckets", - "weight": 207, + "weight": 208, "cookies": false, "type": "", "deprecated": false, @@ -19652,7 +19740,7 @@ "x-appwrite": { "method": "updateBucket", "group": "buckets", - "weight": 208, + "weight": 209, "cookies": false, "type": "", "deprecated": false, @@ -19777,7 +19865,7 @@ "x-appwrite": { "method": "deleteBucket", "group": "buckets", - "weight": 209, + "weight": 210, "cookies": false, "type": "", "deprecated": false, @@ -19839,7 +19927,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 211, + "weight": 212, "cookies": false, "type": "", "deprecated": false, @@ -19927,7 +20015,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 210, + "weight": 211, "cookies": false, "type": "upload", "deprecated": false, @@ -20027,7 +20115,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 212, + "weight": 213, "cookies": false, "type": "", "deprecated": false, @@ -20101,7 +20189,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 217, + "weight": 218, "cookies": false, "type": "", "deprecated": false, @@ -20192,7 +20280,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 218, + "weight": 219, "cookies": false, "type": "", "deprecated": false, @@ -20261,7 +20349,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 214, + "weight": 215, "cookies": false, "type": "location", "deprecated": false, @@ -20341,7 +20429,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 213, + "weight": 214, "cookies": false, "type": "location", "deprecated": false, @@ -20570,7 +20658,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 215, + "weight": 216, "cookies": false, "type": "location", "deprecated": false, @@ -20657,7 +20745,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 222, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -20735,7 +20823,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 221, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -20822,7 +20910,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 223, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -20886,7 +20974,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 225, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -20962,7 +21050,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 227, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -21028,7 +21116,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 229, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -21116,7 +21204,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 228, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -21229,7 +21317,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 230, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -21303,7 +21391,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 231, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -21392,7 +21480,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 233, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -21468,7 +21556,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 232, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -21567,7 +21655,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 224, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -21629,7 +21717,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 226, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -21712,7 +21800,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 438, + "weight": 439, "cookies": false, "type": "", "deprecated": false, @@ -21793,7 +21881,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 436, + "weight": 437, "cookies": false, "type": "", "deprecated": false, @@ -21883,7 +21971,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 437, + "weight": 438, "cookies": false, "type": "", "deprecated": false, @@ -21944,7 +22032,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 439, + "weight": 440, "cookies": false, "type": "", "deprecated": false, @@ -22015,7 +22103,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 440, + "weight": 441, "cookies": false, "type": "", "deprecated": false, @@ -22078,7 +22166,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 244, + "weight": 245, "cookies": false, "type": "", "deprecated": false, @@ -22152,7 +22240,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 235, + "weight": 236, "cookies": false, "type": "", "deprecated": false, @@ -22241,7 +22329,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 238, + "weight": 239, "cookies": false, "type": "", "deprecated": false, @@ -22327,7 +22415,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 236, + "weight": 237, "cookies": false, "type": "", "deprecated": false, @@ -22413,7 +22501,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 252, + "weight": 253, "cookies": false, "type": "", "deprecated": false, @@ -22482,7 +22570,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 275, + "weight": 276, "cookies": false, "type": "", "deprecated": false, @@ -22544,7 +22632,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 237, + "weight": 238, "cookies": false, "type": "", "deprecated": false, @@ -22630,7 +22718,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 240, + "weight": 241, "cookies": false, "type": "", "deprecated": false, @@ -22716,7 +22804,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 241, + "weight": 242, "cookies": false, "type": "", "deprecated": false, @@ -22832,7 +22920,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 242, + "weight": 243, "cookies": false, "type": "", "deprecated": false, @@ -22936,7 +23024,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 239, + "weight": 240, "cookies": false, "type": "", "deprecated": false, @@ -23042,7 +23130,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 245, + "weight": 246, "cookies": false, "type": "", "deprecated": false, @@ -23095,7 +23183,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 273, + "weight": 274, "cookies": false, "type": "", "deprecated": false, @@ -23157,7 +23245,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 258, + "weight": 259, "cookies": false, "type": "", "deprecated": false, @@ -23238,7 +23326,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 276, + "weight": 277, "cookies": false, "type": "", "deprecated": false, @@ -23321,7 +23409,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 254, + "weight": 255, "cookies": false, "type": "", "deprecated": false, @@ -23405,7 +23493,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 250, + "weight": 251, "cookies": false, "type": "", "deprecated": false, @@ -23480,7 +23568,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 249, + "weight": 250, "cookies": false, "type": "", "deprecated": false, @@ -23566,7 +23654,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 263, + "weight": 264, "cookies": false, "type": "", "deprecated": false, @@ -23640,7 +23728,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 268, + "weight": 269, "cookies": false, "type": "", "deprecated": false, @@ -23717,7 +23805,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 264, + "weight": 265, "cookies": false, "type": "", "deprecated": false, @@ -23779,7 +23867,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 265, + "weight": 266, "cookies": false, "type": "", "deprecated": false, @@ -23839,7 +23927,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 267, + "weight": 268, "cookies": false, "type": "", "deprecated": false, @@ -23899,7 +23987,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 266, + "weight": 267, "cookies": false, "type": "", "deprecated": false, @@ -23961,7 +24049,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 256, + "weight": 257, "cookies": false, "type": "", "deprecated": false, @@ -24042,7 +24130,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 257, + "weight": 258, "cookies": false, "type": "", "deprecated": false, @@ -24123,7 +24211,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 259, + "weight": 260, "cookies": false, "type": "", "deprecated": false, @@ -24204,7 +24292,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 246, + "weight": 247, "cookies": false, "type": "", "deprecated": false, @@ -24264,7 +24352,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 261, + "weight": 262, "cookies": false, "type": "", "deprecated": false, @@ -24345,7 +24433,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 248, + "weight": 249, "cookies": false, "type": "", "deprecated": false, @@ -24405,7 +24493,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 269, + "weight": 270, "cookies": false, "type": "", "deprecated": false, @@ -24458,7 +24546,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 272, + "weight": 273, "cookies": false, "type": "", "deprecated": false, @@ -24513,7 +24601,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 271, + "weight": 272, "cookies": false, "type": "", "deprecated": false, @@ -24585,7 +24673,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 253, + "weight": 254, "cookies": false, "type": "", "deprecated": false, @@ -24666,7 +24754,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 251, + "weight": 252, "cookies": false, "type": "", "deprecated": false, @@ -24740,7 +24828,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 243, + "weight": 244, "cookies": false, "type": "", "deprecated": false, @@ -24851,7 +24939,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 247, + "weight": 248, "cookies": false, "type": "", "deprecated": false, @@ -24922,7 +25010,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 262, + "weight": 263, "cookies": false, "type": "", "deprecated": false, @@ -25012,7 +25100,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 274, + "weight": 275, "cookies": false, "type": "", "deprecated": false, @@ -25085,7 +25173,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 270, + "weight": 271, "cookies": false, "type": "", "deprecated": false, @@ -25168,7 +25256,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 260, + "weight": 261, "cookies": false, "type": "", "deprecated": false, @@ -25249,7 +25337,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 255, + "weight": 256, "cookies": false, "type": "", "deprecated": false, diff --git a/app/config/specs/swagger2-1.7.x-client.json b/app/config/specs/swagger2-1.7.x-client.json index e7a8ee5ee7..5c1b764e1e 100644 --- a/app/config/specs/swagger2-1.7.x-client.json +++ b/app/config/specs/swagger2-1.7.x-client.json @@ -61,6 +61,12 @@ "name": "X-Appwrite-Session", "description": "The user session to authenticate with", "in": "header" + }, + "DevKey": { + "type": "apiKey", + "name": "X-Appwrite-Dev-Key", + "description": "Your secret dev API key", + "in": "header" } }, "paths": { @@ -4630,29 +4636,6 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." - }, - { - "name": "createDocuments", - "auth": { - "Key": [] - }, - "parameters": [ - "databaseId", - "collectionId", - "documents" - ], - "required": [ - "databaseId", - "collectionId", - "documents" - ], - "responses": [ - { - "code": 201, - "model": "#\/definitions\/documentList" - } - ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -4814,6 +4797,111 @@ } ] }, + "put": { + "summary": "Upsert document", + "operationId": "databasesUpsertDocument", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "upsertDocument", + "group": "documents", + "weight": 114, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include all required attributes of the document to be created or updated.", + "default": {}, + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "data" + ] + } + } + ] + }, "patch": { "summary": "Update document", "operationId": "databasesUpdateDocument", @@ -4935,7 +5023,7 @@ "x-appwrite": { "method": "deleteDocument", "group": "documents", - "weight": 116, + "weight": 117, "cookies": false, "type": "", "deprecated": false, @@ -5013,7 +5101,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 391, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -5087,7 +5175,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 389, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -5204,7 +5292,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 390, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -5276,7 +5364,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 305, + "weight": 306, "cookies": false, "type": "graphql", "deprecated": false, @@ -5350,7 +5438,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 304, + "weight": 305, "cookies": false, "type": "graphql", "deprecated": false, @@ -5422,7 +5510,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 121, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -5474,7 +5562,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 122, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -5526,7 +5614,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 126, + "weight": 127, "cookies": false, "type": "", "deprecated": false, @@ -5578,7 +5666,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 123, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -5630,7 +5718,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 124, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -5682,7 +5770,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 125, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -5734,7 +5822,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 127, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -5786,7 +5874,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 128, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -5840,7 +5928,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 351, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -5925,7 +6013,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 355, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -5996,7 +6084,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 211, + "weight": 212, "cookies": false, "type": "", "deprecated": false, @@ -6079,7 +6167,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 210, + "weight": 211, "cookies": false, "type": "upload", "deprecated": false, @@ -6169,7 +6257,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 212, + "weight": 213, "cookies": false, "type": "", "deprecated": false, @@ -6239,7 +6327,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 217, + "weight": 218, "cookies": false, "type": "", "deprecated": false, @@ -6328,7 +6416,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 218, + "weight": 219, "cookies": false, "type": "", "deprecated": false, @@ -6398,7 +6486,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 214, + "weight": 215, "cookies": false, "type": "location", "deprecated": false, @@ -6477,7 +6565,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 213, + "weight": 214, "cookies": false, "type": "location", "deprecated": false, @@ -6683,7 +6771,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 215, + "weight": 216, "cookies": false, "type": "location", "deprecated": false, @@ -6762,7 +6850,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 222, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -6837,7 +6925,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 221, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -6927,7 +7015,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 223, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -6989,7 +7077,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 225, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -7064,7 +7152,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 227, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -7126,7 +7214,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 229, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -7209,7 +7297,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 228, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -7322,7 +7410,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 230, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -7392,7 +7480,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 231, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -7478,7 +7566,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 233, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -7550,7 +7638,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 232, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -7644,7 +7732,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 224, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -7705,7 +7793,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 226, + "weight": 227, "cookies": false, "type": "", "deprecated": false, diff --git a/app/config/specs/swagger2-1.7.x-console.json b/app/config/specs/swagger2-1.7.x-console.json index 3b92eceebd..96705f3e61 100644 --- a/app/config/specs/swagger2-1.7.x-console.json +++ b/app/config/specs/swagger2-1.7.x-console.json @@ -4527,7 +4527,7 @@ "x-appwrite": { "method": "chat", "group": "console", - "weight": 307, + "weight": 308, "cookies": false, "type": "", "deprecated": false, @@ -4590,7 +4590,7 @@ "x-appwrite": { "method": "getResource", "group": null, - "weight": 431, + "weight": 432, "cookies": false, "type": "", "deprecated": false, @@ -4661,7 +4661,7 @@ "x-appwrite": { "method": "variables", "group": "console", - "weight": 306, + "weight": 307, "cookies": false, "type": "", "deprecated": false, @@ -4863,7 +4863,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 118, + "weight": 119, "cookies": false, "type": "", "deprecated": false, @@ -8178,29 +8178,6 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." - }, - { - "name": "createDocuments", - "auth": { - "Key": [] - }, - "parameters": [ - "databaseId", - "collectionId", - "documents" - ], - "required": [ - "databaseId", - "collectionId", - "documents" - ], - "responses": [ - { - "code": 201, - "model": "#\/definitions\/documentList" - } - ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -8296,7 +8273,7 @@ "x-appwrite": { "method": "upsertDocuments", "group": "documents", - "weight": 115, + "weight": 116, "cookies": false, "type": "", "deprecated": false, @@ -8381,7 +8358,7 @@ "x-appwrite": { "method": "updateDocuments", "group": "documents", - "weight": 114, + "weight": 115, "cookies": false, "type": "", "deprecated": false, @@ -8472,7 +8449,7 @@ "x-appwrite": { "method": "deleteDocuments", "group": "documents", - "weight": 117, + "weight": 118, "cookies": false, "type": "", "deprecated": false, @@ -8623,6 +8600,111 @@ } ] }, + "put": { + "summary": "Upsert document", + "operationId": "databasesUpsertDocument", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "upsertDocument", + "group": "documents", + "weight": 114, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include all required attributes of the document to be created or updated.", + "default": {}, + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "data" + ] + } + } + ] + }, "patch": { "summary": "Update document", "operationId": "databasesUpdateDocument", @@ -8744,7 +8826,7 @@ "x-appwrite": { "method": "deleteDocument", "group": "documents", - "weight": 116, + "weight": 117, "cookies": false, "type": "", "deprecated": false, @@ -9335,7 +9417,7 @@ "x-appwrite": { "method": "getCollectionUsage", "group": null, - "weight": 120, + "weight": 121, "cookies": false, "type": "", "deprecated": false, @@ -9491,7 +9573,7 @@ "x-appwrite": { "method": "getDatabaseUsage", "group": null, - "weight": 119, + "weight": 120, "cookies": false, "type": "", "deprecated": false, @@ -9569,7 +9651,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 375, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -9641,7 +9723,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 372, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -9890,7 +9972,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 377, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -9939,7 +10021,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 378, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -9989,7 +10071,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 401, + "weight": 402, "cookies": false, "type": "", "deprecated": false, @@ -10083,7 +10165,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 400, + "weight": 401, "cookies": false, "type": "", "deprecated": false, @@ -10141,7 +10223,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 394, + "weight": 395, "cookies": false, "type": "", "deprecated": false, @@ -10211,7 +10293,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 373, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -10270,7 +10352,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 374, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -10515,7 +10597,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 376, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -10576,7 +10658,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 381, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -10653,7 +10735,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 382, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -10733,7 +10815,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 379, + "weight": 380, "cookies": false, "type": "upload", "deprecated": false, @@ -10825,7 +10907,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 387, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -10910,7 +10992,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 384, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -11016,7 +11098,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 385, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -11112,7 +11194,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 380, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -11174,7 +11256,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 383, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -11241,7 +11323,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 386, + "weight": 387, "cookies": false, "type": "location", "deprecated": false, @@ -11327,7 +11409,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 388, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -11394,7 +11476,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 391, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -11468,7 +11550,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 389, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -11585,7 +11667,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 390, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -11650,7 +11732,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 392, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -11717,7 +11799,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 393, + "weight": 394, "cookies": false, "type": "", "deprecated": false, @@ -11795,7 +11877,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 397, + "weight": 398, "cookies": false, "type": "", "deprecated": false, @@ -11854,7 +11936,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 395, + "weight": 396, "cookies": false, "type": "", "deprecated": false, @@ -11944,7 +12026,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 396, + "weight": 397, "cookies": false, "type": "", "deprecated": false, @@ -12011,7 +12093,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 398, + "weight": 399, "cookies": false, "type": "", "deprecated": false, @@ -12103,7 +12185,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 399, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -12172,7 +12254,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 305, + "weight": 306, "cookies": false, "type": "graphql", "deprecated": false, @@ -12246,7 +12328,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 304, + "weight": 305, "cookies": false, "type": "graphql", "deprecated": false, @@ -12318,7 +12400,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 129, + "weight": 130, "cookies": false, "type": "", "deprecated": false, @@ -12367,7 +12449,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 150, + "weight": 151, "cookies": false, "type": "", "deprecated": false, @@ -12416,7 +12498,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 132, + "weight": 133, "cookies": false, "type": "", "deprecated": false, @@ -12465,7 +12547,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 137, + "weight": 138, "cookies": false, "type": "", "deprecated": false, @@ -12523,7 +12605,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 131, + "weight": 132, "cookies": false, "type": "", "deprecated": false, @@ -12572,7 +12654,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 133, + "weight": 134, "cookies": false, "type": "", "deprecated": false, @@ -12621,7 +12703,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 139, + "weight": 140, "cookies": false, "type": "", "deprecated": false, @@ -12681,7 +12763,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 138, + "weight": 139, "cookies": false, "type": "", "deprecated": false, @@ -12741,7 +12823,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 140, + "weight": 141, "cookies": false, "type": "", "deprecated": false, @@ -12810,7 +12892,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 141, + "weight": 142, "cookies": false, "type": "", "deprecated": false, @@ -12870,7 +12952,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 151, + "weight": 152, "cookies": false, "type": "", "deprecated": false, @@ -12954,7 +13036,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 145, + "weight": 146, "cookies": false, "type": "", "deprecated": false, @@ -13014,7 +13096,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 136, + "weight": 137, "cookies": false, "type": "", "deprecated": false, @@ -13074,7 +13156,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 142, + "weight": 143, "cookies": false, "type": "", "deprecated": false, @@ -13134,7 +13216,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 143, + "weight": 144, "cookies": false, "type": "", "deprecated": false, @@ -13194,7 +13276,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 144, + "weight": 145, "cookies": false, "type": "", "deprecated": false, @@ -13254,7 +13336,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 146, + "weight": 147, "cookies": false, "type": "", "deprecated": false, @@ -13314,7 +13396,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 147, + "weight": 148, "cookies": false, "type": "", "deprecated": false, @@ -13374,7 +13456,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 135, + "weight": 136, "cookies": false, "type": "", "deprecated": false, @@ -13434,7 +13516,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 149, + "weight": 150, "cookies": false, "type": "", "deprecated": false, @@ -13483,7 +13565,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 148, + "weight": 149, "cookies": false, "type": "", "deprecated": false, @@ -13532,7 +13614,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 134, + "weight": 135, "cookies": false, "type": "", "deprecated": false, @@ -13581,7 +13663,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 121, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -13633,7 +13715,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 122, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -13685,7 +13767,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 126, + "weight": 127, "cookies": false, "type": "", "deprecated": false, @@ -13737,7 +13819,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 123, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -13789,7 +13871,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 124, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -13841,7 +13923,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 125, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -13893,7 +13975,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 127, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -13945,7 +14027,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 128, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -13997,7 +14079,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 359, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -14072,7 +14154,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 356, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -14230,7 +14312,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 363, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -14385,7 +14467,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 358, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -14580,7 +14662,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 365, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -14774,7 +14856,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 357, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -14892,7 +14974,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 364, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -15006,7 +15088,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 362, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -15061,7 +15143,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 366, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -15121,7 +15203,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 360, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -15193,7 +15275,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 361, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -15265,7 +15347,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 331, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -15340,7 +15422,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 330, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -15455,7 +15537,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 343, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -15568,7 +15650,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 329, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -15659,7 +15741,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 342, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -15748,7 +15830,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 321, + "weight": 322, "cookies": false, "type": "", "deprecated": false, @@ -15875,7 +15957,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 334, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -16000,7 +16082,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 324, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -16103,7 +16185,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 337, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -16204,7 +16286,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 322, + "weight": 323, "cookies": false, "type": "", "deprecated": false, @@ -16319,7 +16401,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 335, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -16432,7 +16514,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 323, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -16591,7 +16673,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 336, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -16747,7 +16829,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 325, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -16850,7 +16932,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 338, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -16951,7 +17033,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 326, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -17054,7 +17136,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 339, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -17155,7 +17237,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 327, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -17258,7 +17340,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 340, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -17359,7 +17441,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 328, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -17462,7 +17544,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 341, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -17561,7 +17643,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 333, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -17616,7 +17698,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 344, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -17676,7 +17758,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 332, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -17748,7 +17830,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 353, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -17820,7 +17902,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 346, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -17893,7 +17975,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 345, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -17981,7 +18063,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 348, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -18041,7 +18123,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 349, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -18120,7 +18202,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 350, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -18180,7 +18262,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 347, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -18252,7 +18334,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 352, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -18333,7 +18415,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 351, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -18421,7 +18503,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 354, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -18484,7 +18566,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 355, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -18555,7 +18637,7 @@ "x-appwrite": { "method": "list", "group": null, - "weight": 313, + "weight": 314, "cookies": false, "type": "", "deprecated": false, @@ -18628,7 +18710,7 @@ "x-appwrite": { "method": "createAppwriteMigration", "group": null, - "weight": 308, + "weight": 309, "cookies": false, "type": "", "deprecated": false, @@ -18720,7 +18802,7 @@ "x-appwrite": { "method": "getAppwriteReport", "group": null, - "weight": 315, + "weight": 316, "cookies": false, "type": "", "deprecated": false, @@ -18808,7 +18890,7 @@ "x-appwrite": { "method": "createCsvMigration", "group": null, - "weight": 312, + "weight": 313, "cookies": false, "type": "", "deprecated": false, @@ -18892,7 +18974,7 @@ "x-appwrite": { "method": "createFirebaseMigration", "group": null, - "weight": 309, + "weight": 310, "cookies": false, "type": "", "deprecated": false, @@ -18970,7 +19052,7 @@ "x-appwrite": { "method": "getFirebaseReport", "group": null, - "weight": 316, + "weight": 317, "cookies": false, "type": "", "deprecated": false, @@ -19041,7 +19123,7 @@ "x-appwrite": { "method": "createNHostMigration", "group": null, - "weight": 311, + "weight": 312, "cookies": false, "type": "", "deprecated": false, @@ -19160,7 +19242,7 @@ "x-appwrite": { "method": "getNHostReport", "group": null, - "weight": 318, + "weight": 319, "cookies": false, "type": "", "deprecated": false, @@ -19280,7 +19362,7 @@ "x-appwrite": { "method": "createSupabaseMigration", "group": null, - "weight": 310, + "weight": 311, "cookies": false, "type": "", "deprecated": false, @@ -19392,7 +19474,7 @@ "x-appwrite": { "method": "getSupabaseReport", "group": null, - "weight": 317, + "weight": 318, "cookies": false, "type": "", "deprecated": false, @@ -19503,7 +19585,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 314, + "weight": 315, "cookies": false, "type": "", "deprecated": false, @@ -19561,7 +19643,7 @@ "x-appwrite": { "method": "retry", "group": null, - "weight": 319, + "weight": 320, "cookies": false, "type": "", "deprecated": false, @@ -19614,7 +19696,7 @@ "x-appwrite": { "method": "delete", "group": null, - "weight": 320, + "weight": 321, "cookies": false, "type": "", "deprecated": false, @@ -19672,7 +19754,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 199, + "weight": 200, "cookies": false, "type": "", "deprecated": false, @@ -19754,7 +19836,7 @@ "x-appwrite": { "method": "listVariables", "group": null, - "weight": 201, + "weight": 202, "cookies": false, "type": "", "deprecated": false, @@ -19802,7 +19884,7 @@ "x-appwrite": { "method": "createVariable", "group": null, - "weight": 200, + "weight": 201, "cookies": false, "type": "", "deprecated": false, @@ -19883,7 +19965,7 @@ "x-appwrite": { "method": "getVariable", "group": null, - "weight": 202, + "weight": 203, "cookies": false, "type": "", "deprecated": false, @@ -19941,7 +20023,7 @@ "x-appwrite": { "method": "updateVariable", "group": null, - "weight": 203, + "weight": 204, "cookies": false, "type": "", "deprecated": false, @@ -20024,7 +20106,7 @@ "x-appwrite": { "method": "deleteVariable", "group": null, - "weight": 204, + "weight": 205, "cookies": false, "type": "", "deprecated": false, @@ -20082,7 +20164,7 @@ "x-appwrite": { "method": "list", "group": "projects", - "weight": 154, + "weight": 155, "cookies": false, "type": "", "deprecated": false, @@ -20153,7 +20235,7 @@ "x-appwrite": { "method": "create", "group": "projects", - "weight": 153, + "weight": 154, "cookies": false, "type": "", "deprecated": false, @@ -20300,7 +20382,7 @@ "x-appwrite": { "method": "get", "group": "projects", - "weight": 155, + "weight": 156, "cookies": false, "type": "", "deprecated": false, @@ -20358,7 +20440,7 @@ "x-appwrite": { "method": "update", "group": "projects", - "weight": 156, + "weight": 157, "cookies": false, "type": "", "deprecated": false, @@ -20483,7 +20565,7 @@ "x-appwrite": { "method": "delete", "group": "projects", - "weight": 173, + "weight": 174, "cookies": false, "type": "", "deprecated": false, @@ -20543,7 +20625,7 @@ "x-appwrite": { "method": "updateApiStatus", "group": "projects", - "weight": 160, + "weight": 161, "cookies": false, "type": "", "deprecated": false, @@ -20635,7 +20717,7 @@ "x-appwrite": { "method": "updateApiStatusAll", "group": "projects", - "weight": 161, + "weight": 162, "cookies": false, "type": "", "deprecated": false, @@ -20713,7 +20795,7 @@ "x-appwrite": { "method": "updateAuthDuration", "group": "auth", - "weight": 166, + "weight": 167, "cookies": false, "type": "", "deprecated": false, @@ -20791,7 +20873,7 @@ "x-appwrite": { "method": "updateAuthLimit", "group": "auth", - "weight": 165, + "weight": 166, "cookies": false, "type": "", "deprecated": false, @@ -20869,7 +20951,7 @@ "x-appwrite": { "method": "updateAuthSessionsLimit", "group": "auth", - "weight": 171, + "weight": 172, "cookies": false, "type": "", "deprecated": false, @@ -20947,7 +21029,7 @@ "x-appwrite": { "method": "updateMembershipsPrivacy", "group": "auth", - "weight": 164, + "weight": 165, "cookies": false, "type": "", "deprecated": false, @@ -21039,7 +21121,7 @@ "x-appwrite": { "method": "updateMockNumbers", "group": "auth", - "weight": 172, + "weight": 173, "cookies": false, "type": "", "deprecated": false, @@ -21120,7 +21202,7 @@ "x-appwrite": { "method": "updateAuthPasswordDictionary", "group": "auth", - "weight": 169, + "weight": 170, "cookies": false, "type": "", "deprecated": false, @@ -21198,7 +21280,7 @@ "x-appwrite": { "method": "updateAuthPasswordHistory", "group": "auth", - "weight": 168, + "weight": 169, "cookies": false, "type": "", "deprecated": false, @@ -21276,7 +21358,7 @@ "x-appwrite": { "method": "updatePersonalDataCheck", "group": "auth", - "weight": 170, + "weight": 171, "cookies": false, "type": "", "deprecated": false, @@ -21354,7 +21436,7 @@ "x-appwrite": { "method": "updateSessionAlerts", "group": "auth", - "weight": 163, + "weight": 164, "cookies": false, "type": "", "deprecated": false, @@ -21432,7 +21514,7 @@ "x-appwrite": { "method": "updateAuthStatus", "group": "auth", - "weight": 167, + "weight": 168, "cookies": false, "type": "", "deprecated": false, @@ -21527,7 +21609,7 @@ "x-appwrite": { "method": "listDevKeys", "group": "devKeys", - "weight": 370, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -21597,7 +21679,7 @@ "x-appwrite": { "method": "createDevKey", "group": "devKeys", - "weight": 367, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -21680,7 +21762,7 @@ "x-appwrite": { "method": "getDevKey", "group": "devKeys", - "weight": 369, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -21746,7 +21828,7 @@ "x-appwrite": { "method": "updateDevKey", "group": "devKeys", - "weight": 368, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -21832,7 +21914,7 @@ "x-appwrite": { "method": "deleteDevKey", "group": "devKeys", - "weight": 371, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -21900,7 +21982,7 @@ "x-appwrite": { "method": "createJWT", "group": "auth", - "weight": 185, + "weight": 186, "cookies": false, "type": "", "deprecated": false, @@ -21985,7 +22067,7 @@ "x-appwrite": { "method": "listKeys", "group": "keys", - "weight": 181, + "weight": 182, "cookies": false, "type": "", "deprecated": false, @@ -22043,7 +22125,7 @@ "x-appwrite": { "method": "createKey", "group": "keys", - "weight": 180, + "weight": 181, "cookies": false, "type": "", "deprecated": false, @@ -22135,7 +22217,7 @@ "x-appwrite": { "method": "getKey", "group": "keys", - "weight": 182, + "weight": 183, "cookies": false, "type": "", "deprecated": false, @@ -22201,7 +22283,7 @@ "x-appwrite": { "method": "updateKey", "group": "keys", - "weight": 183, + "weight": 184, "cookies": false, "type": "", "deprecated": false, @@ -22296,7 +22378,7 @@ "x-appwrite": { "method": "deleteKey", "group": "keys", - "weight": 184, + "weight": 185, "cookies": false, "type": "", "deprecated": false, @@ -22364,7 +22446,7 @@ "x-appwrite": { "method": "updateOAuth2", "group": "auth", - "weight": 162, + "weight": 163, "cookies": false, "type": "", "deprecated": false, @@ -22502,7 +22584,7 @@ "x-appwrite": { "method": "listPlatforms", "group": "platforms", - "weight": 187, + "weight": 188, "cookies": false, "type": "", "deprecated": false, @@ -22560,7 +22642,7 @@ "x-appwrite": { "method": "createPlatform", "group": "platforms", - "weight": 186, + "weight": 187, "cookies": false, "type": "", "deprecated": false, @@ -22680,7 +22762,7 @@ "x-appwrite": { "method": "getPlatform", "group": "platforms", - "weight": 188, + "weight": 189, "cookies": false, "type": "", "deprecated": false, @@ -22746,7 +22828,7 @@ "x-appwrite": { "method": "updatePlatform", "group": "platforms", - "weight": 189, + "weight": 190, "cookies": false, "type": "", "deprecated": false, @@ -22843,7 +22925,7 @@ "x-appwrite": { "method": "deletePlatform", "group": "platforms", - "weight": 190, + "weight": 191, "cookies": false, "type": "", "deprecated": false, @@ -22911,7 +22993,7 @@ "x-appwrite": { "method": "updateServiceStatus", "group": "projects", - "weight": 158, + "weight": 159, "cookies": false, "type": "", "deprecated": false, @@ -23012,7 +23094,7 @@ "x-appwrite": { "method": "updateServiceStatusAll", "group": "projects", - "weight": 159, + "weight": 160, "cookies": false, "type": "", "deprecated": false, @@ -23090,7 +23172,7 @@ "x-appwrite": { "method": "updateSmtp", "group": "templates", - "weight": 191, + "weight": 192, "cookies": false, "type": "", "deprecated": false, @@ -23219,7 +23301,7 @@ "x-appwrite": { "method": "createSmtpTest", "group": "templates", - "weight": 192, + "weight": 193, "cookies": false, "type": "", "deprecated": false, @@ -23357,7 +23439,7 @@ "x-appwrite": { "method": "updateTeam", "group": "projects", - "weight": 157, + "weight": 158, "cookies": false, "type": "", "deprecated": false, @@ -23433,7 +23515,7 @@ "x-appwrite": { "method": "getEmailTemplate", "group": "templates", - "weight": 194, + "weight": 195, "cookies": false, "type": "", "deprecated": false, @@ -23653,7 +23735,7 @@ "x-appwrite": { "method": "updateEmailTemplate", "group": "templates", - "weight": 196, + "weight": 197, "cookies": false, "type": "", "deprecated": false, @@ -23916,7 +23998,7 @@ "x-appwrite": { "method": "deleteEmailTemplate", "group": "templates", - "weight": 198, + "weight": 199, "cookies": false, "type": "", "deprecated": false, @@ -24136,7 +24218,7 @@ "x-appwrite": { "method": "getSmsTemplate", "group": "templates", - "weight": 193, + "weight": 194, "cookies": false, "type": "", "deprecated": false, @@ -24353,7 +24435,7 @@ "x-appwrite": { "method": "updateSmsTemplate", "group": "templates", - "weight": 195, + "weight": 196, "cookies": false, "type": "", "deprecated": false, @@ -24588,7 +24670,7 @@ "x-appwrite": { "method": "deleteSmsTemplate", "group": "templates", - "weight": 197, + "weight": 198, "cookies": false, "type": "", "deprecated": false, @@ -24805,7 +24887,7 @@ "x-appwrite": { "method": "listWebhooks", "group": "webhooks", - "weight": 175, + "weight": 176, "cookies": false, "type": "", "deprecated": false, @@ -24863,7 +24945,7 @@ "x-appwrite": { "method": "createWebhook", "group": "webhooks", - "weight": 174, + "weight": 175, "cookies": false, "type": "", "deprecated": false, @@ -24981,7 +25063,7 @@ "x-appwrite": { "method": "getWebhook", "group": "webhooks", - "weight": 176, + "weight": 177, "cookies": false, "type": "", "deprecated": false, @@ -25047,7 +25129,7 @@ "x-appwrite": { "method": "updateWebhook", "group": "webhooks", - "weight": 177, + "weight": 178, "cookies": false, "type": "", "deprecated": false, @@ -25168,7 +25250,7 @@ "x-appwrite": { "method": "deleteWebhook", "group": "webhooks", - "weight": 179, + "weight": 180, "cookies": false, "type": "", "deprecated": false, @@ -25236,7 +25318,7 @@ "x-appwrite": { "method": "updateWebhookSignature", "group": "webhooks", - "weight": 178, + "weight": 179, "cookies": false, "type": "", "deprecated": false, @@ -25302,7 +25384,7 @@ "x-appwrite": { "method": "listRules", "group": null, - "weight": 291, + "weight": 292, "cookies": false, "type": "", "deprecated": false, @@ -25375,7 +25457,7 @@ "x-appwrite": { "method": "createAPIRule", "group": null, - "weight": 432, + "weight": 433, "cookies": false, "type": "", "deprecated": false, @@ -25445,7 +25527,7 @@ "x-appwrite": { "method": "createFunctionRule", "group": null, - "weight": 434, + "weight": 435, "cookies": false, "type": "", "deprecated": false, @@ -25528,7 +25610,7 @@ "x-appwrite": { "method": "createRedirectRule", "group": null, - "weight": 435, + "weight": 436, "cookies": false, "type": "", "deprecated": false, @@ -25625,7 +25707,7 @@ "x-appwrite": { "method": "createSiteRule", "group": null, - "weight": 433, + "weight": 434, "cookies": false, "type": "", "deprecated": false, @@ -25706,7 +25788,7 @@ "x-appwrite": { "method": "getRule", "group": null, - "weight": 292, + "weight": 293, "cookies": false, "type": "", "deprecated": false, @@ -25759,7 +25841,7 @@ "x-appwrite": { "method": "deleteRule", "group": null, - "weight": 293, + "weight": 294, "cookies": false, "type": "", "deprecated": false, @@ -25819,7 +25901,7 @@ "x-appwrite": { "method": "updateRuleVerification", "group": null, - "weight": 294, + "weight": 295, "cookies": false, "type": "", "deprecated": false, @@ -25877,7 +25959,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 404, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -25949,7 +26031,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 402, + "weight": 403, "cookies": false, "type": "", "deprecated": false, @@ -26214,7 +26296,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 407, + "weight": 408, "cookies": false, "type": "", "deprecated": false, @@ -26263,7 +26345,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 430, + "weight": 431, "cookies": false, "type": "", "deprecated": false, @@ -26313,7 +26395,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 426, + "weight": 427, "cookies": false, "type": "", "deprecated": false, @@ -26407,7 +26489,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 427, + "weight": 428, "cookies": false, "type": "", "deprecated": false, @@ -26465,7 +26547,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 428, + "weight": 429, "cookies": false, "type": "", "deprecated": false, @@ -26535,7 +26617,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 403, + "weight": 404, "cookies": false, "type": "", "deprecated": false, @@ -26594,7 +26676,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 405, + "weight": 406, "cookies": false, "type": "", "deprecated": false, @@ -26854,7 +26936,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 406, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -26915,7 +26997,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 413, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -26992,7 +27074,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 412, + "weight": 413, "cookies": false, "type": "", "deprecated": false, @@ -27072,7 +27154,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 408, + "weight": 409, "cookies": false, "type": "upload", "deprecated": false, @@ -27172,7 +27254,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 416, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -27251,7 +27333,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 409, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -27357,7 +27439,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 410, + "weight": 411, "cookies": false, "type": "", "deprecated": false, @@ -27454,7 +27536,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 411, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -27516,7 +27598,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 414, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -27583,7 +27665,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 415, + "weight": 416, "cookies": false, "type": "location", "deprecated": false, @@ -27669,7 +27751,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 417, + "weight": 418, "cookies": false, "type": "", "deprecated": false, @@ -27736,7 +27818,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 419, + "weight": 420, "cookies": false, "type": "", "deprecated": false, @@ -27807,7 +27889,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 418, + "weight": 419, "cookies": false, "type": "", "deprecated": false, @@ -27871,7 +27953,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 420, + "weight": 421, "cookies": false, "type": "", "deprecated": false, @@ -27938,7 +28020,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 429, + "weight": 430, "cookies": false, "type": "", "deprecated": false, @@ -28016,7 +28098,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 423, + "weight": 424, "cookies": false, "type": "", "deprecated": false, @@ -28075,7 +28157,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 421, + "weight": 422, "cookies": false, "type": "", "deprecated": false, @@ -28165,7 +28247,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 422, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -28232,7 +28314,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 424, + "weight": 425, "cookies": false, "type": "", "deprecated": false, @@ -28324,7 +28406,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 425, + "weight": 426, "cookies": false, "type": "", "deprecated": false, @@ -28391,7 +28473,7 @@ "x-appwrite": { "method": "listBuckets", "group": "buckets", - "weight": 206, + "weight": 207, "cookies": false, "type": "", "deprecated": false, @@ -28463,7 +28545,7 @@ "x-appwrite": { "method": "createBucket", "group": "buckets", - "weight": 205, + "weight": 206, "cookies": false, "type": "", "deprecated": false, @@ -28600,7 +28682,7 @@ "x-appwrite": { "method": "getBucket", "group": "buckets", - "weight": 207, + "weight": 208, "cookies": false, "type": "", "deprecated": false, @@ -28659,7 +28741,7 @@ "x-appwrite": { "method": "updateBucket", "group": "buckets", - "weight": 208, + "weight": 209, "cookies": false, "type": "", "deprecated": false, @@ -28792,7 +28874,7 @@ "x-appwrite": { "method": "deleteBucket", "group": "buckets", - "weight": 209, + "weight": 210, "cookies": false, "type": "", "deprecated": false, @@ -28851,7 +28933,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 211, + "weight": 212, "cookies": false, "type": "", "deprecated": false, @@ -28934,7 +29016,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 210, + "weight": 211, "cookies": false, "type": "upload", "deprecated": false, @@ -29024,7 +29106,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 212, + "weight": 213, "cookies": false, "type": "", "deprecated": false, @@ -29094,7 +29176,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 217, + "weight": 218, "cookies": false, "type": "", "deprecated": false, @@ -29183,7 +29265,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 218, + "weight": 219, "cookies": false, "type": "", "deprecated": false, @@ -29253,7 +29335,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 214, + "weight": 215, "cookies": false, "type": "location", "deprecated": false, @@ -29332,7 +29414,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 213, + "weight": 214, "cookies": false, "type": "location", "deprecated": false, @@ -29538,7 +29620,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 215, + "weight": 216, "cookies": false, "type": "location", "deprecated": false, @@ -29617,7 +29699,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 219, + "weight": 220, "cookies": false, "type": "", "deprecated": false, @@ -29687,7 +29769,7 @@ "x-appwrite": { "method": "getBucketUsage", "group": null, - "weight": 220, + "weight": 221, "cookies": false, "type": "", "deprecated": false, @@ -29765,7 +29847,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 222, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -29840,7 +29922,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 221, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -29930,7 +30012,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 223, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -29992,7 +30074,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 225, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -30067,7 +30149,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 227, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -30129,7 +30211,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 234, + "weight": 235, "cookies": false, "type": "", "deprecated": false, @@ -30199,7 +30281,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 229, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -30282,7 +30364,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 228, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -30395,7 +30477,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 230, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -30465,7 +30547,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 231, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -30551,7 +30633,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 233, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -30623,7 +30705,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 232, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -30716,7 +30798,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 224, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -30776,7 +30858,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 226, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -30854,7 +30936,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 438, + "weight": 439, "cookies": false, "type": "", "deprecated": false, @@ -30934,7 +31016,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 436, + "weight": 437, "cookies": false, "type": "", "deprecated": false, @@ -31018,7 +31100,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 437, + "weight": 438, "cookies": false, "type": "", "deprecated": false, @@ -31078,7 +31160,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 439, + "weight": 440, "cookies": false, "type": "", "deprecated": false, @@ -31149,7 +31231,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 440, + "weight": 441, "cookies": false, "type": "", "deprecated": false, @@ -31209,7 +31291,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 244, + "weight": 245, "cookies": false, "type": "", "deprecated": false, @@ -31281,7 +31363,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 235, + "weight": 236, "cookies": false, "type": "", "deprecated": false, @@ -31376,7 +31458,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 238, + "weight": 239, "cookies": false, "type": "", "deprecated": false, @@ -31467,7 +31549,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 236, + "weight": 237, "cookies": false, "type": "", "deprecated": false, @@ -31556,7 +31638,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 252, + "weight": 253, "cookies": false, "type": "", "deprecated": false, @@ -31625,7 +31707,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 275, + "weight": 276, "cookies": false, "type": "", "deprecated": false, @@ -31686,7 +31768,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 237, + "weight": 238, "cookies": false, "type": "", "deprecated": false, @@ -31777,7 +31859,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 240, + "weight": 241, "cookies": false, "type": "", "deprecated": false, @@ -31868,7 +31950,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 241, + "weight": 242, "cookies": false, "type": "", "deprecated": false, @@ -31994,7 +32076,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 242, + "weight": 243, "cookies": false, "type": "", "deprecated": false, @@ -32106,7 +32188,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 239, + "weight": 240, "cookies": false, "type": "", "deprecated": false, @@ -32216,7 +32298,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 277, + "weight": 278, "cookies": false, "type": "", "deprecated": false, @@ -32286,7 +32368,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 245, + "weight": 246, "cookies": false, "type": "", "deprecated": false, @@ -32340,7 +32422,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 273, + "weight": 274, "cookies": false, "type": "", "deprecated": false, @@ -32401,7 +32483,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 258, + "weight": 259, "cookies": false, "type": "", "deprecated": false, @@ -32480,7 +32562,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 276, + "weight": 277, "cookies": false, "type": "", "deprecated": false, @@ -32562,7 +32644,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 254, + "weight": 255, "cookies": false, "type": "", "deprecated": false, @@ -32642,7 +32724,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 250, + "weight": 251, "cookies": false, "type": "", "deprecated": false, @@ -32713,7 +32795,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 249, + "weight": 250, "cookies": false, "type": "", "deprecated": false, @@ -32795,7 +32877,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 263, + "weight": 264, "cookies": false, "type": "", "deprecated": false, @@ -32869,7 +32951,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 268, + "weight": 269, "cookies": false, "type": "", "deprecated": false, @@ -32941,7 +33023,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 264, + "weight": 265, "cookies": false, "type": "", "deprecated": false, @@ -33000,7 +33082,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 265, + "weight": 266, "cookies": false, "type": "", "deprecated": false, @@ -33059,7 +33141,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 267, + "weight": 268, "cookies": false, "type": "", "deprecated": false, @@ -33118,7 +33200,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 266, + "weight": 267, "cookies": false, "type": "", "deprecated": false, @@ -33179,7 +33261,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 256, + "weight": 257, "cookies": false, "type": "", "deprecated": false, @@ -33258,7 +33340,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 257, + "weight": 258, "cookies": false, "type": "", "deprecated": false, @@ -33337,7 +33419,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 259, + "weight": 260, "cookies": false, "type": "", "deprecated": false, @@ -33414,7 +33496,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 246, + "weight": 247, "cookies": false, "type": "", "deprecated": false, @@ -33473,7 +33555,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 261, + "weight": 262, "cookies": false, "type": "", "deprecated": false, @@ -33550,7 +33632,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 248, + "weight": 249, "cookies": false, "type": "", "deprecated": false, @@ -33609,7 +33691,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 269, + "weight": 270, "cookies": false, "type": "", "deprecated": false, @@ -33663,7 +33745,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 272, + "weight": 273, "cookies": false, "type": "", "deprecated": false, @@ -33719,7 +33801,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 271, + "weight": 272, "cookies": false, "type": "", "deprecated": false, @@ -33788,7 +33870,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 253, + "weight": 254, "cookies": false, "type": "", "deprecated": false, @@ -33865,7 +33947,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 251, + "weight": 252, "cookies": false, "type": "", "deprecated": false, @@ -33937,7 +34019,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 243, + "weight": 244, "cookies": false, "type": "", "deprecated": false, @@ -34048,7 +34130,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 247, + "weight": 248, "cookies": false, "type": "", "deprecated": false, @@ -34116,7 +34198,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 262, + "weight": 263, "cookies": false, "type": "", "deprecated": false, @@ -34206,7 +34288,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 274, + "weight": 275, "cookies": false, "type": "", "deprecated": false, @@ -34276,7 +34358,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 270, + "weight": 271, "cookies": false, "type": "", "deprecated": false, @@ -34358,7 +34440,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 260, + "weight": 261, "cookies": false, "type": "", "deprecated": false, @@ -34437,7 +34519,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 255, + "weight": 256, "cookies": false, "type": "", "deprecated": false, @@ -34516,7 +34598,7 @@ "x-appwrite": { "method": "createRepositoryDetection", "group": "repositories", - "weight": 281, + "weight": 282, "cookies": false, "type": "", "deprecated": false, @@ -34611,7 +34693,7 @@ "x-appwrite": { "method": "listRepositories", "group": "repositories", - "weight": 282, + "weight": 283, "cookies": false, "type": "", "deprecated": false, @@ -34692,7 +34774,7 @@ "x-appwrite": { "method": "createRepository", "group": "repositories", - "weight": 283, + "weight": 284, "cookies": false, "type": "", "deprecated": false, @@ -34775,7 +34857,7 @@ "x-appwrite": { "method": "getRepository", "group": "repositories", - "weight": 284, + "weight": 285, "cookies": false, "type": "", "deprecated": false, @@ -34841,7 +34923,7 @@ "x-appwrite": { "method": "listRepositoryBranches", "group": "repositories", - "weight": 285, + "weight": 286, "cookies": false, "type": "", "deprecated": false, @@ -34907,7 +34989,7 @@ "x-appwrite": { "method": "getRepositoryContents", "group": "repositories", - "weight": 280, + "weight": 281, "cookies": false, "type": "", "deprecated": false, @@ -34981,7 +35063,7 @@ "x-appwrite": { "method": "updateExternalDeployments", "group": "repositories", - "weight": 290, + "weight": 291, "cookies": false, "type": "", "deprecated": false, @@ -35065,7 +35147,7 @@ "x-appwrite": { "method": "listInstallations", "group": "installations", - "weight": 287, + "weight": 288, "cookies": false, "type": "", "deprecated": false, @@ -35136,7 +35218,7 @@ "x-appwrite": { "method": "getInstallation", "group": "installations", - "weight": 288, + "weight": 289, "cookies": false, "type": "", "deprecated": false, @@ -35189,7 +35271,7 @@ "x-appwrite": { "method": "deleteInstallation", "group": "installations", - "weight": 289, + "weight": 290, "cookies": false, "type": "", "deprecated": false, diff --git a/app/config/specs/swagger2-1.7.x-server.json b/app/config/specs/swagger2-1.7.x-server.json index 07e1107789..c033008417 100644 --- a/app/config/specs/swagger2-1.7.x-server.json +++ b/app/config/specs/swagger2-1.7.x-server.json @@ -7649,29 +7649,6 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." - }, - { - "name": "createDocuments", - "auth": { - "Key": [] - }, - "parameters": [ - "databaseId", - "collectionId", - "documents" - ], - "required": [ - "databaseId", - "collectionId", - "documents" - ], - "responses": [ - { - "code": 201, - "model": "#\/definitions\/documentList" - } - ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -7769,7 +7746,7 @@ "x-appwrite": { "method": "upsertDocuments", "group": "documents", - "weight": 115, + "weight": 116, "cookies": false, "type": "", "deprecated": false, @@ -7855,7 +7832,7 @@ "x-appwrite": { "method": "updateDocuments", "group": "documents", - "weight": 114, + "weight": 115, "cookies": false, "type": "", "deprecated": false, @@ -7947,7 +7924,7 @@ "x-appwrite": { "method": "deleteDocuments", "group": "documents", - "weight": 117, + "weight": 118, "cookies": false, "type": "", "deprecated": false, @@ -8101,6 +8078,113 @@ } ] }, + "put": { + "summary": "Upsert document", + "operationId": "databasesUpsertDocument", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "upsertDocument", + "group": "documents", + "weight": 114, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include all required attributes of the document to be created or updated.", + "default": {}, + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "data" + ] + } + } + ] + }, "patch": { "summary": "Update document", "operationId": "databasesUpdateDocument", @@ -8224,7 +8308,7 @@ "x-appwrite": { "method": "deleteDocument", "group": "documents", - "weight": 116, + "weight": 117, "cookies": false, "type": "", "deprecated": false, @@ -8657,7 +8741,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 375, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -8730,7 +8814,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 372, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -8980,7 +9064,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 377, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -9030,7 +9114,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 378, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -9081,7 +9165,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 373, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -9141,7 +9225,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 374, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -9387,7 +9471,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 376, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -9449,7 +9533,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 381, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -9527,7 +9611,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 382, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -9608,7 +9692,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 379, + "weight": 380, "cookies": false, "type": "upload", "deprecated": false, @@ -9701,7 +9785,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 387, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -9787,7 +9871,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 384, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -9894,7 +9978,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 385, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -9991,7 +10075,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 380, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -10054,7 +10138,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 383, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -10122,7 +10206,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 386, + "weight": 387, "cookies": false, "type": "location", "deprecated": false, @@ -10209,7 +10293,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 388, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -10277,7 +10361,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 391, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -10353,7 +10437,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 389, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -10472,7 +10556,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 390, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -10539,7 +10623,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 392, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -10607,7 +10691,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 397, + "weight": 398, "cookies": false, "type": "", "deprecated": false, @@ -10667,7 +10751,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 395, + "weight": 396, "cookies": false, "type": "", "deprecated": false, @@ -10758,7 +10842,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 396, + "weight": 397, "cookies": false, "type": "", "deprecated": false, @@ -10826,7 +10910,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 398, + "weight": 399, "cookies": false, "type": "", "deprecated": false, @@ -10919,7 +11003,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 399, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -10989,7 +11073,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 305, + "weight": 306, "cookies": false, "type": "graphql", "deprecated": false, @@ -11065,7 +11149,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 304, + "weight": 305, "cookies": false, "type": "graphql", "deprecated": false, @@ -11139,7 +11223,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 129, + "weight": 130, "cookies": false, "type": "", "deprecated": false, @@ -11189,7 +11273,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 150, + "weight": 151, "cookies": false, "type": "", "deprecated": false, @@ -11239,7 +11323,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 132, + "weight": 133, "cookies": false, "type": "", "deprecated": false, @@ -11289,7 +11373,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 137, + "weight": 138, "cookies": false, "type": "", "deprecated": false, @@ -11348,7 +11432,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 131, + "weight": 132, "cookies": false, "type": "", "deprecated": false, @@ -11398,7 +11482,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 133, + "weight": 134, "cookies": false, "type": "", "deprecated": false, @@ -11448,7 +11532,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 139, + "weight": 140, "cookies": false, "type": "", "deprecated": false, @@ -11509,7 +11593,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 138, + "weight": 139, "cookies": false, "type": "", "deprecated": false, @@ -11570,7 +11654,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 140, + "weight": 141, "cookies": false, "type": "", "deprecated": false, @@ -11640,7 +11724,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 141, + "weight": 142, "cookies": false, "type": "", "deprecated": false, @@ -11701,7 +11785,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 151, + "weight": 152, "cookies": false, "type": "", "deprecated": false, @@ -11786,7 +11870,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 145, + "weight": 146, "cookies": false, "type": "", "deprecated": false, @@ -11847,7 +11931,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 136, + "weight": 137, "cookies": false, "type": "", "deprecated": false, @@ -11908,7 +11992,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 142, + "weight": 143, "cookies": false, "type": "", "deprecated": false, @@ -11969,7 +12053,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 143, + "weight": 144, "cookies": false, "type": "", "deprecated": false, @@ -12030,7 +12114,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 144, + "weight": 145, "cookies": false, "type": "", "deprecated": false, @@ -12091,7 +12175,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 146, + "weight": 147, "cookies": false, "type": "", "deprecated": false, @@ -12152,7 +12236,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 147, + "weight": 148, "cookies": false, "type": "", "deprecated": false, @@ -12213,7 +12297,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 135, + "weight": 136, "cookies": false, "type": "", "deprecated": false, @@ -12274,7 +12358,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 149, + "weight": 150, "cookies": false, "type": "", "deprecated": false, @@ -12324,7 +12408,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 148, + "weight": 149, "cookies": false, "type": "", "deprecated": false, @@ -12374,7 +12458,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 134, + "weight": 135, "cookies": false, "type": "", "deprecated": false, @@ -12424,7 +12508,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 121, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -12478,7 +12562,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 122, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -12532,7 +12616,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 126, + "weight": 127, "cookies": false, "type": "", "deprecated": false, @@ -12586,7 +12670,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 123, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -12640,7 +12724,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 124, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -12694,7 +12778,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 125, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -12748,7 +12832,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 127, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -12802,7 +12886,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 128, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -12856,7 +12940,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 359, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -12932,7 +13016,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 356, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -13091,7 +13175,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 363, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -13247,7 +13331,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 358, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -13443,7 +13527,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 365, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -13638,7 +13722,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 357, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -13757,7 +13841,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 364, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -13872,7 +13956,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 362, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -13928,7 +14012,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 366, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -13989,7 +14073,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 360, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -14062,7 +14146,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 361, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -14135,7 +14219,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 331, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -14211,7 +14295,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 330, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -14327,7 +14411,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 343, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -14441,7 +14525,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 329, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -14533,7 +14617,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 342, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -14623,7 +14707,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 321, + "weight": 322, "cookies": false, "type": "", "deprecated": false, @@ -14751,7 +14835,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 334, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -14877,7 +14961,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 324, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -14981,7 +15065,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 337, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -15083,7 +15167,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 322, + "weight": 323, "cookies": false, "type": "", "deprecated": false, @@ -15199,7 +15283,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 335, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -15313,7 +15397,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 323, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -15473,7 +15557,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 336, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -15630,7 +15714,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 325, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -15734,7 +15818,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 338, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -15836,7 +15920,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 326, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -15940,7 +16024,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 339, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -16042,7 +16126,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 327, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -16146,7 +16230,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 340, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -16248,7 +16332,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 328, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -16352,7 +16436,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 341, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -16452,7 +16536,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 333, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -16508,7 +16592,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 344, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -16569,7 +16653,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 332, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -16642,7 +16726,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 353, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -16715,7 +16799,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 346, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -16789,7 +16873,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 345, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -16878,7 +16962,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 348, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -16939,7 +17023,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 349, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -17019,7 +17103,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 350, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -17080,7 +17164,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 347, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -17153,7 +17237,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 352, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -17235,7 +17319,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 351, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -17325,7 +17409,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 354, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -17389,7 +17473,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 355, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -17462,7 +17546,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 404, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -17535,7 +17619,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 402, + "weight": 403, "cookies": false, "type": "", "deprecated": false, @@ -17801,7 +17885,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 407, + "weight": 408, "cookies": false, "type": "", "deprecated": false, @@ -17851,7 +17935,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 430, + "weight": 431, "cookies": false, "type": "", "deprecated": false, @@ -17902,7 +17986,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 403, + "weight": 404, "cookies": false, "type": "", "deprecated": false, @@ -17962,7 +18046,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 405, + "weight": 406, "cookies": false, "type": "", "deprecated": false, @@ -18223,7 +18307,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 406, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -18285,7 +18369,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 413, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -18363,7 +18447,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 412, + "weight": 413, "cookies": false, "type": "", "deprecated": false, @@ -18444,7 +18528,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 408, + "weight": 409, "cookies": false, "type": "upload", "deprecated": false, @@ -18545,7 +18629,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 416, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -18625,7 +18709,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 409, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -18732,7 +18816,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 410, + "weight": 411, "cookies": false, "type": "", "deprecated": false, @@ -18830,7 +18914,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 411, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -18893,7 +18977,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 414, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -18961,7 +19045,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 415, + "weight": 416, "cookies": false, "type": "location", "deprecated": false, @@ -19048,7 +19132,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 417, + "weight": 418, "cookies": false, "type": "", "deprecated": false, @@ -19116,7 +19200,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 419, + "weight": 420, "cookies": false, "type": "", "deprecated": false, @@ -19188,7 +19272,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 418, + "weight": 419, "cookies": false, "type": "", "deprecated": false, @@ -19253,7 +19337,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 420, + "weight": 421, "cookies": false, "type": "", "deprecated": false, @@ -19321,7 +19405,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 423, + "weight": 424, "cookies": false, "type": "", "deprecated": false, @@ -19381,7 +19465,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 421, + "weight": 422, "cookies": false, "type": "", "deprecated": false, @@ -19472,7 +19556,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 422, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -19540,7 +19624,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 424, + "weight": 425, "cookies": false, "type": "", "deprecated": false, @@ -19633,7 +19717,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 425, + "weight": 426, "cookies": false, "type": "", "deprecated": false, @@ -19701,7 +19785,7 @@ "x-appwrite": { "method": "listBuckets", "group": "buckets", - "weight": 206, + "weight": 207, "cookies": false, "type": "", "deprecated": false, @@ -19774,7 +19858,7 @@ "x-appwrite": { "method": "createBucket", "group": "buckets", - "weight": 205, + "weight": 206, "cookies": false, "type": "", "deprecated": false, @@ -19912,7 +19996,7 @@ "x-appwrite": { "method": "getBucket", "group": "buckets", - "weight": 207, + "weight": 208, "cookies": false, "type": "", "deprecated": false, @@ -19972,7 +20056,7 @@ "x-appwrite": { "method": "updateBucket", "group": "buckets", - "weight": 208, + "weight": 209, "cookies": false, "type": "", "deprecated": false, @@ -20106,7 +20190,7 @@ "x-appwrite": { "method": "deleteBucket", "group": "buckets", - "weight": 209, + "weight": 210, "cookies": false, "type": "", "deprecated": false, @@ -20166,7 +20250,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 211, + "weight": 212, "cookies": false, "type": "", "deprecated": false, @@ -20251,7 +20335,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 210, + "weight": 211, "cookies": false, "type": "upload", "deprecated": false, @@ -20343,7 +20427,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 212, + "weight": 213, "cookies": false, "type": "", "deprecated": false, @@ -20415,7 +20499,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 217, + "weight": 218, "cookies": false, "type": "", "deprecated": false, @@ -20506,7 +20590,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 218, + "weight": 219, "cookies": false, "type": "", "deprecated": false, @@ -20578,7 +20662,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 214, + "weight": 215, "cookies": false, "type": "location", "deprecated": false, @@ -20659,7 +20743,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 213, + "weight": 214, "cookies": false, "type": "location", "deprecated": false, @@ -20867,7 +20951,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 215, + "weight": 216, "cookies": false, "type": "location", "deprecated": false, @@ -20948,7 +21032,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 222, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -21025,7 +21109,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 221, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -21117,7 +21201,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 223, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -21181,7 +21265,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 225, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -21258,7 +21342,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 227, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -21322,7 +21406,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 229, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -21407,7 +21491,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 228, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -21522,7 +21606,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 230, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -21594,7 +21678,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 231, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -21682,7 +21766,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 233, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -21756,7 +21840,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 232, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -21851,7 +21935,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 224, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -21913,7 +21997,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 226, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -21993,7 +22077,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 438, + "weight": 439, "cookies": false, "type": "", "deprecated": false, @@ -22074,7 +22158,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 436, + "weight": 437, "cookies": false, "type": "", "deprecated": false, @@ -22159,7 +22243,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 437, + "weight": 438, "cookies": false, "type": "", "deprecated": false, @@ -22220,7 +22304,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 439, + "weight": 440, "cookies": false, "type": "", "deprecated": false, @@ -22292,7 +22376,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 440, + "weight": 441, "cookies": false, "type": "", "deprecated": false, @@ -22353,7 +22437,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 244, + "weight": 245, "cookies": false, "type": "", "deprecated": false, @@ -22426,7 +22510,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 235, + "weight": 236, "cookies": false, "type": "", "deprecated": false, @@ -22522,7 +22606,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 238, + "weight": 239, "cookies": false, "type": "", "deprecated": false, @@ -22614,7 +22698,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 236, + "weight": 237, "cookies": false, "type": "", "deprecated": false, @@ -22704,7 +22788,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 252, + "weight": 253, "cookies": false, "type": "", "deprecated": false, @@ -22774,7 +22858,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 275, + "weight": 276, "cookies": false, "type": "", "deprecated": false, @@ -22836,7 +22920,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 237, + "weight": 238, "cookies": false, "type": "", "deprecated": false, @@ -22928,7 +23012,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 240, + "weight": 241, "cookies": false, "type": "", "deprecated": false, @@ -23020,7 +23104,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 241, + "weight": 242, "cookies": false, "type": "", "deprecated": false, @@ -23147,7 +23231,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 242, + "weight": 243, "cookies": false, "type": "", "deprecated": false, @@ -23260,7 +23344,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 239, + "weight": 240, "cookies": false, "type": "", "deprecated": false, @@ -23371,7 +23455,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 245, + "weight": 246, "cookies": false, "type": "", "deprecated": false, @@ -23426,7 +23510,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 273, + "weight": 274, "cookies": false, "type": "", "deprecated": false, @@ -23488,7 +23572,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 258, + "weight": 259, "cookies": false, "type": "", "deprecated": false, @@ -23568,7 +23652,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 276, + "weight": 277, "cookies": false, "type": "", "deprecated": false, @@ -23651,7 +23735,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 254, + "weight": 255, "cookies": false, "type": "", "deprecated": false, @@ -23732,7 +23816,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 250, + "weight": 251, "cookies": false, "type": "", "deprecated": false, @@ -23804,7 +23888,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 249, + "weight": 250, "cookies": false, "type": "", "deprecated": false, @@ -23887,7 +23971,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 263, + "weight": 264, "cookies": false, "type": "", "deprecated": false, @@ -23962,7 +24046,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 268, + "weight": 269, "cookies": false, "type": "", "deprecated": false, @@ -24035,7 +24119,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 264, + "weight": 265, "cookies": false, "type": "", "deprecated": false, @@ -24095,7 +24179,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 265, + "weight": 266, "cookies": false, "type": "", "deprecated": false, @@ -24155,7 +24239,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 267, + "weight": 268, "cookies": false, "type": "", "deprecated": false, @@ -24215,7 +24299,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 266, + "weight": 267, "cookies": false, "type": "", "deprecated": false, @@ -24277,7 +24361,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 256, + "weight": 257, "cookies": false, "type": "", "deprecated": false, @@ -24357,7 +24441,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 257, + "weight": 258, "cookies": false, "type": "", "deprecated": false, @@ -24437,7 +24521,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 259, + "weight": 260, "cookies": false, "type": "", "deprecated": false, @@ -24515,7 +24599,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 246, + "weight": 247, "cookies": false, "type": "", "deprecated": false, @@ -24575,7 +24659,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 261, + "weight": 262, "cookies": false, "type": "", "deprecated": false, @@ -24653,7 +24737,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 248, + "weight": 249, "cookies": false, "type": "", "deprecated": false, @@ -24713,7 +24797,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 269, + "weight": 270, "cookies": false, "type": "", "deprecated": false, @@ -24768,7 +24852,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 272, + "weight": 273, "cookies": false, "type": "", "deprecated": false, @@ -24825,7 +24909,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 271, + "weight": 272, "cookies": false, "type": "", "deprecated": false, @@ -24895,7 +24979,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 253, + "weight": 254, "cookies": false, "type": "", "deprecated": false, @@ -24973,7 +25057,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 251, + "weight": 252, "cookies": false, "type": "", "deprecated": false, @@ -25046,7 +25130,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 243, + "weight": 244, "cookies": false, "type": "", "deprecated": false, @@ -25158,7 +25242,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 247, + "weight": 248, "cookies": false, "type": "", "deprecated": false, @@ -25227,7 +25311,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 262, + "weight": 263, "cookies": false, "type": "", "deprecated": false, @@ -25318,7 +25402,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 274, + "weight": 275, "cookies": false, "type": "", "deprecated": false, @@ -25389,7 +25473,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 270, + "weight": 271, "cookies": false, "type": "", "deprecated": false, @@ -25472,7 +25556,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 260, + "weight": 261, "cookies": false, "type": "", "deprecated": false, @@ -25552,7 +25636,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 255, + "weight": 256, "cookies": false, "type": "", "deprecated": false, diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index e7a8ee5ee7..5c1b764e1e 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -61,6 +61,12 @@ "name": "X-Appwrite-Session", "description": "The user session to authenticate with", "in": "header" + }, + "DevKey": { + "type": "apiKey", + "name": "X-Appwrite-Dev-Key", + "description": "Your secret dev API key", + "in": "header" } }, "paths": { @@ -4630,29 +4636,6 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." - }, - { - "name": "createDocuments", - "auth": { - "Key": [] - }, - "parameters": [ - "databaseId", - "collectionId", - "documents" - ], - "required": [ - "databaseId", - "collectionId", - "documents" - ], - "responses": [ - { - "code": 201, - "model": "#\/definitions\/documentList" - } - ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -4814,6 +4797,111 @@ } ] }, + "put": { + "summary": "Upsert document", + "operationId": "databasesUpsertDocument", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "upsertDocument", + "group": "documents", + "weight": 114, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include all required attributes of the document to be created or updated.", + "default": {}, + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "data" + ] + } + } + ] + }, "patch": { "summary": "Update document", "operationId": "databasesUpdateDocument", @@ -4935,7 +5023,7 @@ "x-appwrite": { "method": "deleteDocument", "group": "documents", - "weight": 116, + "weight": 117, "cookies": false, "type": "", "deprecated": false, @@ -5013,7 +5101,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 391, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -5087,7 +5175,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 389, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -5204,7 +5292,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 390, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -5276,7 +5364,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 305, + "weight": 306, "cookies": false, "type": "graphql", "deprecated": false, @@ -5350,7 +5438,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 304, + "weight": 305, "cookies": false, "type": "graphql", "deprecated": false, @@ -5422,7 +5510,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 121, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -5474,7 +5562,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 122, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -5526,7 +5614,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 126, + "weight": 127, "cookies": false, "type": "", "deprecated": false, @@ -5578,7 +5666,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 123, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -5630,7 +5718,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 124, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -5682,7 +5770,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 125, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -5734,7 +5822,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 127, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -5786,7 +5874,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 128, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -5840,7 +5928,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 351, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -5925,7 +6013,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 355, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -5996,7 +6084,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 211, + "weight": 212, "cookies": false, "type": "", "deprecated": false, @@ -6079,7 +6167,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 210, + "weight": 211, "cookies": false, "type": "upload", "deprecated": false, @@ -6169,7 +6257,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 212, + "weight": 213, "cookies": false, "type": "", "deprecated": false, @@ -6239,7 +6327,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 217, + "weight": 218, "cookies": false, "type": "", "deprecated": false, @@ -6328,7 +6416,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 218, + "weight": 219, "cookies": false, "type": "", "deprecated": false, @@ -6398,7 +6486,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 214, + "weight": 215, "cookies": false, "type": "location", "deprecated": false, @@ -6477,7 +6565,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 213, + "weight": 214, "cookies": false, "type": "location", "deprecated": false, @@ -6683,7 +6771,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 215, + "weight": 216, "cookies": false, "type": "location", "deprecated": false, @@ -6762,7 +6850,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 222, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -6837,7 +6925,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 221, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -6927,7 +7015,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 223, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -6989,7 +7077,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 225, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -7064,7 +7152,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 227, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -7126,7 +7214,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 229, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -7209,7 +7297,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 228, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -7322,7 +7410,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 230, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -7392,7 +7480,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 231, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -7478,7 +7566,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 233, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -7550,7 +7638,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 232, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -7644,7 +7732,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 224, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -7705,7 +7793,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 226, + "weight": 227, "cookies": false, "type": "", "deprecated": false, diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 3b92eceebd..96705f3e61 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -4527,7 +4527,7 @@ "x-appwrite": { "method": "chat", "group": "console", - "weight": 307, + "weight": 308, "cookies": false, "type": "", "deprecated": false, @@ -4590,7 +4590,7 @@ "x-appwrite": { "method": "getResource", "group": null, - "weight": 431, + "weight": 432, "cookies": false, "type": "", "deprecated": false, @@ -4661,7 +4661,7 @@ "x-appwrite": { "method": "variables", "group": "console", - "weight": 306, + "weight": 307, "cookies": false, "type": "", "deprecated": false, @@ -4863,7 +4863,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 118, + "weight": 119, "cookies": false, "type": "", "deprecated": false, @@ -8178,29 +8178,6 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." - }, - { - "name": "createDocuments", - "auth": { - "Key": [] - }, - "parameters": [ - "databaseId", - "collectionId", - "documents" - ], - "required": [ - "databaseId", - "collectionId", - "documents" - ], - "responses": [ - { - "code": 201, - "model": "#\/definitions\/documentList" - } - ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -8296,7 +8273,7 @@ "x-appwrite": { "method": "upsertDocuments", "group": "documents", - "weight": 115, + "weight": 116, "cookies": false, "type": "", "deprecated": false, @@ -8381,7 +8358,7 @@ "x-appwrite": { "method": "updateDocuments", "group": "documents", - "weight": 114, + "weight": 115, "cookies": false, "type": "", "deprecated": false, @@ -8472,7 +8449,7 @@ "x-appwrite": { "method": "deleteDocuments", "group": "documents", - "weight": 117, + "weight": 118, "cookies": false, "type": "", "deprecated": false, @@ -8623,6 +8600,111 @@ } ] }, + "put": { + "summary": "Upsert document", + "operationId": "databasesUpsertDocument", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "upsertDocument", + "group": "documents", + "weight": 114, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include all required attributes of the document to be created or updated.", + "default": {}, + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "data" + ] + } + } + ] + }, "patch": { "summary": "Update document", "operationId": "databasesUpdateDocument", @@ -8744,7 +8826,7 @@ "x-appwrite": { "method": "deleteDocument", "group": "documents", - "weight": 116, + "weight": 117, "cookies": false, "type": "", "deprecated": false, @@ -9335,7 +9417,7 @@ "x-appwrite": { "method": "getCollectionUsage", "group": null, - "weight": 120, + "weight": 121, "cookies": false, "type": "", "deprecated": false, @@ -9491,7 +9573,7 @@ "x-appwrite": { "method": "getDatabaseUsage", "group": null, - "weight": 119, + "weight": 120, "cookies": false, "type": "", "deprecated": false, @@ -9569,7 +9651,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 375, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -9641,7 +9723,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 372, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -9890,7 +9972,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 377, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -9939,7 +10021,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 378, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -9989,7 +10071,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 401, + "weight": 402, "cookies": false, "type": "", "deprecated": false, @@ -10083,7 +10165,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 400, + "weight": 401, "cookies": false, "type": "", "deprecated": false, @@ -10141,7 +10223,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 394, + "weight": 395, "cookies": false, "type": "", "deprecated": false, @@ -10211,7 +10293,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 373, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -10270,7 +10352,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 374, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -10515,7 +10597,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 376, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -10576,7 +10658,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 381, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -10653,7 +10735,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 382, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -10733,7 +10815,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 379, + "weight": 380, "cookies": false, "type": "upload", "deprecated": false, @@ -10825,7 +10907,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 387, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -10910,7 +10992,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 384, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -11016,7 +11098,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 385, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -11112,7 +11194,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 380, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -11174,7 +11256,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 383, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -11241,7 +11323,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 386, + "weight": 387, "cookies": false, "type": "location", "deprecated": false, @@ -11327,7 +11409,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 388, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -11394,7 +11476,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 391, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -11468,7 +11550,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 389, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -11585,7 +11667,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 390, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -11650,7 +11732,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 392, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -11717,7 +11799,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 393, + "weight": 394, "cookies": false, "type": "", "deprecated": false, @@ -11795,7 +11877,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 397, + "weight": 398, "cookies": false, "type": "", "deprecated": false, @@ -11854,7 +11936,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 395, + "weight": 396, "cookies": false, "type": "", "deprecated": false, @@ -11944,7 +12026,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 396, + "weight": 397, "cookies": false, "type": "", "deprecated": false, @@ -12011,7 +12093,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 398, + "weight": 399, "cookies": false, "type": "", "deprecated": false, @@ -12103,7 +12185,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 399, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -12172,7 +12254,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 305, + "weight": 306, "cookies": false, "type": "graphql", "deprecated": false, @@ -12246,7 +12328,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 304, + "weight": 305, "cookies": false, "type": "graphql", "deprecated": false, @@ -12318,7 +12400,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 129, + "weight": 130, "cookies": false, "type": "", "deprecated": false, @@ -12367,7 +12449,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 150, + "weight": 151, "cookies": false, "type": "", "deprecated": false, @@ -12416,7 +12498,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 132, + "weight": 133, "cookies": false, "type": "", "deprecated": false, @@ -12465,7 +12547,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 137, + "weight": 138, "cookies": false, "type": "", "deprecated": false, @@ -12523,7 +12605,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 131, + "weight": 132, "cookies": false, "type": "", "deprecated": false, @@ -12572,7 +12654,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 133, + "weight": 134, "cookies": false, "type": "", "deprecated": false, @@ -12621,7 +12703,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 139, + "weight": 140, "cookies": false, "type": "", "deprecated": false, @@ -12681,7 +12763,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 138, + "weight": 139, "cookies": false, "type": "", "deprecated": false, @@ -12741,7 +12823,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 140, + "weight": 141, "cookies": false, "type": "", "deprecated": false, @@ -12810,7 +12892,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 141, + "weight": 142, "cookies": false, "type": "", "deprecated": false, @@ -12870,7 +12952,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 151, + "weight": 152, "cookies": false, "type": "", "deprecated": false, @@ -12954,7 +13036,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 145, + "weight": 146, "cookies": false, "type": "", "deprecated": false, @@ -13014,7 +13096,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 136, + "weight": 137, "cookies": false, "type": "", "deprecated": false, @@ -13074,7 +13156,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 142, + "weight": 143, "cookies": false, "type": "", "deprecated": false, @@ -13134,7 +13216,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 143, + "weight": 144, "cookies": false, "type": "", "deprecated": false, @@ -13194,7 +13276,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 144, + "weight": 145, "cookies": false, "type": "", "deprecated": false, @@ -13254,7 +13336,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 146, + "weight": 147, "cookies": false, "type": "", "deprecated": false, @@ -13314,7 +13396,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 147, + "weight": 148, "cookies": false, "type": "", "deprecated": false, @@ -13374,7 +13456,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 135, + "weight": 136, "cookies": false, "type": "", "deprecated": false, @@ -13434,7 +13516,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 149, + "weight": 150, "cookies": false, "type": "", "deprecated": false, @@ -13483,7 +13565,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 148, + "weight": 149, "cookies": false, "type": "", "deprecated": false, @@ -13532,7 +13614,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 134, + "weight": 135, "cookies": false, "type": "", "deprecated": false, @@ -13581,7 +13663,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 121, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -13633,7 +13715,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 122, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -13685,7 +13767,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 126, + "weight": 127, "cookies": false, "type": "", "deprecated": false, @@ -13737,7 +13819,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 123, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -13789,7 +13871,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 124, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -13841,7 +13923,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 125, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -13893,7 +13975,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 127, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -13945,7 +14027,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 128, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -13997,7 +14079,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 359, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -14072,7 +14154,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 356, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -14230,7 +14312,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 363, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -14385,7 +14467,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 358, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -14580,7 +14662,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 365, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -14774,7 +14856,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 357, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -14892,7 +14974,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 364, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -15006,7 +15088,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 362, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -15061,7 +15143,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 366, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -15121,7 +15203,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 360, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -15193,7 +15275,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 361, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -15265,7 +15347,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 331, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -15340,7 +15422,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 330, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -15455,7 +15537,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 343, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -15568,7 +15650,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 329, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -15659,7 +15741,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 342, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -15748,7 +15830,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 321, + "weight": 322, "cookies": false, "type": "", "deprecated": false, @@ -15875,7 +15957,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 334, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -16000,7 +16082,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 324, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -16103,7 +16185,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 337, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -16204,7 +16286,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 322, + "weight": 323, "cookies": false, "type": "", "deprecated": false, @@ -16319,7 +16401,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 335, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -16432,7 +16514,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 323, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -16591,7 +16673,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 336, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -16747,7 +16829,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 325, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -16850,7 +16932,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 338, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -16951,7 +17033,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 326, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -17054,7 +17136,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 339, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -17155,7 +17237,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 327, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -17258,7 +17340,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 340, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -17359,7 +17441,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 328, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -17462,7 +17544,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 341, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -17561,7 +17643,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 333, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -17616,7 +17698,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 344, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -17676,7 +17758,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 332, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -17748,7 +17830,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 353, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -17820,7 +17902,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 346, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -17893,7 +17975,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 345, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -17981,7 +18063,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 348, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -18041,7 +18123,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 349, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -18120,7 +18202,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 350, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -18180,7 +18262,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 347, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -18252,7 +18334,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 352, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -18333,7 +18415,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 351, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -18421,7 +18503,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 354, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -18484,7 +18566,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 355, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -18555,7 +18637,7 @@ "x-appwrite": { "method": "list", "group": null, - "weight": 313, + "weight": 314, "cookies": false, "type": "", "deprecated": false, @@ -18628,7 +18710,7 @@ "x-appwrite": { "method": "createAppwriteMigration", "group": null, - "weight": 308, + "weight": 309, "cookies": false, "type": "", "deprecated": false, @@ -18720,7 +18802,7 @@ "x-appwrite": { "method": "getAppwriteReport", "group": null, - "weight": 315, + "weight": 316, "cookies": false, "type": "", "deprecated": false, @@ -18808,7 +18890,7 @@ "x-appwrite": { "method": "createCsvMigration", "group": null, - "weight": 312, + "weight": 313, "cookies": false, "type": "", "deprecated": false, @@ -18892,7 +18974,7 @@ "x-appwrite": { "method": "createFirebaseMigration", "group": null, - "weight": 309, + "weight": 310, "cookies": false, "type": "", "deprecated": false, @@ -18970,7 +19052,7 @@ "x-appwrite": { "method": "getFirebaseReport", "group": null, - "weight": 316, + "weight": 317, "cookies": false, "type": "", "deprecated": false, @@ -19041,7 +19123,7 @@ "x-appwrite": { "method": "createNHostMigration", "group": null, - "weight": 311, + "weight": 312, "cookies": false, "type": "", "deprecated": false, @@ -19160,7 +19242,7 @@ "x-appwrite": { "method": "getNHostReport", "group": null, - "weight": 318, + "weight": 319, "cookies": false, "type": "", "deprecated": false, @@ -19280,7 +19362,7 @@ "x-appwrite": { "method": "createSupabaseMigration", "group": null, - "weight": 310, + "weight": 311, "cookies": false, "type": "", "deprecated": false, @@ -19392,7 +19474,7 @@ "x-appwrite": { "method": "getSupabaseReport", "group": null, - "weight": 317, + "weight": 318, "cookies": false, "type": "", "deprecated": false, @@ -19503,7 +19585,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 314, + "weight": 315, "cookies": false, "type": "", "deprecated": false, @@ -19561,7 +19643,7 @@ "x-appwrite": { "method": "retry", "group": null, - "weight": 319, + "weight": 320, "cookies": false, "type": "", "deprecated": false, @@ -19614,7 +19696,7 @@ "x-appwrite": { "method": "delete", "group": null, - "weight": 320, + "weight": 321, "cookies": false, "type": "", "deprecated": false, @@ -19672,7 +19754,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 199, + "weight": 200, "cookies": false, "type": "", "deprecated": false, @@ -19754,7 +19836,7 @@ "x-appwrite": { "method": "listVariables", "group": null, - "weight": 201, + "weight": 202, "cookies": false, "type": "", "deprecated": false, @@ -19802,7 +19884,7 @@ "x-appwrite": { "method": "createVariable", "group": null, - "weight": 200, + "weight": 201, "cookies": false, "type": "", "deprecated": false, @@ -19883,7 +19965,7 @@ "x-appwrite": { "method": "getVariable", "group": null, - "weight": 202, + "weight": 203, "cookies": false, "type": "", "deprecated": false, @@ -19941,7 +20023,7 @@ "x-appwrite": { "method": "updateVariable", "group": null, - "weight": 203, + "weight": 204, "cookies": false, "type": "", "deprecated": false, @@ -20024,7 +20106,7 @@ "x-appwrite": { "method": "deleteVariable", "group": null, - "weight": 204, + "weight": 205, "cookies": false, "type": "", "deprecated": false, @@ -20082,7 +20164,7 @@ "x-appwrite": { "method": "list", "group": "projects", - "weight": 154, + "weight": 155, "cookies": false, "type": "", "deprecated": false, @@ -20153,7 +20235,7 @@ "x-appwrite": { "method": "create", "group": "projects", - "weight": 153, + "weight": 154, "cookies": false, "type": "", "deprecated": false, @@ -20300,7 +20382,7 @@ "x-appwrite": { "method": "get", "group": "projects", - "weight": 155, + "weight": 156, "cookies": false, "type": "", "deprecated": false, @@ -20358,7 +20440,7 @@ "x-appwrite": { "method": "update", "group": "projects", - "weight": 156, + "weight": 157, "cookies": false, "type": "", "deprecated": false, @@ -20483,7 +20565,7 @@ "x-appwrite": { "method": "delete", "group": "projects", - "weight": 173, + "weight": 174, "cookies": false, "type": "", "deprecated": false, @@ -20543,7 +20625,7 @@ "x-appwrite": { "method": "updateApiStatus", "group": "projects", - "weight": 160, + "weight": 161, "cookies": false, "type": "", "deprecated": false, @@ -20635,7 +20717,7 @@ "x-appwrite": { "method": "updateApiStatusAll", "group": "projects", - "weight": 161, + "weight": 162, "cookies": false, "type": "", "deprecated": false, @@ -20713,7 +20795,7 @@ "x-appwrite": { "method": "updateAuthDuration", "group": "auth", - "weight": 166, + "weight": 167, "cookies": false, "type": "", "deprecated": false, @@ -20791,7 +20873,7 @@ "x-appwrite": { "method": "updateAuthLimit", "group": "auth", - "weight": 165, + "weight": 166, "cookies": false, "type": "", "deprecated": false, @@ -20869,7 +20951,7 @@ "x-appwrite": { "method": "updateAuthSessionsLimit", "group": "auth", - "weight": 171, + "weight": 172, "cookies": false, "type": "", "deprecated": false, @@ -20947,7 +21029,7 @@ "x-appwrite": { "method": "updateMembershipsPrivacy", "group": "auth", - "weight": 164, + "weight": 165, "cookies": false, "type": "", "deprecated": false, @@ -21039,7 +21121,7 @@ "x-appwrite": { "method": "updateMockNumbers", "group": "auth", - "weight": 172, + "weight": 173, "cookies": false, "type": "", "deprecated": false, @@ -21120,7 +21202,7 @@ "x-appwrite": { "method": "updateAuthPasswordDictionary", "group": "auth", - "weight": 169, + "weight": 170, "cookies": false, "type": "", "deprecated": false, @@ -21198,7 +21280,7 @@ "x-appwrite": { "method": "updateAuthPasswordHistory", "group": "auth", - "weight": 168, + "weight": 169, "cookies": false, "type": "", "deprecated": false, @@ -21276,7 +21358,7 @@ "x-appwrite": { "method": "updatePersonalDataCheck", "group": "auth", - "weight": 170, + "weight": 171, "cookies": false, "type": "", "deprecated": false, @@ -21354,7 +21436,7 @@ "x-appwrite": { "method": "updateSessionAlerts", "group": "auth", - "weight": 163, + "weight": 164, "cookies": false, "type": "", "deprecated": false, @@ -21432,7 +21514,7 @@ "x-appwrite": { "method": "updateAuthStatus", "group": "auth", - "weight": 167, + "weight": 168, "cookies": false, "type": "", "deprecated": false, @@ -21527,7 +21609,7 @@ "x-appwrite": { "method": "listDevKeys", "group": "devKeys", - "weight": 370, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -21597,7 +21679,7 @@ "x-appwrite": { "method": "createDevKey", "group": "devKeys", - "weight": 367, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -21680,7 +21762,7 @@ "x-appwrite": { "method": "getDevKey", "group": "devKeys", - "weight": 369, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -21746,7 +21828,7 @@ "x-appwrite": { "method": "updateDevKey", "group": "devKeys", - "weight": 368, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -21832,7 +21914,7 @@ "x-appwrite": { "method": "deleteDevKey", "group": "devKeys", - "weight": 371, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -21900,7 +21982,7 @@ "x-appwrite": { "method": "createJWT", "group": "auth", - "weight": 185, + "weight": 186, "cookies": false, "type": "", "deprecated": false, @@ -21985,7 +22067,7 @@ "x-appwrite": { "method": "listKeys", "group": "keys", - "weight": 181, + "weight": 182, "cookies": false, "type": "", "deprecated": false, @@ -22043,7 +22125,7 @@ "x-appwrite": { "method": "createKey", "group": "keys", - "weight": 180, + "weight": 181, "cookies": false, "type": "", "deprecated": false, @@ -22135,7 +22217,7 @@ "x-appwrite": { "method": "getKey", "group": "keys", - "weight": 182, + "weight": 183, "cookies": false, "type": "", "deprecated": false, @@ -22201,7 +22283,7 @@ "x-appwrite": { "method": "updateKey", "group": "keys", - "weight": 183, + "weight": 184, "cookies": false, "type": "", "deprecated": false, @@ -22296,7 +22378,7 @@ "x-appwrite": { "method": "deleteKey", "group": "keys", - "weight": 184, + "weight": 185, "cookies": false, "type": "", "deprecated": false, @@ -22364,7 +22446,7 @@ "x-appwrite": { "method": "updateOAuth2", "group": "auth", - "weight": 162, + "weight": 163, "cookies": false, "type": "", "deprecated": false, @@ -22502,7 +22584,7 @@ "x-appwrite": { "method": "listPlatforms", "group": "platforms", - "weight": 187, + "weight": 188, "cookies": false, "type": "", "deprecated": false, @@ -22560,7 +22642,7 @@ "x-appwrite": { "method": "createPlatform", "group": "platforms", - "weight": 186, + "weight": 187, "cookies": false, "type": "", "deprecated": false, @@ -22680,7 +22762,7 @@ "x-appwrite": { "method": "getPlatform", "group": "platforms", - "weight": 188, + "weight": 189, "cookies": false, "type": "", "deprecated": false, @@ -22746,7 +22828,7 @@ "x-appwrite": { "method": "updatePlatform", "group": "platforms", - "weight": 189, + "weight": 190, "cookies": false, "type": "", "deprecated": false, @@ -22843,7 +22925,7 @@ "x-appwrite": { "method": "deletePlatform", "group": "platforms", - "weight": 190, + "weight": 191, "cookies": false, "type": "", "deprecated": false, @@ -22911,7 +22993,7 @@ "x-appwrite": { "method": "updateServiceStatus", "group": "projects", - "weight": 158, + "weight": 159, "cookies": false, "type": "", "deprecated": false, @@ -23012,7 +23094,7 @@ "x-appwrite": { "method": "updateServiceStatusAll", "group": "projects", - "weight": 159, + "weight": 160, "cookies": false, "type": "", "deprecated": false, @@ -23090,7 +23172,7 @@ "x-appwrite": { "method": "updateSmtp", "group": "templates", - "weight": 191, + "weight": 192, "cookies": false, "type": "", "deprecated": false, @@ -23219,7 +23301,7 @@ "x-appwrite": { "method": "createSmtpTest", "group": "templates", - "weight": 192, + "weight": 193, "cookies": false, "type": "", "deprecated": false, @@ -23357,7 +23439,7 @@ "x-appwrite": { "method": "updateTeam", "group": "projects", - "weight": 157, + "weight": 158, "cookies": false, "type": "", "deprecated": false, @@ -23433,7 +23515,7 @@ "x-appwrite": { "method": "getEmailTemplate", "group": "templates", - "weight": 194, + "weight": 195, "cookies": false, "type": "", "deprecated": false, @@ -23653,7 +23735,7 @@ "x-appwrite": { "method": "updateEmailTemplate", "group": "templates", - "weight": 196, + "weight": 197, "cookies": false, "type": "", "deprecated": false, @@ -23916,7 +23998,7 @@ "x-appwrite": { "method": "deleteEmailTemplate", "group": "templates", - "weight": 198, + "weight": 199, "cookies": false, "type": "", "deprecated": false, @@ -24136,7 +24218,7 @@ "x-appwrite": { "method": "getSmsTemplate", "group": "templates", - "weight": 193, + "weight": 194, "cookies": false, "type": "", "deprecated": false, @@ -24353,7 +24435,7 @@ "x-appwrite": { "method": "updateSmsTemplate", "group": "templates", - "weight": 195, + "weight": 196, "cookies": false, "type": "", "deprecated": false, @@ -24588,7 +24670,7 @@ "x-appwrite": { "method": "deleteSmsTemplate", "group": "templates", - "weight": 197, + "weight": 198, "cookies": false, "type": "", "deprecated": false, @@ -24805,7 +24887,7 @@ "x-appwrite": { "method": "listWebhooks", "group": "webhooks", - "weight": 175, + "weight": 176, "cookies": false, "type": "", "deprecated": false, @@ -24863,7 +24945,7 @@ "x-appwrite": { "method": "createWebhook", "group": "webhooks", - "weight": 174, + "weight": 175, "cookies": false, "type": "", "deprecated": false, @@ -24981,7 +25063,7 @@ "x-appwrite": { "method": "getWebhook", "group": "webhooks", - "weight": 176, + "weight": 177, "cookies": false, "type": "", "deprecated": false, @@ -25047,7 +25129,7 @@ "x-appwrite": { "method": "updateWebhook", "group": "webhooks", - "weight": 177, + "weight": 178, "cookies": false, "type": "", "deprecated": false, @@ -25168,7 +25250,7 @@ "x-appwrite": { "method": "deleteWebhook", "group": "webhooks", - "weight": 179, + "weight": 180, "cookies": false, "type": "", "deprecated": false, @@ -25236,7 +25318,7 @@ "x-appwrite": { "method": "updateWebhookSignature", "group": "webhooks", - "weight": 178, + "weight": 179, "cookies": false, "type": "", "deprecated": false, @@ -25302,7 +25384,7 @@ "x-appwrite": { "method": "listRules", "group": null, - "weight": 291, + "weight": 292, "cookies": false, "type": "", "deprecated": false, @@ -25375,7 +25457,7 @@ "x-appwrite": { "method": "createAPIRule", "group": null, - "weight": 432, + "weight": 433, "cookies": false, "type": "", "deprecated": false, @@ -25445,7 +25527,7 @@ "x-appwrite": { "method": "createFunctionRule", "group": null, - "weight": 434, + "weight": 435, "cookies": false, "type": "", "deprecated": false, @@ -25528,7 +25610,7 @@ "x-appwrite": { "method": "createRedirectRule", "group": null, - "weight": 435, + "weight": 436, "cookies": false, "type": "", "deprecated": false, @@ -25625,7 +25707,7 @@ "x-appwrite": { "method": "createSiteRule", "group": null, - "weight": 433, + "weight": 434, "cookies": false, "type": "", "deprecated": false, @@ -25706,7 +25788,7 @@ "x-appwrite": { "method": "getRule", "group": null, - "weight": 292, + "weight": 293, "cookies": false, "type": "", "deprecated": false, @@ -25759,7 +25841,7 @@ "x-appwrite": { "method": "deleteRule", "group": null, - "weight": 293, + "weight": 294, "cookies": false, "type": "", "deprecated": false, @@ -25819,7 +25901,7 @@ "x-appwrite": { "method": "updateRuleVerification", "group": null, - "weight": 294, + "weight": 295, "cookies": false, "type": "", "deprecated": false, @@ -25877,7 +25959,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 404, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -25949,7 +26031,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 402, + "weight": 403, "cookies": false, "type": "", "deprecated": false, @@ -26214,7 +26296,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 407, + "weight": 408, "cookies": false, "type": "", "deprecated": false, @@ -26263,7 +26345,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 430, + "weight": 431, "cookies": false, "type": "", "deprecated": false, @@ -26313,7 +26395,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 426, + "weight": 427, "cookies": false, "type": "", "deprecated": false, @@ -26407,7 +26489,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 427, + "weight": 428, "cookies": false, "type": "", "deprecated": false, @@ -26465,7 +26547,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 428, + "weight": 429, "cookies": false, "type": "", "deprecated": false, @@ -26535,7 +26617,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 403, + "weight": 404, "cookies": false, "type": "", "deprecated": false, @@ -26594,7 +26676,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 405, + "weight": 406, "cookies": false, "type": "", "deprecated": false, @@ -26854,7 +26936,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 406, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -26915,7 +26997,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 413, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -26992,7 +27074,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 412, + "weight": 413, "cookies": false, "type": "", "deprecated": false, @@ -27072,7 +27154,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 408, + "weight": 409, "cookies": false, "type": "upload", "deprecated": false, @@ -27172,7 +27254,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 416, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -27251,7 +27333,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 409, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -27357,7 +27439,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 410, + "weight": 411, "cookies": false, "type": "", "deprecated": false, @@ -27454,7 +27536,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 411, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -27516,7 +27598,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 414, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -27583,7 +27665,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 415, + "weight": 416, "cookies": false, "type": "location", "deprecated": false, @@ -27669,7 +27751,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 417, + "weight": 418, "cookies": false, "type": "", "deprecated": false, @@ -27736,7 +27818,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 419, + "weight": 420, "cookies": false, "type": "", "deprecated": false, @@ -27807,7 +27889,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 418, + "weight": 419, "cookies": false, "type": "", "deprecated": false, @@ -27871,7 +27953,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 420, + "weight": 421, "cookies": false, "type": "", "deprecated": false, @@ -27938,7 +28020,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 429, + "weight": 430, "cookies": false, "type": "", "deprecated": false, @@ -28016,7 +28098,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 423, + "weight": 424, "cookies": false, "type": "", "deprecated": false, @@ -28075,7 +28157,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 421, + "weight": 422, "cookies": false, "type": "", "deprecated": false, @@ -28165,7 +28247,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 422, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -28232,7 +28314,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 424, + "weight": 425, "cookies": false, "type": "", "deprecated": false, @@ -28324,7 +28406,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 425, + "weight": 426, "cookies": false, "type": "", "deprecated": false, @@ -28391,7 +28473,7 @@ "x-appwrite": { "method": "listBuckets", "group": "buckets", - "weight": 206, + "weight": 207, "cookies": false, "type": "", "deprecated": false, @@ -28463,7 +28545,7 @@ "x-appwrite": { "method": "createBucket", "group": "buckets", - "weight": 205, + "weight": 206, "cookies": false, "type": "", "deprecated": false, @@ -28600,7 +28682,7 @@ "x-appwrite": { "method": "getBucket", "group": "buckets", - "weight": 207, + "weight": 208, "cookies": false, "type": "", "deprecated": false, @@ -28659,7 +28741,7 @@ "x-appwrite": { "method": "updateBucket", "group": "buckets", - "weight": 208, + "weight": 209, "cookies": false, "type": "", "deprecated": false, @@ -28792,7 +28874,7 @@ "x-appwrite": { "method": "deleteBucket", "group": "buckets", - "weight": 209, + "weight": 210, "cookies": false, "type": "", "deprecated": false, @@ -28851,7 +28933,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 211, + "weight": 212, "cookies": false, "type": "", "deprecated": false, @@ -28934,7 +29016,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 210, + "weight": 211, "cookies": false, "type": "upload", "deprecated": false, @@ -29024,7 +29106,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 212, + "weight": 213, "cookies": false, "type": "", "deprecated": false, @@ -29094,7 +29176,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 217, + "weight": 218, "cookies": false, "type": "", "deprecated": false, @@ -29183,7 +29265,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 218, + "weight": 219, "cookies": false, "type": "", "deprecated": false, @@ -29253,7 +29335,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 214, + "weight": 215, "cookies": false, "type": "location", "deprecated": false, @@ -29332,7 +29414,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 213, + "weight": 214, "cookies": false, "type": "location", "deprecated": false, @@ -29538,7 +29620,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 215, + "weight": 216, "cookies": false, "type": "location", "deprecated": false, @@ -29617,7 +29699,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 219, + "weight": 220, "cookies": false, "type": "", "deprecated": false, @@ -29687,7 +29769,7 @@ "x-appwrite": { "method": "getBucketUsage", "group": null, - "weight": 220, + "weight": 221, "cookies": false, "type": "", "deprecated": false, @@ -29765,7 +29847,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 222, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -29840,7 +29922,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 221, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -29930,7 +30012,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 223, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -29992,7 +30074,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 225, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -30067,7 +30149,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 227, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -30129,7 +30211,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 234, + "weight": 235, "cookies": false, "type": "", "deprecated": false, @@ -30199,7 +30281,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 229, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -30282,7 +30364,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 228, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -30395,7 +30477,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 230, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -30465,7 +30547,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 231, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -30551,7 +30633,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 233, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -30623,7 +30705,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 232, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -30716,7 +30798,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 224, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -30776,7 +30858,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 226, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -30854,7 +30936,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 438, + "weight": 439, "cookies": false, "type": "", "deprecated": false, @@ -30934,7 +31016,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 436, + "weight": 437, "cookies": false, "type": "", "deprecated": false, @@ -31018,7 +31100,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 437, + "weight": 438, "cookies": false, "type": "", "deprecated": false, @@ -31078,7 +31160,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 439, + "weight": 440, "cookies": false, "type": "", "deprecated": false, @@ -31149,7 +31231,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 440, + "weight": 441, "cookies": false, "type": "", "deprecated": false, @@ -31209,7 +31291,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 244, + "weight": 245, "cookies": false, "type": "", "deprecated": false, @@ -31281,7 +31363,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 235, + "weight": 236, "cookies": false, "type": "", "deprecated": false, @@ -31376,7 +31458,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 238, + "weight": 239, "cookies": false, "type": "", "deprecated": false, @@ -31467,7 +31549,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 236, + "weight": 237, "cookies": false, "type": "", "deprecated": false, @@ -31556,7 +31638,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 252, + "weight": 253, "cookies": false, "type": "", "deprecated": false, @@ -31625,7 +31707,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 275, + "weight": 276, "cookies": false, "type": "", "deprecated": false, @@ -31686,7 +31768,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 237, + "weight": 238, "cookies": false, "type": "", "deprecated": false, @@ -31777,7 +31859,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 240, + "weight": 241, "cookies": false, "type": "", "deprecated": false, @@ -31868,7 +31950,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 241, + "weight": 242, "cookies": false, "type": "", "deprecated": false, @@ -31994,7 +32076,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 242, + "weight": 243, "cookies": false, "type": "", "deprecated": false, @@ -32106,7 +32188,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 239, + "weight": 240, "cookies": false, "type": "", "deprecated": false, @@ -32216,7 +32298,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 277, + "weight": 278, "cookies": false, "type": "", "deprecated": false, @@ -32286,7 +32368,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 245, + "weight": 246, "cookies": false, "type": "", "deprecated": false, @@ -32340,7 +32422,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 273, + "weight": 274, "cookies": false, "type": "", "deprecated": false, @@ -32401,7 +32483,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 258, + "weight": 259, "cookies": false, "type": "", "deprecated": false, @@ -32480,7 +32562,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 276, + "weight": 277, "cookies": false, "type": "", "deprecated": false, @@ -32562,7 +32644,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 254, + "weight": 255, "cookies": false, "type": "", "deprecated": false, @@ -32642,7 +32724,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 250, + "weight": 251, "cookies": false, "type": "", "deprecated": false, @@ -32713,7 +32795,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 249, + "weight": 250, "cookies": false, "type": "", "deprecated": false, @@ -32795,7 +32877,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 263, + "weight": 264, "cookies": false, "type": "", "deprecated": false, @@ -32869,7 +32951,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 268, + "weight": 269, "cookies": false, "type": "", "deprecated": false, @@ -32941,7 +33023,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 264, + "weight": 265, "cookies": false, "type": "", "deprecated": false, @@ -33000,7 +33082,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 265, + "weight": 266, "cookies": false, "type": "", "deprecated": false, @@ -33059,7 +33141,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 267, + "weight": 268, "cookies": false, "type": "", "deprecated": false, @@ -33118,7 +33200,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 266, + "weight": 267, "cookies": false, "type": "", "deprecated": false, @@ -33179,7 +33261,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 256, + "weight": 257, "cookies": false, "type": "", "deprecated": false, @@ -33258,7 +33340,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 257, + "weight": 258, "cookies": false, "type": "", "deprecated": false, @@ -33337,7 +33419,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 259, + "weight": 260, "cookies": false, "type": "", "deprecated": false, @@ -33414,7 +33496,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 246, + "weight": 247, "cookies": false, "type": "", "deprecated": false, @@ -33473,7 +33555,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 261, + "weight": 262, "cookies": false, "type": "", "deprecated": false, @@ -33550,7 +33632,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 248, + "weight": 249, "cookies": false, "type": "", "deprecated": false, @@ -33609,7 +33691,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 269, + "weight": 270, "cookies": false, "type": "", "deprecated": false, @@ -33663,7 +33745,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 272, + "weight": 273, "cookies": false, "type": "", "deprecated": false, @@ -33719,7 +33801,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 271, + "weight": 272, "cookies": false, "type": "", "deprecated": false, @@ -33788,7 +33870,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 253, + "weight": 254, "cookies": false, "type": "", "deprecated": false, @@ -33865,7 +33947,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 251, + "weight": 252, "cookies": false, "type": "", "deprecated": false, @@ -33937,7 +34019,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 243, + "weight": 244, "cookies": false, "type": "", "deprecated": false, @@ -34048,7 +34130,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 247, + "weight": 248, "cookies": false, "type": "", "deprecated": false, @@ -34116,7 +34198,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 262, + "weight": 263, "cookies": false, "type": "", "deprecated": false, @@ -34206,7 +34288,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 274, + "weight": 275, "cookies": false, "type": "", "deprecated": false, @@ -34276,7 +34358,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 270, + "weight": 271, "cookies": false, "type": "", "deprecated": false, @@ -34358,7 +34440,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 260, + "weight": 261, "cookies": false, "type": "", "deprecated": false, @@ -34437,7 +34519,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 255, + "weight": 256, "cookies": false, "type": "", "deprecated": false, @@ -34516,7 +34598,7 @@ "x-appwrite": { "method": "createRepositoryDetection", "group": "repositories", - "weight": 281, + "weight": 282, "cookies": false, "type": "", "deprecated": false, @@ -34611,7 +34693,7 @@ "x-appwrite": { "method": "listRepositories", "group": "repositories", - "weight": 282, + "weight": 283, "cookies": false, "type": "", "deprecated": false, @@ -34692,7 +34774,7 @@ "x-appwrite": { "method": "createRepository", "group": "repositories", - "weight": 283, + "weight": 284, "cookies": false, "type": "", "deprecated": false, @@ -34775,7 +34857,7 @@ "x-appwrite": { "method": "getRepository", "group": "repositories", - "weight": 284, + "weight": 285, "cookies": false, "type": "", "deprecated": false, @@ -34841,7 +34923,7 @@ "x-appwrite": { "method": "listRepositoryBranches", "group": "repositories", - "weight": 285, + "weight": 286, "cookies": false, "type": "", "deprecated": false, @@ -34907,7 +34989,7 @@ "x-appwrite": { "method": "getRepositoryContents", "group": "repositories", - "weight": 280, + "weight": 281, "cookies": false, "type": "", "deprecated": false, @@ -34981,7 +35063,7 @@ "x-appwrite": { "method": "updateExternalDeployments", "group": "repositories", - "weight": 290, + "weight": 291, "cookies": false, "type": "", "deprecated": false, @@ -35065,7 +35147,7 @@ "x-appwrite": { "method": "listInstallations", "group": "installations", - "weight": 287, + "weight": 288, "cookies": false, "type": "", "deprecated": false, @@ -35136,7 +35218,7 @@ "x-appwrite": { "method": "getInstallation", "group": "installations", - "weight": 288, + "weight": 289, "cookies": false, "type": "", "deprecated": false, @@ -35189,7 +35271,7 @@ "x-appwrite": { "method": "deleteInstallation", "group": "installations", - "weight": 289, + "weight": 290, "cookies": false, "type": "", "deprecated": false, diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 07e1107789..c033008417 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -7649,29 +7649,6 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." - }, - { - "name": "createDocuments", - "auth": { - "Key": [] - }, - "parameters": [ - "databaseId", - "collectionId", - "documents" - ], - "required": [ - "databaseId", - "collectionId", - "documents" - ], - "responses": [ - { - "code": 201, - "model": "#\/definitions\/documentList" - } - ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -7769,7 +7746,7 @@ "x-appwrite": { "method": "upsertDocuments", "group": "documents", - "weight": 115, + "weight": 116, "cookies": false, "type": "", "deprecated": false, @@ -7855,7 +7832,7 @@ "x-appwrite": { "method": "updateDocuments", "group": "documents", - "weight": 114, + "weight": 115, "cookies": false, "type": "", "deprecated": false, @@ -7947,7 +7924,7 @@ "x-appwrite": { "method": "deleteDocuments", "group": "documents", - "weight": 117, + "weight": 118, "cookies": false, "type": "", "deprecated": false, @@ -8101,6 +8078,113 @@ } ] }, + "put": { + "summary": "Upsert document", + "operationId": "databasesUpsertDocument", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "upsertDocument", + "group": "documents", + "weight": 114, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include all required attributes of the document to be created or updated.", + "default": {}, + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "data" + ] + } + } + ] + }, "patch": { "summary": "Update document", "operationId": "databasesUpdateDocument", @@ -8224,7 +8308,7 @@ "x-appwrite": { "method": "deleteDocument", "group": "documents", - "weight": 116, + "weight": 117, "cookies": false, "type": "", "deprecated": false, @@ -8657,7 +8741,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 375, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -8730,7 +8814,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 372, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -8980,7 +9064,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 377, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -9030,7 +9114,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 378, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -9081,7 +9165,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 373, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -9141,7 +9225,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 374, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -9387,7 +9471,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 376, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -9449,7 +9533,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 381, + "weight": 382, "cookies": false, "type": "", "deprecated": false, @@ -9527,7 +9611,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 382, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -9608,7 +9692,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 379, + "weight": 380, "cookies": false, "type": "upload", "deprecated": false, @@ -9701,7 +9785,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 387, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -9787,7 +9871,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 384, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -9894,7 +9978,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 385, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -9991,7 +10075,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 380, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -10054,7 +10138,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 383, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -10122,7 +10206,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 386, + "weight": 387, "cookies": false, "type": "location", "deprecated": false, @@ -10209,7 +10293,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 388, + "weight": 389, "cookies": false, "type": "", "deprecated": false, @@ -10277,7 +10361,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 391, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -10353,7 +10437,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 389, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -10472,7 +10556,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 390, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -10539,7 +10623,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 392, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -10607,7 +10691,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 397, + "weight": 398, "cookies": false, "type": "", "deprecated": false, @@ -10667,7 +10751,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 395, + "weight": 396, "cookies": false, "type": "", "deprecated": false, @@ -10758,7 +10842,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 396, + "weight": 397, "cookies": false, "type": "", "deprecated": false, @@ -10826,7 +10910,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 398, + "weight": 399, "cookies": false, "type": "", "deprecated": false, @@ -10919,7 +11003,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 399, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -10989,7 +11073,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 305, + "weight": 306, "cookies": false, "type": "graphql", "deprecated": false, @@ -11065,7 +11149,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 304, + "weight": 305, "cookies": false, "type": "graphql", "deprecated": false, @@ -11139,7 +11223,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 129, + "weight": 130, "cookies": false, "type": "", "deprecated": false, @@ -11189,7 +11273,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 150, + "weight": 151, "cookies": false, "type": "", "deprecated": false, @@ -11239,7 +11323,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 132, + "weight": 133, "cookies": false, "type": "", "deprecated": false, @@ -11289,7 +11373,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 137, + "weight": 138, "cookies": false, "type": "", "deprecated": false, @@ -11348,7 +11432,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 131, + "weight": 132, "cookies": false, "type": "", "deprecated": false, @@ -11398,7 +11482,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 133, + "weight": 134, "cookies": false, "type": "", "deprecated": false, @@ -11448,7 +11532,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 139, + "weight": 140, "cookies": false, "type": "", "deprecated": false, @@ -11509,7 +11593,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 138, + "weight": 139, "cookies": false, "type": "", "deprecated": false, @@ -11570,7 +11654,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 140, + "weight": 141, "cookies": false, "type": "", "deprecated": false, @@ -11640,7 +11724,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 141, + "weight": 142, "cookies": false, "type": "", "deprecated": false, @@ -11701,7 +11785,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 151, + "weight": 152, "cookies": false, "type": "", "deprecated": false, @@ -11786,7 +11870,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 145, + "weight": 146, "cookies": false, "type": "", "deprecated": false, @@ -11847,7 +11931,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 136, + "weight": 137, "cookies": false, "type": "", "deprecated": false, @@ -11908,7 +11992,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 142, + "weight": 143, "cookies": false, "type": "", "deprecated": false, @@ -11969,7 +12053,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 143, + "weight": 144, "cookies": false, "type": "", "deprecated": false, @@ -12030,7 +12114,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 144, + "weight": 145, "cookies": false, "type": "", "deprecated": false, @@ -12091,7 +12175,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 146, + "weight": 147, "cookies": false, "type": "", "deprecated": false, @@ -12152,7 +12236,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 147, + "weight": 148, "cookies": false, "type": "", "deprecated": false, @@ -12213,7 +12297,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 135, + "weight": 136, "cookies": false, "type": "", "deprecated": false, @@ -12274,7 +12358,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 149, + "weight": 150, "cookies": false, "type": "", "deprecated": false, @@ -12324,7 +12408,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 148, + "weight": 149, "cookies": false, "type": "", "deprecated": false, @@ -12374,7 +12458,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 134, + "weight": 135, "cookies": false, "type": "", "deprecated": false, @@ -12424,7 +12508,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 121, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -12478,7 +12562,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 122, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -12532,7 +12616,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 126, + "weight": 127, "cookies": false, "type": "", "deprecated": false, @@ -12586,7 +12670,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 123, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -12640,7 +12724,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 124, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -12694,7 +12778,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 125, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -12748,7 +12832,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 127, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -12802,7 +12886,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 128, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -12856,7 +12940,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 359, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -12932,7 +13016,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 356, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -13091,7 +13175,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 363, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -13247,7 +13331,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 358, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -13443,7 +13527,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 365, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -13638,7 +13722,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 357, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -13757,7 +13841,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 364, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -13872,7 +13956,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 362, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -13928,7 +14012,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 366, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -13989,7 +14073,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 360, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -14062,7 +14146,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 361, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -14135,7 +14219,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 331, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -14211,7 +14295,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 330, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -14327,7 +14411,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 343, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -14441,7 +14525,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 329, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -14533,7 +14617,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 342, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -14623,7 +14707,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 321, + "weight": 322, "cookies": false, "type": "", "deprecated": false, @@ -14751,7 +14835,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 334, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -14877,7 +14961,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 324, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -14981,7 +15065,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 337, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -15083,7 +15167,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 322, + "weight": 323, "cookies": false, "type": "", "deprecated": false, @@ -15199,7 +15283,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 335, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -15313,7 +15397,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 323, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -15473,7 +15557,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 336, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -15630,7 +15714,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 325, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -15734,7 +15818,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 338, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -15836,7 +15920,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 326, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -15940,7 +16024,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 339, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -16042,7 +16126,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 327, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -16146,7 +16230,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 340, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -16248,7 +16332,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 328, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -16352,7 +16436,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 341, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -16452,7 +16536,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 333, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -16508,7 +16592,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 344, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -16569,7 +16653,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 332, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -16642,7 +16726,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 353, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -16715,7 +16799,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 346, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -16789,7 +16873,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 345, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -16878,7 +16962,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 348, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -16939,7 +17023,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 349, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -17019,7 +17103,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 350, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -17080,7 +17164,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 347, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -17153,7 +17237,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 352, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -17235,7 +17319,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 351, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -17325,7 +17409,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 354, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -17389,7 +17473,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 355, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -17462,7 +17546,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 404, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -17535,7 +17619,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 402, + "weight": 403, "cookies": false, "type": "", "deprecated": false, @@ -17801,7 +17885,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 407, + "weight": 408, "cookies": false, "type": "", "deprecated": false, @@ -17851,7 +17935,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 430, + "weight": 431, "cookies": false, "type": "", "deprecated": false, @@ -17902,7 +17986,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 403, + "weight": 404, "cookies": false, "type": "", "deprecated": false, @@ -17962,7 +18046,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 405, + "weight": 406, "cookies": false, "type": "", "deprecated": false, @@ -18223,7 +18307,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 406, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -18285,7 +18369,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 413, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -18363,7 +18447,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 412, + "weight": 413, "cookies": false, "type": "", "deprecated": false, @@ -18444,7 +18528,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 408, + "weight": 409, "cookies": false, "type": "upload", "deprecated": false, @@ -18545,7 +18629,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 416, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -18625,7 +18709,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 409, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -18732,7 +18816,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 410, + "weight": 411, "cookies": false, "type": "", "deprecated": false, @@ -18830,7 +18914,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 411, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -18893,7 +18977,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 414, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -18961,7 +19045,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 415, + "weight": 416, "cookies": false, "type": "location", "deprecated": false, @@ -19048,7 +19132,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 417, + "weight": 418, "cookies": false, "type": "", "deprecated": false, @@ -19116,7 +19200,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 419, + "weight": 420, "cookies": false, "type": "", "deprecated": false, @@ -19188,7 +19272,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 418, + "weight": 419, "cookies": false, "type": "", "deprecated": false, @@ -19253,7 +19337,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 420, + "weight": 421, "cookies": false, "type": "", "deprecated": false, @@ -19321,7 +19405,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 423, + "weight": 424, "cookies": false, "type": "", "deprecated": false, @@ -19381,7 +19465,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 421, + "weight": 422, "cookies": false, "type": "", "deprecated": false, @@ -19472,7 +19556,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 422, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -19540,7 +19624,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 424, + "weight": 425, "cookies": false, "type": "", "deprecated": false, @@ -19633,7 +19717,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 425, + "weight": 426, "cookies": false, "type": "", "deprecated": false, @@ -19701,7 +19785,7 @@ "x-appwrite": { "method": "listBuckets", "group": "buckets", - "weight": 206, + "weight": 207, "cookies": false, "type": "", "deprecated": false, @@ -19774,7 +19858,7 @@ "x-appwrite": { "method": "createBucket", "group": "buckets", - "weight": 205, + "weight": 206, "cookies": false, "type": "", "deprecated": false, @@ -19912,7 +19996,7 @@ "x-appwrite": { "method": "getBucket", "group": "buckets", - "weight": 207, + "weight": 208, "cookies": false, "type": "", "deprecated": false, @@ -19972,7 +20056,7 @@ "x-appwrite": { "method": "updateBucket", "group": "buckets", - "weight": 208, + "weight": 209, "cookies": false, "type": "", "deprecated": false, @@ -20106,7 +20190,7 @@ "x-appwrite": { "method": "deleteBucket", "group": "buckets", - "weight": 209, + "weight": 210, "cookies": false, "type": "", "deprecated": false, @@ -20166,7 +20250,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 211, + "weight": 212, "cookies": false, "type": "", "deprecated": false, @@ -20251,7 +20335,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 210, + "weight": 211, "cookies": false, "type": "upload", "deprecated": false, @@ -20343,7 +20427,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 212, + "weight": 213, "cookies": false, "type": "", "deprecated": false, @@ -20415,7 +20499,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 217, + "weight": 218, "cookies": false, "type": "", "deprecated": false, @@ -20506,7 +20590,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 218, + "weight": 219, "cookies": false, "type": "", "deprecated": false, @@ -20578,7 +20662,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 214, + "weight": 215, "cookies": false, "type": "location", "deprecated": false, @@ -20659,7 +20743,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 213, + "weight": 214, "cookies": false, "type": "location", "deprecated": false, @@ -20867,7 +20951,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 215, + "weight": 216, "cookies": false, "type": "location", "deprecated": false, @@ -20948,7 +21032,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 222, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -21025,7 +21109,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 221, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -21117,7 +21201,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 223, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -21181,7 +21265,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 225, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -21258,7 +21342,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 227, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -21322,7 +21406,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 229, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -21407,7 +21491,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 228, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -21522,7 +21606,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 230, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -21594,7 +21678,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 231, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -21682,7 +21766,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 233, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -21756,7 +21840,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 232, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -21851,7 +21935,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 224, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -21913,7 +21997,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 226, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -21993,7 +22077,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 438, + "weight": 439, "cookies": false, "type": "", "deprecated": false, @@ -22074,7 +22158,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 436, + "weight": 437, "cookies": false, "type": "", "deprecated": false, @@ -22159,7 +22243,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 437, + "weight": 438, "cookies": false, "type": "", "deprecated": false, @@ -22220,7 +22304,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 439, + "weight": 440, "cookies": false, "type": "", "deprecated": false, @@ -22292,7 +22376,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 440, + "weight": 441, "cookies": false, "type": "", "deprecated": false, @@ -22353,7 +22437,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 244, + "weight": 245, "cookies": false, "type": "", "deprecated": false, @@ -22426,7 +22510,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 235, + "weight": 236, "cookies": false, "type": "", "deprecated": false, @@ -22522,7 +22606,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 238, + "weight": 239, "cookies": false, "type": "", "deprecated": false, @@ -22614,7 +22698,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 236, + "weight": 237, "cookies": false, "type": "", "deprecated": false, @@ -22704,7 +22788,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 252, + "weight": 253, "cookies": false, "type": "", "deprecated": false, @@ -22774,7 +22858,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 275, + "weight": 276, "cookies": false, "type": "", "deprecated": false, @@ -22836,7 +22920,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 237, + "weight": 238, "cookies": false, "type": "", "deprecated": false, @@ -22928,7 +23012,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 240, + "weight": 241, "cookies": false, "type": "", "deprecated": false, @@ -23020,7 +23104,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 241, + "weight": 242, "cookies": false, "type": "", "deprecated": false, @@ -23147,7 +23231,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 242, + "weight": 243, "cookies": false, "type": "", "deprecated": false, @@ -23260,7 +23344,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 239, + "weight": 240, "cookies": false, "type": "", "deprecated": false, @@ -23371,7 +23455,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 245, + "weight": 246, "cookies": false, "type": "", "deprecated": false, @@ -23426,7 +23510,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 273, + "weight": 274, "cookies": false, "type": "", "deprecated": false, @@ -23488,7 +23572,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 258, + "weight": 259, "cookies": false, "type": "", "deprecated": false, @@ -23568,7 +23652,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 276, + "weight": 277, "cookies": false, "type": "", "deprecated": false, @@ -23651,7 +23735,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 254, + "weight": 255, "cookies": false, "type": "", "deprecated": false, @@ -23732,7 +23816,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 250, + "weight": 251, "cookies": false, "type": "", "deprecated": false, @@ -23804,7 +23888,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 249, + "weight": 250, "cookies": false, "type": "", "deprecated": false, @@ -23887,7 +23971,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 263, + "weight": 264, "cookies": false, "type": "", "deprecated": false, @@ -23962,7 +24046,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 268, + "weight": 269, "cookies": false, "type": "", "deprecated": false, @@ -24035,7 +24119,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 264, + "weight": 265, "cookies": false, "type": "", "deprecated": false, @@ -24095,7 +24179,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 265, + "weight": 266, "cookies": false, "type": "", "deprecated": false, @@ -24155,7 +24239,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 267, + "weight": 268, "cookies": false, "type": "", "deprecated": false, @@ -24215,7 +24299,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 266, + "weight": 267, "cookies": false, "type": "", "deprecated": false, @@ -24277,7 +24361,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 256, + "weight": 257, "cookies": false, "type": "", "deprecated": false, @@ -24357,7 +24441,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 257, + "weight": 258, "cookies": false, "type": "", "deprecated": false, @@ -24437,7 +24521,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 259, + "weight": 260, "cookies": false, "type": "", "deprecated": false, @@ -24515,7 +24599,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 246, + "weight": 247, "cookies": false, "type": "", "deprecated": false, @@ -24575,7 +24659,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 261, + "weight": 262, "cookies": false, "type": "", "deprecated": false, @@ -24653,7 +24737,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 248, + "weight": 249, "cookies": false, "type": "", "deprecated": false, @@ -24713,7 +24797,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 269, + "weight": 270, "cookies": false, "type": "", "deprecated": false, @@ -24768,7 +24852,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 272, + "weight": 273, "cookies": false, "type": "", "deprecated": false, @@ -24825,7 +24909,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 271, + "weight": 272, "cookies": false, "type": "", "deprecated": false, @@ -24895,7 +24979,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 253, + "weight": 254, "cookies": false, "type": "", "deprecated": false, @@ -24973,7 +25057,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 251, + "weight": 252, "cookies": false, "type": "", "deprecated": false, @@ -25046,7 +25130,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 243, + "weight": 244, "cookies": false, "type": "", "deprecated": false, @@ -25158,7 +25242,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 247, + "weight": 248, "cookies": false, "type": "", "deprecated": false, @@ -25227,7 +25311,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 262, + "weight": 263, "cookies": false, "type": "", "deprecated": false, @@ -25318,7 +25402,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 274, + "weight": 275, "cookies": false, "type": "", "deprecated": false, @@ -25389,7 +25473,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 270, + "weight": 271, "cookies": false, "type": "", "deprecated": false, @@ -25472,7 +25556,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 260, + "weight": 261, "cookies": false, "type": "", "deprecated": false, @@ -25552,7 +25636,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 255, + "weight": 256, "cookies": false, "type": "", "deprecated": false, diff --git a/docs/examples/1.7.x/client-android/java/databases/upsert-document.md b/docs/examples/1.7.x/client-android/java/databases/upsert-document.md new file mode 100644 index 0000000000..868576b982 --- /dev/null +++ b/docs/examples/1.7.x/client-android/java/databases/upsert-document.md @@ -0,0 +1,26 @@ +import io.appwrite.Client; +import io.appwrite.coroutines.CoroutineCallback; +import io.appwrite.services.Databases; + +Client client = new Client(context) + .setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("<YOUR_PROJECT_ID>"); // Your project ID + +Databases databases = new Databases(client); + +databases.upsertDocument( + "<DATABASE_ID>", // databaseId + "<COLLECTION_ID>", // collectionId + "<DOCUMENT_ID>", // documentId + mapOf( "a" to "b" ), // data + listOf("read("any")"), // permissions (optional) + new CoroutineCallback<>((result, error) -> { + if (error != null) { + error.printStackTrace(); + return; + } + + Log.d("Appwrite", result.toString()); + }) +); + diff --git a/docs/examples/1.7.x/client-android/kotlin/databases/upsert-document.md b/docs/examples/1.7.x/client-android/kotlin/databases/upsert-document.md new file mode 100644 index 0000000000..a31dfc8797 --- /dev/null +++ b/docs/examples/1.7.x/client-android/kotlin/databases/upsert-document.md @@ -0,0 +1,17 @@ +import io.appwrite.Client +import io.appwrite.coroutines.CoroutineCallback +import io.appwrite.services.Databases + +val client = Client(context) + .setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("<YOUR_PROJECT_ID>") // Your project ID + +val databases = Databases(client) + +val result = databases.upsertDocument( + databaseId = "<DATABASE_ID>", + collectionId = "<COLLECTION_ID>", + documentId = "<DOCUMENT_ID>", + data = mapOf( "a" to "b" ), + permissions = listOf("read("any")"), // (optional) +) \ No newline at end of file diff --git a/docs/examples/1.7.x/client-apple/examples/databases/upsert-document.md b/docs/examples/1.7.x/client-apple/examples/databases/upsert-document.md new file mode 100644 index 0000000000..3e1bf83a66 --- /dev/null +++ b/docs/examples/1.7.x/client-apple/examples/databases/upsert-document.md @@ -0,0 +1,16 @@ +import Appwrite + +let client = Client() + .setEndpoint("https://<REGION>.cloud.appwrite.io/v1") // Your API Endpoint + .setProject("<YOUR_PROJECT_ID>") // Your project ID + +let databases = Databases(client) + +let document = try await databases.upsertDocument( + databaseId: "<DATABASE_ID>", + collectionId: "<COLLECTION_ID>", + documentId: "<DOCUMENT_ID>", + data: [:], + permissions: ["read("any")"] // optional +) + diff --git a/docs/examples/1.7.x/client-flutter/examples/databases/upsert-document.md b/docs/examples/1.7.x/client-flutter/examples/databases/upsert-document.md new file mode 100644 index 0000000000..398a99cb1d --- /dev/null +++ b/docs/examples/1.7.x/client-flutter/examples/databases/upsert-document.md @@ -0,0 +1,15 @@ +import 'package:appwrite/appwrite.dart'; + +Client client = Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +Databases databases = Databases(client); + +Document result = await databases.upsertDocument( + databaseId: '<DATABASE_ID>', + collectionId: '<COLLECTION_ID>', + documentId: '<DOCUMENT_ID>', + data: {}, + permissions: ["read("any")"], // optional +); diff --git a/docs/examples/1.7.x/client-graphql/examples/databases/upsert-document.md b/docs/examples/1.7.x/client-graphql/examples/databases/upsert-document.md new file mode 100644 index 0000000000..2ccab1c490 --- /dev/null +++ b/docs/examples/1.7.x/client-graphql/examples/databases/upsert-document.md @@ -0,0 +1,17 @@ +mutation { + databasesUpsertDocument( + databaseId: "<DATABASE_ID>", + collectionId: "<COLLECTION_ID>", + documentId: "<DOCUMENT_ID>", + data: "{}", + permissions: ["read("any")"] + ) { + _id + _collectionId + _databaseId + _createdAt + _updatedAt + _permissions + data + } +} diff --git a/docs/examples/1.7.x/client-react-native/examples/databases/upsert-document.md b/docs/examples/1.7.x/client-react-native/examples/databases/upsert-document.md new file mode 100644 index 0000000000..ae423d12a7 --- /dev/null +++ b/docs/examples/1.7.x/client-react-native/examples/databases/upsert-document.md @@ -0,0 +1,17 @@ +import { Client, Databases } from "react-native-appwrite"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const databases = new Databases(client); + +const result = await databases.upsertDocument( + '<DATABASE_ID>', // databaseId + '<COLLECTION_ID>', // collectionId + '<DOCUMENT_ID>', // documentId + {}, // data + ["read("any")"] // permissions (optional) +); + +console.log(result); diff --git a/docs/examples/1.7.x/client-rest/examples/databases/upsert-document.md b/docs/examples/1.7.x/client-rest/examples/databases/upsert-document.md new file mode 100644 index 0000000000..f834802b7e --- /dev/null +++ b/docs/examples/1.7.x/client-rest/examples/databases/upsert-document.md @@ -0,0 +1,12 @@ +PUT /v1/databases/{databaseId}/collections/{collectionId}/documents/{documentId} HTTP/1.1 +Host: cloud.appwrite.io +Content-Type: application/json +X-Appwrite-Response-Format: 1.7.0 +X-Appwrite-Project: <YOUR_PROJECT_ID> +X-Appwrite-Session: +X-Appwrite-JWT: <YOUR_JWT> + +{ + "data": {}, + "permissions": ["read(\"any\")"] +} diff --git a/docs/examples/1.7.x/client-web/examples/databases/upsert-document.md b/docs/examples/1.7.x/client-web/examples/databases/upsert-document.md new file mode 100644 index 0000000000..cfefe06242 --- /dev/null +++ b/docs/examples/1.7.x/client-web/examples/databases/upsert-document.md @@ -0,0 +1,17 @@ +import { Client, Databases } from "appwrite"; + +const client = new Client() + .setEndpoint('https://<REGION>.cloud.appwrite.io/v1') // Your API Endpoint + .setProject('<YOUR_PROJECT_ID>'); // Your project ID + +const databases = new Databases(client); + +const result = await databases.upsertDocument( + '<DATABASE_ID>', // databaseId + '<COLLECTION_ID>', // collectionId + '<DOCUMENT_ID>', // documentId + {}, // data + ["read("any")"] // permissions (optional) +); + +console.log(result); diff --git a/docs/sdks/flutter/CHANGELOG.md b/docs/sdks/flutter/CHANGELOG.md index 674742b845..be03d0fa2a 100644 --- a/docs/sdks/flutter/CHANGELOG.md +++ b/docs/sdks/flutter/CHANGELOG.md @@ -1,5 +1,10 @@ # Change Log +## 16.0.1 + +* Add `setDevKey` method to Client service +* Add `upsertDocument` method to Databases service + ## 16.0.0 * Remove `Gif` from ImageFormat enum From f534b9e460a1ce3727fd73168ace33dfffd039a3 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k <arnabchatterjee.ac.2@gmail.com> Date: Wed, 21 May 2025 11:00:01 +0530 Subject: [PATCH 041/219] added checking for encrypt and plan allowing encryption of string attribute --- app/controllers/api/databases.php | 6 +++++- tests/e2e/Services/Databases/DatabasesBase.php | 14 ++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 8883e245b6..90b482e0b8 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1347,7 +1347,11 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + ->inject('plan') + ->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, array $plan) { + if ($encrypt && !isset($plan['databasesAllowEncrypt'])) { + throw new Exception(Exception::ATTRIBUTE_FORMAT_UNSUPPORTED, 'Encrypted string attributes are not available on your plan. Please upgrade to create encrypted string attributes.'); + } // Ensure attribute default is within required size $validator = new Text($size, 0); if (!is_null($default) && !$validator->isValid($default)) { diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 7c0060ecaa..c16701db42 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -195,6 +195,20 @@ trait DatabasesBase public function testCreateAttributes(array $data): array { $databaseId = $data['databaseId']; + // must fail as we are using encrypt and plan has no 'databasesAllowEncrypt' + $encryptStringAttribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'title', + 'size' => 256, + 'required' => true, + 'encrypt' => true + ]); + + $this->assertEquals(400, $encryptStringAttribute['headers']['status-code']); + $this->assertEquals($encryptStringAttribute['body']['message'], 'Encrypted string attributes are not available on your plan. Please upgrade to create encrypted string attributes.'); $title = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', From 43aae24132f6a60f169848c365c58ad3b1459595 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k <arnabchatterjee.ac.2@gmail.com> Date: Wed, 21 May 2025 11:38:34 +0530 Subject: [PATCH 042/219] updated tests for the custom server test --- .../Databases/DatabasesCustomServerTest.php | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 829960b54f..36b50bed62 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -687,6 +687,7 @@ class DatabasesCustomServerTest extends Scope 'required' => true, ]); + // must fail due to encrpt and no plan $lastName = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -698,6 +699,18 @@ class DatabasesCustomServerTest extends Scope 'encrypt' => true, ]); + $this->assertEquals(400, $lastName['headers']['status-code']); + + $lastName = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'lastName', + 'size' => 256, + 'required' => true, + ]); + /** * Check status of every attribute From cca95d5bd2fd5769752f9647f0b5fc0c1dfe9d9d Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Wed, 21 May 2025 06:36:09 +0000 Subject: [PATCH 043/219] chore: update to minor versions --- app/config/platforms.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/config/platforms.php b/app/config/platforms.php index 11479f23ad..358edd0cf8 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -11,7 +11,7 @@ return [ [ 'key' => 'web', 'name' => 'Web', - 'version' => '18.0.1', + 'version' => '18.1.0', 'url' => 'https://github.com/appwrite/sdk-for-web', 'package' => 'https://www.npmjs.com/package/appwrite', 'enabled' => true, @@ -59,7 +59,7 @@ return [ [ 'key' => 'flutter', 'name' => 'Flutter', - 'version' => '16.0.1', + 'version' => '16.1.0', 'url' => 'https://github.com/appwrite/sdk-for-flutter', 'package' => 'https://pub.dev/packages/appwrite', 'enabled' => true, @@ -77,7 +77,7 @@ return [ [ 'key' => 'apple', 'name' => 'Apple', - 'version' => '10.0.1', + 'version' => '10.1.0', 'url' => 'https://github.com/appwrite/sdk-for-apple', 'package' => 'https://github.com/appwrite/sdk-for-apple', 'enabled' => true, @@ -112,7 +112,7 @@ return [ [ 'key' => 'android', 'name' => 'Android', - 'version' => '8.0.1', + 'version' => '8.1.0', 'url' => 'https://github.com/appwrite/sdk-for-android', 'package' => 'https://search.maven.org/artifact/io.appwrite/sdk-for-android', 'enabled' => true, From fe5419401a3ca08d4eb614a3a720dc0427cdf30c Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Wed, 21 May 2025 07:28:25 +0000 Subject: [PATCH 044/219] chore: use unique filename for health check --- app/controllers/api/health.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index 11fc4cc244..825244e776 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -852,15 +852,18 @@ App::get('/v1/health/storage') $checkStart = \microtime(true); foreach ($devices as $device) { - if (!$device->write($device->getPath('health.txt'), 'test', 'text/plain')) { + $uniqueFileName = \uniqid('health', true); + $filePath = $device->getPath($uniqueFileName); + + if (!$device->write($filePath, 'test', 'text/plain')) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed writing test file to ' . $device->getRoot()); } - if ($device->read($device->getPath('health.txt')) !== 'test') { + if ($device->read($filePath) !== 'test') { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed reading test file from ' . $device->getRoot()); } - if (!$device->delete($device->getPath('health.txt'))) { + if (!$device->delete($filePath)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed deleting test file from ' . $device->getRoot()); } } From 20f2cbffda764cf3c26fb78b3071855d98f39c6a Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Tue, 20 May 2025 14:37:10 +0000 Subject: [PATCH 045/219] Merge pull request #9811 from ArnabChatterjee20k/upsert-single-document-route Upsert single document route --- app/controllers/api/databases.php | 238 ++++++++++++++ docs/references/databases/upsert-document.md | 1 + .../e2e/Services/Databases/DatabasesBase.php | 303 +++++++++++++++++- 3 files changed, 541 insertions(+), 1 deletion(-) create mode 100644 docs/references/databases/upsert-document.md diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index ec402333e4..68d8891067 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4207,6 +4207,244 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $response->dynamic($document, Response::MODEL_DOCUMENT); }); +App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId') + ->desc('Upsert document') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].upsert') + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'document.upsert') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}/document/{response.$id}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', new Method( + namespace: 'databases', + group: 'documents', + name: 'upsertDocument', + description: '/docs/references/databases/upsert-document.md', + auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DOCUMENT, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('documentId', '', new CustomId(), 'Document ID.') + ->param('data', [], new JSON(), 'Document data as JSON object. Include all required attributes of the document to be created or updated.') + ->param('permissions', null, new Permissions(APP_LIMIT_ARRAY_PARAMS_SIZE, [Database::PERMISSION_READ, Database::PERMISSION_UPDATE, Database::PERMISSION_DELETE, Database::PERMISSION_WRITE]), 'An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https://appwrite.io/docs/permissions).', true) + ->inject('requestTimestamp') + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->action(function (string $databaseId, string $collectionId, string $documentId, string|array $data, ?array $permissions, ?\DateTime $requestTimestamp, Response $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) { + $data = (\is_string($data)) ? \json_decode($data, true) : $data; // Cast to JSON array + + if (empty($data) && \is_null($permissions)) { + throw new Exception(Exception::DOCUMENT_MISSING_PAYLOAD); + } + + $isAPIKey = Auth::isAppUser(Authorization::getRoles()); + $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); + + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); + if ($database->isEmpty() || (!$database->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + // Map aggregate permissions into the multiple permissions they represent. + $permissions = Permission::aggregate($permissions, [ + Database::PERMISSION_READ, + Database::PERMISSION_UPDATE, + Database::PERMISSION_DELETE, + ]); + + // Users can only manage their own roles, API keys and Admin users can manage any + $roles = Authorization::getRoles(); + if (!$isAPIKey && !$isPrivilegedUser && !\is_null($permissions)) { + foreach (Database::PERMISSIONS as $type) { + foreach ($permissions as $permission) { + $permission = Permission::parse($permission); + if ($permission->getPermission() != $type) { + continue; + } + $role = (new Role( + $permission->getRole(), + $permission->getIdentifier(), + $permission->getDimension() + ))->toString(); + if (!Authorization::isRole($role)) { + throw new Exception(Exception::USER_UNAUTHORIZED, 'Permissions must be one of: (' . \implode(', ', $roles) . ')'); + } + } + } + } + + $data['$id'] = $documentId; + $data['$permissions'] = $permissions; + $newDocument = new Document($data); + + $operations = 0; + + $setCollection = (function (Document $collection, Document $document) use (&$setCollection, $dbForProject, $database, &$operations) { + + $operations++; + + $relationships = \array_filter( + $collection->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $document->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + continue; + } + + $isList = \is_array($related) && \array_values($related) === $related; + + if ($isList) { + $relations = $related; + } else { + $relations = [$related]; + } + + $relatedCollectionId = $relationship->getAttribute('relatedCollection'); + $relatedCollection = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + ); + + foreach ($relations as &$relation) { + // If the relation is an array it can be either update or create a child document. + if ( + \is_array($relation) + && \array_values($relation) !== $relation + && !isset($relation['$id']) + ) { + $relation['$id'] = ID::unique(); + $relation = new Document($relation); + } + if ($relation instanceof Document) { + $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( + 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), + $relation->getId() + )); + $relation->removeAttribute('$collectionId'); + $relation->removeAttribute('$databaseId'); + // Attribute $collection is required for Utopia. + $relation->setAttribute( + '$collection', + 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId() + ); + + if ($oldDocument->isEmpty()) { + if (isset($relation['$id']) && $relation['$id'] === 'unique()') { + $relation['$id'] = ID::unique(); + } + } + $setCollection($relatedCollection, $relation); + } + } + + if ($isList) { + $document->setAttribute($relationship->getAttribute('key'), \array_values($relations)); + } else { + $document->setAttribute($relationship->getAttribute('key'), \reset($relations)); + } + } + }); + + $setCollection($collection, $newDocument); + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations)) + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); + + $upserted = []; + try { + $modified = $dbForProject->createOrUpdateDocuments( + 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + [$newDocument], + onNext: function (Document $document) use (&$upserted) { + $upserted[] = $document; + }, + ); + } catch (ConflictException) { + throw new Exception(Exception::DOCUMENT_UPDATE_CONFLICT); + } catch (DuplicateException) { + throw new Exception(Exception::DOCUMENT_ALREADY_EXISTS); + } catch (RelationshipException $e) { + throw new Exception(Exception::RELATIONSHIP_VALUE_INVALID, $e->getMessage()); + } catch (StructureException $e) { + throw new Exception(Exception::DOCUMENT_INVALID_STRUCTURE, $e->getMessage()); + } + + $document = $upserted[0]; + // Add $collectionId and $databaseId for all documents + $processDocument = function (Document $collection, Document $document) use (&$processDocument, $dbForProject, $database) { + $document->setAttribute('$databaseId', $database->getId()); + $document->setAttribute('$collectionId', $collection->getId()); + + $relationships = \array_filter( + $collection->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ); + + foreach ($relationships as $relationship) { + $related = $document->getAttribute($relationship->getAttribute('key')); + + if (empty($related)) { + continue; + } + if (!\is_array($related)) { + $related = [$related]; + } + + $relatedCollectionId = $relationship->getAttribute('relatedCollection'); + $relatedCollection = Authorization::skip( + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + ); + + foreach ($related as $relation) { + if ($relation instanceof Document) { + $processDocument($relatedCollection, $relation); + } + } + } + }; + + $processDocument($collection, $document); + + $relationships = \array_map( + fn ($document) => $document->getAttribute('key'), + \array_filter( + $collection->getAttribute('attributes', []), + fn ($attribute) => $attribute->getAttribute('type') === Database::VAR_RELATIONSHIP + ) + ); + + $queueForEvents + ->setParam('databaseId', $databaseId) + ->setParam('collectionId', $collection->getId()) + ->setParam('documentId', $document->getId()) + ->setContext('collection', $collection) + ->setContext('database', $database) + ->setPayload($response->getPayload(), sensitive: $relationships); + + $response->dynamic($document, Response::MODEL_DOCUMENT); + }); + App::patch('/v1/databases/:databaseId/collections/:collectionId/documents') ->desc('Update documents') ->groups(['api', 'database']) diff --git a/docs/references/databases/upsert-document.md b/docs/references/databases/upsert-document.md new file mode 100644 index 0000000000..a67694cfa6 --- /dev/null +++ b/docs/references/databases/upsert-document.md @@ -0,0 +1 @@ +Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https://appwrite.io/docs/server/databases#databasesCreateCollection) API or directly from your database console. \ No newline at end of file diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 2b60dee856..7c0060ecaa 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -12,7 +12,6 @@ use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; use Utopia\Database\Query; use Utopia\Database\Validator\Datetime as DatetimeValidator; -use Utopia\Validator\JSON; trait DatabasesBase { @@ -1683,6 +1682,308 @@ trait DatabasesBase return $data; } + /** + * @depends testCreateIndexes + */ + public function testUpsertDocument(array $data): void + { + $databaseId = $data['databaseId']; + $documentId = ID::unique(); + $document = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'title' => 'Thor: Ragnarok', + 'releaseYear' => 2000 + ], + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + ]); + + $this->assertEquals(200, $document['headers']['status-code']); + $this->assertCount(3, $document['body']['$permissions']); + $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('Thor: Ragnarok', $document['body']['title']); + + $document = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'title' => 'Thor: Love and Thunder', + 'releaseYear' => 2000 + ], + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + ]); + + $this->assertEquals(200, $document['headers']['status-code']); + $this->assertEquals('Thor: Love and Thunder', $document['body']['title']); + + $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals('Thor: Love and Thunder', $document['body']['title']); + + // removing permission to read and delete + $document = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'title' => 'Thor: Love and Thunder', + 'releaseYear' => 2000 + ], + 'permissions' => [ + Permission::update(Role::users()) + ], + ]); + // shouldn't be able to read as no read permission + $document = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + switch ($this->getSide()) { + case 'client': + $this->assertEquals(404, $document['headers']['status-code']); + break; + case 'server': + $this->assertEquals(200, $document['headers']['status-code']); + break; + } + // shouldn't be able to delete as no delete permission + $document = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + // simulating for the client + // the document should not be allowed to be deleted as needed downward + if ($this->getSide() === 'client') { + $this->assertEquals(401, $document['headers']['status-code']); + } + // giving the delete permission + $document = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'title' => 'Thor: Love and Thunder', + 'releaseYear' => 2000 + ], + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()) + ], + ]); + $document = $this->client->call(Client::METHOD_DELETE, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(204, $document['headers']['status-code']); + + // relationship behaviour + $person = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => 'person-upsert', + 'name' => 'person', + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + Permission::create(Role::users()), + ], + 'documentSecurity' => true, + ]); + + $this->assertEquals(201, $person['headers']['status-code']); + + $library = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => 'library-upsert', + 'name' => 'library', + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::create(Role::users()), + Permission::delete(Role::users()), + ], + 'documentSecurity' => true, + ]); + + $this->assertEquals(201, $library['headers']['status-code']); + + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/attributes/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'fullName', + 'size' => 255, + 'required' => false, + ]); + + sleep(1); // Wait for worker + + $relation = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/attributes/relationship', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'relatedCollectionId' => 'library-upsert', + 'type' => Database::RELATION_ONE_TO_ONE, + 'key' => 'library', + 'twoWay' => true, + 'onDelete' => Database::RELATION_MUTATE_CASCADE, + ]); + + sleep(1); // Wait for worker + + $libraryName = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $library['body']['$id'] . '/attributes/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'libraryName', + 'size' => 255, + 'required' => true, + ]); + + sleep(1); // Wait for worker + + $this->assertEquals(202, $libraryName['headers']['status-code']); + + // upserting values + $documentId = ID::unique(); + $person1 = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents/'.$documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'library' => [ + '$id' => 'library1', + '$permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + 'libraryName' => 'Library 1', + ], + ], + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ] + ]); + + $this->assertEquals('Library 1', $person1['body']['library']['libraryName']); + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::select(['fullName', 'library.*'])->toString(), + Query::equal('library', ['library1'])->toString(), + ], + ]); + + $this->assertEquals(1, $documents['body']['total']); + $this->assertEquals('Library 1', $documents['body']['documents'][0]['library']['libraryName']); + + + $person1 = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents/'.$documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'library' => [ + '$id' => 'library1', + '$permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + 'libraryName' => 'Library 2', + ], + ], + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ] + ]); + + // data should get updated + $this->assertEquals('Library 2', $person1['body']['library']['libraryName']); + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::select(['fullName', 'library.*'])->toString(), + Query::equal('library', ['library1'])->toString(), + ], + ]); + + $this->assertEquals(1, $documents['body']['total']); + $this->assertEquals('Library 2', $documents['body']['documents'][0]['library']['libraryName']); + + + // data should get added + $person1 = $this->client->call(Client::METHOD_PUT, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents/'.ID::unique(), array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'data' => [ + 'library' => [ + '$id' => 'library2', + '$permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ], + 'libraryName' => 'Library 2', + ], + ], + 'permissions' => [ + Permission::read(Role::users()), + Permission::update(Role::users()), + Permission::delete(Role::users()), + ] + ]); + + $this->assertEquals('Library 2', $person1['body']['library']['libraryName']); + $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'queries' => [ + Query::select(['fullName', 'library.*'])->toString() + ], + ]); + $this->assertEquals(2, $documents['body']['total']); + } + /** * @depends testCreateDocument */ From 9fa6deae6104fd3d1308de9a01b774e3b54c0b38 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k <arnabchatterjee.ac.2@gmail.com> Date: Wed, 21 May 2025 13:14:22 +0530 Subject: [PATCH 046/219] reverted the tests and updated the plan checking condition --- app/controllers/api/databases.php | 2 +- tests/e2e/Services/Databases/DatabasesBase.php | 14 -------------- .../Databases/DatabasesCustomServerTest.php | 14 -------------- 3 files changed, 1 insertion(+), 29 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 90b482e0b8..c2c1a9d6b5 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1349,7 +1349,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string ->inject('queueForEvents') ->inject('plan') ->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, array $plan) { - if ($encrypt && !isset($plan['databasesAllowEncrypt'])) { + if ($encrypt && !empty($plan) && !isset($plan['databasesAllowEncrypt'])) { throw new Exception(Exception::ATTRIBUTE_FORMAT_UNSUPPORTED, 'Encrypted string attributes are not available on your plan. Please upgrade to create encrypted string attributes.'); } // Ensure attribute default is within required size diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index c16701db42..7c0060ecaa 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -195,20 +195,6 @@ trait DatabasesBase public function testCreateAttributes(array $data): array { $databaseId = $data['databaseId']; - // must fail as we are using encrypt and plan has no 'databasesAllowEncrypt' - $encryptStringAttribute = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/string', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] - ]), [ - 'key' => 'title', - 'size' => 256, - 'required' => true, - 'encrypt' => true - ]); - - $this->assertEquals(400, $encryptStringAttribute['headers']['status-code']); - $this->assertEquals($encryptStringAttribute['body']['message'], 'Encrypted string attributes are not available on your plan. Please upgrade to create encrypted string attributes.'); $title = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $data['moviesId'] . '/attributes/string', array_merge([ 'content-type' => 'application/json', diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 36b50bed62..b0517a9fbd 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -687,20 +687,6 @@ class DatabasesCustomServerTest extends Scope 'required' => true, ]); - // must fail due to encrpt and no plan - $lastName = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] - ]), [ - 'key' => 'lastName', - 'size' => 256, - 'required' => true, - 'encrypt' => true, - ]); - - $this->assertEquals(400, $lastName['headers']['status-code']); - $lastName = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], From 8796670c667b94ff841c410fbadb167388922a17 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k <arnabchatterjee.ac.2@gmail.com> Date: Wed, 21 May 2025 13:19:07 +0530 Subject: [PATCH 047/219] reverted test --- tests/e2e/Services/Databases/DatabasesCustomServerTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index b0517a9fbd..67f7a07a9b 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -695,6 +695,7 @@ class DatabasesCustomServerTest extends Scope 'key' => 'lastName', 'size' => 256, 'required' => true, + 'encrypt' => true ]); From 82fd8553bf4745c89aaa21c55016209fb9e56073 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k <arnabchatterjee.ac.2@gmail.com> Date: Wed, 21 May 2025 13:29:24 +0530 Subject: [PATCH 048/219] updated the condition --- app/controllers/api/databases.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index c2c1a9d6b5..5d6533e2b2 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1349,7 +1349,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string ->inject('queueForEvents') ->inject('plan') ->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, array $plan) { - if ($encrypt && !empty($plan) && !isset($plan['databasesAllowEncrypt'])) { + if ($encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) { throw new Exception(Exception::ATTRIBUTE_FORMAT_UNSUPPORTED, 'Encrypted string attributes are not available on your plan. Please upgrade to create encrypted string attributes.'); } // Ensure attribute default is within required size From c4df1c8c4b7e9f505155f3cbc1f73f3032b6a6f1 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k <arnabchatterjee.ac.2@gmail.com> Date: Wed, 21 May 2025 13:34:08 +0530 Subject: [PATCH 049/219] updated exception type --- app/controllers/api/databases.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 5d6533e2b2..d495a1d924 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1350,7 +1350,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string ->inject('plan') ->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, array $plan) { if ($encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) { - throw new Exception(Exception::ATTRIBUTE_FORMAT_UNSUPPORTED, 'Encrypted string attributes are not available on your plan. Please upgrade to create encrypted string attributes.'); + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string attributes are not available on your plan. Please upgrade to create encrypted string attributes.'); } // Ensure attribute default is within required size $validator = new Text($size, 0); From ba3f907028877c565df05fce6d3b9124f5a17f53 Mon Sep 17 00:00:00 2001 From: Fabian Gruber <fabian@appwrite.io> Date: Wed, 21 May 2025 10:57:58 +0200 Subject: [PATCH 050/219] fix(storage): do not allow full range This prevents requests with `Range: 0-<file length>` and limits it to APP_STORAGE_READ_BUFFER --- app/controllers/api/storage.php | 60 ++++++++++++++++----------------- 1 file changed, 30 insertions(+), 30 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index a96b871bf2..4a158bb68e 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -996,7 +996,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $algorithm = $file->getAttribute('algorithm', Compression::NONE); $cipher = $file->getAttribute('openSSLCipher'); $mime = $file->getAttribute('mimeType'); - if (!\in_array($mime, $inputs) || $file->getAttribute('sizeActual') > (int) System::getEnv('_APP_STORAGE_PREVIEW_LIMIT', 20000000)) { + if (!\in_array($mime, $inputs) || $file->getAttribute('sizeActual') > (int) System::getEnv('_APP_STORAGE_PREVIEW_LIMIT', APP_STORAGE_READ_BUFFER)) { if (!\in_array($mime, $inputs)) { $path = (\array_key_exists($mime, $fileLogos)) ? $fileLogos[$mime] : $fileLogos['default']; } else { @@ -1162,13 +1162,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in ' . $path); } - $response - ->setContentType($file->getAttribute('mimeType')) - ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days - ->addHeader('X-Peak', \memory_get_peak_usage()) - ->addHeader('Content-Disposition', 'attachment; filename="' . $file->getAttribute('name', '') . '"') - ; - $size = $file->getAttribute('sizeOriginal', 0); $rangeHeader = $request->getHeader('range'); @@ -1177,7 +1170,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') $end = $request->getRangeEnd(); $unit = $request->getRangeUnit(); - if ($end === null) { + if ($end === null || $end - $start > APP_STORAGE_READ_BUFFER) { $end = min(($start + MAX_OUTPUT_CHUNK_SIZE - 1), ($size - 1)); } @@ -1192,6 +1185,13 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') ->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT); } + $response + ->setContentType($file->getAttribute('mimeType')) + ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days + ->addHeader('X-Peak', \memory_get_peak_usage()) + ->addHeader('Content-Disposition', 'attachment; filename="' . $file->getAttribute('name', '') . '"') + ; + $source = ''; if (!empty($file->getAttribute('openSSLCipher'))) { // Decrypt $source = $deviceForFiles->read($path); @@ -1321,15 +1321,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') $contentType = $file->getAttribute('mimeType'); } - $response - ->setContentType($contentType) - ->addHeader('Content-Security-Policy', 'script-src none;') - ->addHeader('X-Content-Type-Options', 'nosniff') - ->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"') - ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days - ->addHeader('X-Peak', \memory_get_peak_usage()) - ; - $size = $file->getAttribute('sizeOriginal', 0); $rangeHeader = $request->getHeader('range'); @@ -1338,8 +1329,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') $end = $request->getRangeEnd(); $unit = $request->getRangeUnit(); - if ($end === null) { - $end = min(($start + 2000000 - 1), ($size - 1)); + if ($end === null || $end - $start > APP_STORAGE_READ_BUFFER) { + $end = min(($start + APP_STORAGE_READ_BUFFER - 1), ($size - 1)); } if ($unit != 'bytes' || $start >= $end || $end >= $size) { @@ -1353,6 +1344,15 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') ->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT); } + $response + ->setContentType($contentType) + ->addHeader('Content-Security-Policy', 'script-src none;') + ->addHeader('X-Content-Type-Options', 'nosniff') + ->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"') + ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days + ->addHeader('X-Peak', \memory_get_peak_usage()) + ; + $source = ''; if (!empty($file->getAttribute('openSSLCipher'))) { // Decrypt $source = $deviceForFiles->read($path); @@ -1474,14 +1474,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') $contentType = $file->getAttribute('mimeType'); } - $response - ->setContentType($contentType) - ->addHeader('Content-Security-Policy', 'script-src none;') - ->addHeader('X-Content-Type-Options', 'nosniff') - ->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"') - ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days - ->addHeader('X-Peak', \memory_get_peak_usage()); - $size = $file->getAttribute('sizeOriginal', 0); $rangeHeader = $request->getHeader('range'); @@ -1490,8 +1482,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') $end = $request->getRangeEnd(); $unit = $request->getRangeUnit(); - if ($end === null) { - $end = min(($start + 2000000 - 1), ($size - 1)); + if ($end === null || $end - $start > APP_STORAGE_READ_BUFFER) { + $end = min(($start + APP_STORAGE_READ_BUFFER - 1), ($size - 1)); } if ($unit != 'bytes' || $start >= $end || $end >= $size) { @@ -1505,6 +1497,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') ->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT); } + $response + ->setContentType($contentType) + ->addHeader('Content-Security-Policy', 'script-src none;') + ->addHeader('X-Content-Type-Options', 'nosniff') + ->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"') + ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days + ->addHeader('X-Peak', \memory_get_peak_usage()); + $source = ''; if (!empty($file->getAttribute('openSSLCipher'))) { // Decrypt $source = $deviceForFiles->read($path); From d9bd867b385a2c63745482cea0f30c1400500239 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Wed, 21 May 2025 10:32:56 +0000 Subject: [PATCH 051/219] fix: allow devkeys header to pass CORS --- app/controllers/general.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index 13433b98c8..26874d4f66 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -1030,7 +1030,7 @@ App::init() ->addHeader('Server', 'Appwrite') ->addHeader('X-Content-Type-Options', 'nosniff') ->addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE') - ->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Forwarded-For, X-Forwarded-User-Agent') + ->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Dev-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Forwarded-For, X-Forwarded-User-Agent') ->addHeader('Access-Control-Expose-Headers', 'X-Appwrite-Session, X-Fallback-Cookies') ->addHeader('Access-Control-Allow-Origin', $refDomain) ->addHeader('Access-Control-Allow-Credentials', 'true'); @@ -1093,7 +1093,7 @@ App::options() $response ->addHeader('Server', 'Appwrite') ->addHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, PATCH, DELETE') - ->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Appwrite-Session, X-Fallback-Cookies, X-Forwarded-For, X-Forwarded-User-Agent') + ->addHeader('Access-Control-Allow-Headers', 'Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Dev-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Appwrite-Session, X-Fallback-Cookies, X-Forwarded-For, X-Forwarded-User-Agent') ->addHeader('Access-Control-Expose-Headers', 'X-Appwrite-Session, X-Fallback-Cookies') ->addHeader('Access-Control-Allow-Origin', $origin) ->addHeader('Access-Control-Allow-Credentials', 'true') From eda1bf3207f19ee77236fa3e33628642f0fca880 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Wed, 21 May 2025 11:05:16 +0000 Subject: [PATCH 052/219] chore: update test --- tests/e2e/General/HTTPTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/General/HTTPTest.php b/tests/e2e/General/HTTPTest.php index fe600cd0f8..620409bb39 100644 --- a/tests/e2e/General/HTTPTest.php +++ b/tests/e2e/General/HTTPTest.php @@ -31,7 +31,7 @@ class HTTPTest extends Scope $this->assertEquals(204, $response['headers']['status-code']); $this->assertEquals('Appwrite', $response['headers']['server']); $this->assertEquals('GET, POST, PUT, PATCH, DELETE', $response['headers']['access-control-allow-methods']); - $this->assertEquals('Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Appwrite-Session, X-Fallback-Cookies, X-Forwarded-For, X-Forwarded-User-Agent', $response['headers']['access-control-allow-headers']); + $this->assertEquals('Origin, Cookie, Set-Cookie, X-Requested-With, Content-Type, Access-Control-Allow-Origin, Access-Control-Request-Headers, Accept, X-Appwrite-Project, X-Appwrite-Key, X-Appwrite-Dev-Key, X-Appwrite-Locale, X-Appwrite-Mode, X-Appwrite-JWT, X-Appwrite-Response-Format, X-Appwrite-Timeout, X-SDK-Version, X-SDK-Name, X-SDK-Language, X-SDK-Platform, X-SDK-GraphQL, X-Appwrite-ID, X-Appwrite-Timestamp, Content-Range, Range, Cache-Control, Expires, Pragma, X-Appwrite-Session, X-Fallback-Cookies, X-Forwarded-For, X-Forwarded-User-Agent', $response['headers']['access-control-allow-headers']); $this->assertEquals('X-Appwrite-Session, X-Fallback-Cookies', $response['headers']['access-control-expose-headers']); $this->assertEquals('http://localhost', $response['headers']['access-control-allow-origin']); $this->assertEquals('true', $response['headers']['access-control-allow-credentials']); From 280369340224b46ceb758b77e2391e21dfbc258b Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Wed, 21 May 2025 13:43:10 +0000 Subject: [PATCH 053/219] chore: sync with main --- .github/workflows/sdk-preview.yml | 2 +- composer.json | 2 +- composer.lock | 20 +++++++++++--------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/.github/workflows/sdk-preview.yml b/.github/workflows/sdk-preview.yml index e317845768..8abe2c2f91 100644 --- a/.github/workflows/sdk-preview.yml +++ b/.github/workflows/sdk-preview.yml @@ -47,7 +47,7 @@ jobs: node-version: 20 - name: Build and Publish SDK - working-directory: ./app/sdks/console-web + working-directory: ./app/sdks/${{ steps.set-sdk.outputs.platform }}-${{ steps.set-sdk.outputs.sdk_type }} run: | npm install npm run build diff --git a/composer.json b/composer.json index 7e445cd36b..20b0317b3e 100644 --- a/composer.json +++ b/composer.json @@ -86,7 +86,7 @@ }, "require-dev": { "ext-fileinfo": "*", - "appwrite/sdk-generator": "0.40.*", + "appwrite/sdk-generator": "dev-fix-devkeys-header", "phpunit/phpunit": "9.*", "swoole/ide-helper": "5.1.2", "phpstan/phpstan": "1.8.*", diff --git a/composer.lock b/composer.lock index f36b815777..d762ace581 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9f5de64d73e2ef73d796fa64f2baf232", + "content-hash": "d4762811abd986e47a4d1259cfb1a0de", "packages": [ { "name": "adhocore/jwt", @@ -4816,16 +4816,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.40.17", + "version": "dev-fix-devkeys-header", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de" + "reference": "6a31bbe97dbfa972960fbc4d9ed51dfcee6deb07" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de", - "reference": "7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/6a31bbe97dbfa972960fbc4d9ed51dfcee6deb07", + "reference": "6a31bbe97dbfa972960fbc4d9ed51dfcee6deb07", "shasum": "" }, "require": { @@ -4861,9 +4861,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.40.17" + "source": "https://github.com/appwrite/sdk-generator/tree/fix-devkeys-header" }, - "time": "2025-05-16T15:10:54+00:00" + "time": "2025-05-21T13:05:09+00:00" }, { "name": "doctrine/annotations", @@ -8242,7 +8242,9 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "appwrite/sdk-generator": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -8266,5 +8268,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } From 241a0c88e1da48032739c89dd718ddac8de753fc Mon Sep 17 00:00:00 2001 From: Fabian Gruber <fabian@appwrite.io> Date: Wed, 21 May 2025 16:21:11 +0200 Subject: [PATCH 054/219] fix: task coroutine hooks --- app/cli.php | 3 +-- composer.lock | 12 ++++++------ src/Appwrite/Platform/Tasks/ScheduleBase.php | 10 +++++----- src/Appwrite/Platform/Tasks/ScheduleFunctions.php | 2 +- src/Appwrite/Platform/Tasks/ScheduleMessages.php | 2 +- 5 files changed, 14 insertions(+), 15 deletions(-) diff --git a/app/cli.php b/app/cli.php index aaa8468ef3..7b8d6cd52f 100644 --- a/app/cli.php +++ b/app/cli.php @@ -284,6 +284,5 @@ $cli $cli->shutdown()->action(fn () => Timer::clearAll()); -// Enable coroutines, but disable TCP hooks. These don't work until we use `\Utopia\Cache\Adapter\Pool` and `\Utopia\Database\Adapter\Pool`. -Runtime::enableCoroutine(SWOOLE_HOOK_ALL ^ SWOOLE_HOOK_TCP); +Runtime::enableCoroutine(SWOOLE_HOOK_ALL); run($cli->run(...)); diff --git a/composer.lock b/composer.lock index 557b61f36c..57d627d493 100644 --- a/composer.lock +++ b/composer.lock @@ -4771,16 +4771,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.40.17", + "version": "0.40.18", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de" + "reference": "38de4b9c58112d7e83eb75955994c8412a401093" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de", - "reference": "7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/38de4b9c58112d7e83eb75955994c8412a401093", + "reference": "38de4b9c58112d7e83eb75955994c8412a401093", "shasum": "" }, "require": { @@ -4816,9 +4816,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.40.17" + "source": "https://github.com/appwrite/sdk-generator/tree/0.40.18" }, - "time": "2025-05-16T15:10:54+00:00" + "time": "2025-05-21T14:14:47+00:00" }, { "name": "doctrine/annotations", diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index 888d291a75..ea0476fc33 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -79,16 +79,16 @@ abstract class ScheduleBase extends Action // start with "0" to load all active documents. $lastSyncUpdate = "0"; - $this->collectSchedules($pools, $dbForPlatform, $getProjectDB, $lastSyncUpdate); + $this->collectSchedules($dbForPlatform, $getProjectDB, $lastSyncUpdate); Console::success("Starting timers at " . DateTime::now()); /** * The timer synchronize $schedules copy with database collection. */ - Timer::tick(static::UPDATE_TIMER * 1000, function () use ($pools, $dbForPlatform, $getProjectDB, &$lastSyncUpdate) { + Timer::tick(static::UPDATE_TIMER * 1000, function () use ($dbForPlatform, $getProjectDB, &$lastSyncUpdate) { $time = DateTime::now(); Console::log("Sync tick: Running at $time"); - $this->collectSchedules($pools, $dbForPlatform, $getProjectDB, $lastSyncUpdate); + $this->collectSchedules($dbForPlatform, $getProjectDB, $lastSyncUpdate); }); while (true) { @@ -103,7 +103,7 @@ abstract class ScheduleBase extends Action } } - private function collectSchedules(Group $pools, Database $dbForPlatform, callable $getProjectDB, string &$lastSyncUpdate): void + private function collectSchedules(Database $dbForPlatform, callable $getProjectDB, string &$lastSyncUpdate): void { // If we haven't synced yet, load all active schedules $initialLoad = $lastSyncUpdate === "0"; @@ -115,7 +115,7 @@ abstract class ScheduleBase extends Action * @throws Exception * @var Document $schedule */ - $getSchedule = function (Document $schedule) use ($pools, $dbForPlatform, $getProjectDB): array { + $getSchedule = function (Document $schedule) use ($dbForPlatform, $getProjectDB): array { $project = $dbForPlatform->getDocument('projects', $schedule->getAttribute('projectId')); $resource = $getProjectDB($project)->getDocument( diff --git a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php index 19e068107a..7812b27832 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php @@ -76,7 +76,7 @@ class ScheduleFunctions extends ScheduleBase } foreach ($delayedExecutions as $delay => $schedules) { - \go(function () use ($delay, $schedules, $pools, $dbForPlatform) { + \go(function () use ($delay, $schedules, $dbForPlatform) { \sleep($delay); // in seconds foreach ($schedules as $delayConfig) { diff --git a/src/Appwrite/Platform/Tasks/ScheduleMessages.php b/src/Appwrite/Platform/Tasks/ScheduleMessages.php index 5e65f7a8a6..d23e3de575 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleMessages.php +++ b/src/Appwrite/Platform/Tasks/ScheduleMessages.php @@ -40,7 +40,7 @@ class ScheduleMessages extends ScheduleBase continue; } - \go(function () use ($schedule, $scheduledAt, $pools, $dbForPlatform) { + \go(function () use ($schedule, $scheduledAt, $dbForPlatform) { $queueForMessaging = new Messaging($this->publisher); $this->updateProjectAccess($schedule['project'], $dbForPlatform); From 83e62dc6e12630141df7dc5faa5001b6f7f1aa2e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= <matejbaco2000@gmail.com> Date: Wed, 21 May 2025 16:44:04 +0200 Subject: [PATCH 055/219] Fix double logs on failure --- .../Platform/Modules/Functions/Workers/Builds.php | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index cbbe6ee9c3..163623241c 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -1218,13 +1218,22 @@ class Builds extends Action $message .= "\n" . $error; } + // Combine with previous logs if deployment got past build process + $previousLogs = ''; + if (!empty($deployment->getAttribute('buildEndedAt', ''))) { + $previousLogs = $deployment->getAttribute('buildLogs', ''); + if (!empty($previousLogs)) { + $message = $previousLogs . "\n" . $message; + } + } + $endTime = DateTime::now(); $durationEnd = \microtime(true); $deployment->setAttribute('buildEndedAt', $endTime); $deployment->setAttribute('buildDuration', \intval(\ceil($durationEnd - $durationStart))); $deployment->setAttribute('status', 'failed'); - $deployment->setAttribute('buildLogs', $deployment->getAttribute('buildLogs', '') . "\n" . $message); + $deployment->setAttribute('buildLogs', $message); $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment); if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) { From c00d032c5a3fc6490bf0378eac3b313b9b77f419 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Wed, 21 May 2025 14:45:09 +0000 Subject: [PATCH 056/219] chore: update platforms --- app/config/platforms.php | 4 ++-- composer.json | 2 +- composer.lock | 18 ++++++++---------- 3 files changed, 11 insertions(+), 13 deletions(-) diff --git a/app/config/platforms.php b/app/config/platforms.php index 358edd0cf8..4ebb049633 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -11,7 +11,7 @@ return [ [ 'key' => 'web', 'name' => 'Web', - 'version' => '18.1.0', + 'version' => '18.1.1', 'url' => 'https://github.com/appwrite/sdk-for-web', 'package' => 'https://www.npmjs.com/package/appwrite', 'enabled' => true, @@ -134,7 +134,7 @@ return [ [ 'key' => 'react-native', 'name' => 'React Native', - 'version' => '0.9.1', + 'version' => '0.9.2', 'url' => 'https://github.com/appwrite/sdk-for-react-native', 'package' => 'https://npmjs.com/package/react-native-appwrite', 'enabled' => true, diff --git a/composer.json b/composer.json index 20b0317b3e..7e445cd36b 100644 --- a/composer.json +++ b/composer.json @@ -86,7 +86,7 @@ }, "require-dev": { "ext-fileinfo": "*", - "appwrite/sdk-generator": "dev-fix-devkeys-header", + "appwrite/sdk-generator": "0.40.*", "phpunit/phpunit": "9.*", "swoole/ide-helper": "5.1.2", "phpstan/phpstan": "1.8.*", diff --git a/composer.lock b/composer.lock index d762ace581..9ba4927742 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d4762811abd986e47a4d1259cfb1a0de", + "content-hash": "9f5de64d73e2ef73d796fa64f2baf232", "packages": [ { "name": "adhocore/jwt", @@ -4816,16 +4816,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "dev-fix-devkeys-header", + "version": "0.40.18", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "6a31bbe97dbfa972960fbc4d9ed51dfcee6deb07" + "reference": "38de4b9c58112d7e83eb75955994c8412a401093" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/6a31bbe97dbfa972960fbc4d9ed51dfcee6deb07", - "reference": "6a31bbe97dbfa972960fbc4d9ed51dfcee6deb07", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/38de4b9c58112d7e83eb75955994c8412a401093", + "reference": "38de4b9c58112d7e83eb75955994c8412a401093", "shasum": "" }, "require": { @@ -4861,9 +4861,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/fix-devkeys-header" + "source": "https://github.com/appwrite/sdk-generator/tree/0.40.18" }, - "time": "2025-05-21T13:05:09+00:00" + "time": "2025-05-21T14:14:47+00:00" }, { "name": "doctrine/annotations", @@ -8242,9 +8242,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "appwrite/sdk-generator": 20 - }, + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { From c5f7a724090fee6cf763d8cf2dbda82b2495ea4e Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Thu, 22 May 2025 06:03:35 +0000 Subject: [PATCH 057/219] chore: update flutter_web_auth_2 docs to match 4.x --- docs/sdks/flutter/GETTING_STARTED.md | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/docs/sdks/flutter/GETTING_STARTED.md b/docs/sdks/flutter/GETTING_STARTED.md index 8d239402b3..c3a1a8d33d 100644 --- a/docs/sdks/flutter/GETTING_STARTED.md +++ b/docs/sdks/flutter/GETTING_STARTED.md @@ -56,13 +56,25 @@ For web in order to capture the OAuth2 callback URL and send it to the applicati ```html <!DOCTYPE html> <title>Authentication complete -

Authentication is complete. If this does not happen automatically, please -close the window. +

Authentication is complete. If this does not happen automatically, please close the window.

``` From 86526fa1df15f1cb94981bdf656e64861d01b6bb Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Thu, 22 May 2025 06:11:28 +0000 Subject: [PATCH 058/219] chore: update changelog --- docs/sdks/flutter/CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/docs/sdks/flutter/CHANGELOG.md b/docs/sdks/flutter/CHANGELOG.md index be03d0fa2a..f707c645e6 100644 --- a/docs/sdks/flutter/CHANGELOG.md +++ b/docs/sdks/flutter/CHANGELOG.md @@ -1,6 +1,11 @@ # Change Log -## 16.0.1 +## 16.1.1 + +* Update `flutter_web_auth_2` dependency to version 4.1.0 +* Update `auth.html` example in README.md to align with `flutter_web_auth_2` documentation + +## 16.1.0 * Add `setDevKey` method to Client service * Add `upsertDocument` method to Databases service From d283c820daa4f42c9a83749d35125ae7dc70e9ce Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Thu, 22 May 2025 13:34:25 +0530 Subject: [PATCH 059/219] Only load error page for development mode --- app/views/general/error.phtml | 54 ++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 26 deletions(-) diff --git a/app/views/general/error.phtml b/app/views/general/error.phtml index c6457ce98f..de1c2b6541 100644 --- a/app/views/general/error.phtml +++ b/app/views/general/error.phtml @@ -479,35 +479,37 @@ switch ($type) { -
- -
Error trace
- $traceItem): ?> -
- -
file
-
print($traceItem['file']); ?>
- + +
+ +
Error trace
+ $traceItem): ?> +
+ +
file
+
print($traceItem['file']); ?>
+ - -
line
-
print($traceItem['line']); ?>
- + +
line
+
print($traceItem['line']); ?>
+ - -
function
-
print($traceItem['function']); ?>
- + +
function
+
print($traceItem['function']); ?>
+ - -
args
-
print(\var_export($traceItem['args'], true)); ?>
- -
- -
+ +
args
+
print(\var_export($traceItem['args'], true)); ?>
+ +
+ +
+
From 128dc1d946ab46bdb23127dcc94bc4f77a159139 Mon Sep 17 00:00:00 2001 From: Fabian Gruber Date: Thu, 22 May 2025 09:58:48 +0200 Subject: [PATCH 060/219] fix: send deploymentResourceType in rules verification --- app/controllers/api/proxy.php | 3 ++- src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php | 2 +- .../Platform/Modules/Proxy/Http/Rules/Function/Create.php | 2 +- .../Platform/Modules/Proxy/Http/Rules/Redirect/Create.php | 2 +- src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php | 2 +- src/Appwrite/Platform/Workers/Certificates.php | 2 +- 6 files changed, 7 insertions(+), 6 deletions(-) diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index e96f8bfb2c..8c30025551 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -260,7 +260,8 @@ App::patch('/v1/proxy/rules/:ruleId/verification') // Issue a TLS certificate when domain is verified $queueForCertificates ->setDomain(new Document([ - 'domain' => $rule->getAttribute('domain') + 'domain' => $rule->getAttribute('domain'), + 'domainType' => $rule->getAttribute('deploymentResourceType', $rule->getAttribute('type')), ])) ->trigger(); diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php index 8ae48ab345..e4d0d2899f 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php @@ -174,7 +174,7 @@ class Create extends Action $queueForCertificates ->setDomain(new Document([ 'domain' => $rule->getAttribute('domain'), - 'domainType' => 'api', + 'domainType' => $rule->getAttribute('deploymentResourceType', $rule->getAttribute('type')), ])) ->trigger(); } diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php index 15d58c7b29..6c5a87a68d 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php @@ -192,7 +192,7 @@ class Create extends Action $queueForCertificates ->setDomain(new Document([ 'domain' => $rule->getAttribute('domain'), - 'domainType' => 'function', + 'domainType' => $rule->getAttribute('deploymentResourceType', $rule->getAttribute('type')), ])) ->trigger(); } diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php index 0ff41e5ac2..d0c9dbbbe3 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php @@ -180,7 +180,7 @@ class Create extends Action $queueForCertificates ->setDomain(new Document([ 'domain' => $rule->getAttribute('domain'), - 'domainType' => 'redirect', + 'domainType' => $rule->getAttribute('deploymentResourceType', $rule->getAttribute('type')), ])) ->trigger(); } diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php index f5f6628d68..894c954a32 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php @@ -192,7 +192,7 @@ class Create extends Action $queueForCertificates ->setDomain(new Document([ 'domain' => $rule->getAttribute('domain'), - 'domainType' => 'site', + 'domainType' => $rule->getAttribute('deploymentResourceType', $rule->getAttribute('type')), ])) ->trigger(); } diff --git a/src/Appwrite/Platform/Workers/Certificates.php b/src/Appwrite/Platform/Workers/Certificates.php index 4e83497cdd..0dce51cb52 100644 --- a/src/Appwrite/Platform/Workers/Certificates.php +++ b/src/Appwrite/Platform/Workers/Certificates.php @@ -96,7 +96,7 @@ class Certificates extends Action $log->addTag('domain', $domain->get()); - $domainType = $payload['domainType'] ?? null; + $domainType = $document->getAttribute('domainType'); $this->execute($domain, $domainType, $dbForPlatform, $queueForMails, $queueForEvents, $queueForWebhooks, $queueForFunctions, $queueForRealtime, $log, $certificates, $skipRenewCheck, $plan); } From 67a5192705eefc330e096c2d16024d613d10520e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 22 May 2025 10:13:12 +0200 Subject: [PATCH 061/219] Fix CNAME validation --- app/controllers/api/proxy.php | 39 +++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index e96f8bfb2c..f07d7755be 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -214,11 +214,42 @@ App::patch('/v1/proxy/rules/:ruleId/verification') throw new Exception(Exception::RULE_NOT_FOUND); } - $validators = []; - $targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', '')); - if ($targetCNAME->isKnown() && !$targetCNAME->isTest()) { - $validators[] = new DNS($targetCNAME->get(), DNS::RECORD_CNAME); + $targetCNAME = null; + switch ($rule->getAttribute('type', '')) { + case 'api': + // For example: fra.cloud.appwrite.io + $targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_TARGET_CNAME', '')); + break; + case 'redirect': + // For example: appwrite.network + $targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_SITES', '')); + break; + case 'deployment': + switch ($rule->getAttribute('deploymentResourceType', '')) { + case 'function': + // For example: fra.appwrite.run + $targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_FUNCTIONS', '')); + break; + case 'site': + // For example: appwrite.network + $targetCNAME = new Domain(System::getEnv('_APP_DOMAIN_SITES', '')); + break; + default: + break; + } + // no break + default: + break; } + + $validators = []; + + if (!is_null($targetCNAME)) { + if ($targetCNAME->isKnown() && !$targetCNAME->isTest()) { + $validators[] = new DNS($targetCNAME->get(), DNS::RECORD_CNAME); + } + } + if ((new IP(IP::V4))->isValid(System::getEnv('_APP_DOMAIN_TARGET_A', ''))) { $validators[] = new DNS(System::getEnv('_APP_DOMAIN_TARGET_A', ''), DNS::RECORD_A); } From b727b8c100b67965c6bbdcae7bc26e03a9fa241d Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Thu, 22 May 2025 18:01:34 +0530 Subject: [PATCH 062/219] Add configurable deployment and build size --- app/worker.php | 4 ++++ .../Functions/Http/Deployments/Create.php | 12 ++++++++-- .../Modules/Functions/Workers/Builds.php | 23 +++++++++++++++---- .../Modules/Sites/Http/Deployments/Create.php | 12 ++++++++-- 4 files changed, 42 insertions(+), 9 deletions(-) diff --git a/app/worker.php b/app/worker.php index 79cfffc8bb..1277162bfa 100644 --- a/app/worker.php +++ b/app/worker.php @@ -240,6 +240,10 @@ Server::setResource('timelimit', function (\Redis $redis) { Server::setResource('log', fn () => new Log()); +Server::setResource('plan', function (array $plan = []) { + return []; +}); + Server::setResource('publisher', function (Group $pools) { return new BrokerPool(publisher: $pools->get('publisher')); }, ['pools']); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php index 54894f2caa..cda6dc38bf 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php @@ -86,6 +86,7 @@ class Create extends Action ->inject('deviceForFunctions') ->inject('deviceForLocal') ->inject('queueForBuilds') + ->inject('plan') ->callback([$this, 'action']); } @@ -102,7 +103,8 @@ class Create extends Action Document $project, Device $deviceForFunctions, Device $deviceForLocal, - Build $queueForBuilds + Build $queueForBuilds, + array $plan ) { $activate = \strval($activate) === 'true' || \strval($activate) === '1'; @@ -135,8 +137,14 @@ class Create extends Action throw new Exception(Exception::STORAGE_FILE_EMPTY, 'No file sent'); } + $functionSizeLimit = (int) System::getEnv('_APP_COMPUTE_SIZE_LIMIT', '30000000'); + + if (isset($plan['deploymentSize'])) { + $functionSizeLimit = $plan['deploymentSize'] * 1000 * 1000; + } + $fileExt = new FileExt([FileExt::TYPE_GZIP]); - $fileSizeValidator = new FileSize(System::getEnv('_APP_COMPUTE_SIZE_LIMIT', '30000000')); + $fileSizeValidator = new FileSize($functionSizeLimit); $upload = new Upload(); // Make sure we handle a single file and multiple files the same way diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 163623241c..6ff2161c1a 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -73,6 +73,7 @@ class Builds extends Action ->inject('deviceForFiles') ->inject('log') ->inject('executor') + ->inject('plan') ->callback([$this, 'action']); } @@ -92,6 +93,7 @@ class Builds extends Action * @param Device $deviceForFiles * @param Log $log * @param Executor $executor + * @param array $plan * @return void * @throws \Utopia\Database\Exception */ @@ -111,7 +113,8 @@ class Builds extends Action callable $isResourceBlocked, Device $deviceForFiles, Log $log, - Executor $executor + Executor $executor, + array $plan ): void { $payload = $message->getPayload() ?? []; @@ -150,7 +153,8 @@ class Builds extends Action $template, $isResourceBlocked, $log, - $executor + $executor, + $plan ); break; @@ -177,6 +181,7 @@ class Builds extends Action * @param Document $template * @param Log $log * @param Executor $executor + * @param array $plan * @return void * @throws \Utopia\Database\Exception * @@ -200,7 +205,8 @@ class Builds extends Action Document $template, callable $isResourceBlocked, Log $log, - Executor $executor + Executor $executor, + array $plan ): void { $resourceKey = match ($resource->getCollection()) { 'functions' => 'functionId', @@ -476,8 +482,12 @@ class Builds extends Action $directorySize = $localDevice->getDirectorySize($tmpDirectory); $sizeLimit = (int)System::getEnv('_APP_COMPUTE_SIZE_LIMIT', '30000000'); + if (isset($plan['deploymentSize'])) { + $sizeLimit = (int) $plan['deploymentSize'] * 1000 * 1000; + } + if ($directorySize > $sizeLimit) { - throw new \Exception('Repository directory size should be less than ' . number_format($sizeLimit / 1048576, 2) . ' MBs.'); + throw new \Exception('Repository directory size should be less than ' . number_format($sizeLimit / (1000 * 1000), 2) . ' MBs.'); } Console::execute('find ' . \escapeshellarg($tmpDirectory) . ' -type d -name ".git" -exec rm -rf {} +', '', $stdout, $stderr); @@ -803,8 +813,11 @@ class Builds extends Action $durationEnd = \microtime(true); $buildSizeLimit = (int)System::getEnv('_APP_COMPUTE_BUILD_SIZE_LIMIT', '2000000000'); + if (isset($plan['buildSize'])) { + $buildSizeLimit = $plan['buildSize'] * 1000 * 1000; + } if ($response['size'] > $buildSizeLimit) { - throw new \Exception('Build size should be less than ' . number_format($buildSizeLimit / 1048576, 2) . ' MBs.'); + throw new \Exception('Build size should be less than ' . number_format($buildSizeLimit / (1000 * 1000), 2) . ' MBs.'); } /** Update the build document */ diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php index 7400d86e74..afa1dba7d8 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php @@ -85,6 +85,7 @@ class Create extends Action ->inject('deviceForSites') ->inject('deviceForLocal') ->inject('queueForBuilds') + ->inject('plan') ->callback([$this, 'action']); } @@ -103,7 +104,8 @@ class Create extends Action Event $queueForEvents, Device $deviceForSites, Device $deviceForLocal, - Build $queueForBuilds + Build $queueForBuilds, + array $plan ) { $activate = \strval($activate) === 'true' || \strval($activate) === '1'; @@ -136,8 +138,14 @@ class Create extends Action throw new Exception(Exception::STORAGE_FILE_EMPTY, 'No file sent'); } + $siteSizeLimit = (int) System::getEnv('_APP_COMPUTE_SIZE_LIMIT', '30000000'); + + if (isset($plan['deploymentSize'])) { + $siteSizeLimit = $plan['deploymentSize'] * 1000 * 1000; + } + $fileExt = new FileExt([FileExt::TYPE_GZIP]); - $fileSizeValidator = new FileSize(System::getEnv('_APP_COMPUTE_SIZE_LIMIT', '30000000')); + $fileSizeValidator = new FileSize($siteSizeLimit); $upload = new Upload(); // Make sure we handle a single file and multiple files the same way From d2d9032ede2395e0cd79f5272901579789378b38 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 23 May 2025 00:49:26 +1200 Subject: [PATCH 063/219] Fix bucket not included in path --- app/init/resources.php | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/app/init/resources.php b/app/init/resources.php index 910e8369db..14961ea44b 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -487,10 +487,9 @@ App::setResource('timelimit', function (\Redis $redis) { }; }, ['redis']); -App::setResource('deviceForLocal', function (Telemetry $telemetry) { +App::setResource('deviceForLocal', function () { return new Local(); -}, ['telemetry']); - +}); App::setResource('deviceForFiles', function ($project) { return getDevice(APP_STORAGE_UPLOADS . '/app-' . $project->getId()); }, ['project']); @@ -534,7 +533,8 @@ function getDevice(string $root, string $connection = ''): Device switch ($device) { case Storage::DEVICE_S3: if (!empty($url)) { - return new S3($root, $accessKey, $accessSecret, $url, $region, $acl); + $bucketRoot = (!empty($bucket) ? $bucket . '/' : '') . \ltrim($root, '/'); + return new S3($bucketRoot, $accessKey, $accessSecret, $url, $region, $acl); } else { return new AWS($root, $accessKey, $accessSecret, $bucket, $region, $acl); } @@ -566,7 +566,8 @@ function getDevice(string $root, string $connection = ''): Device $s3Acl = 'private'; $s3EndpointUrl = System::getEnv('_APP_STORAGE_S3_ENDPOINT', ''); if (!empty($s3EndpointUrl)) { - return new S3($root, $s3AccessKey, $s3SecretKey, $s3EndpointUrl, $s3Region, $s3Acl); + $bucketRoot = (!empty($s3Bucket) ? $s3Bucket . '/' : '') . \ltrim($root, '/'); + return new S3($bucketRoot, $s3AccessKey, $s3SecretKey, $s3EndpointUrl, $s3Region, $s3Acl); } else { return new AWS($root, $s3AccessKey, $s3SecretKey, $s3Bucket, $s3Region, $s3Acl); } From bd01d12db57f64ab4faf18be3ada1c8758ca618b Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 23 May 2025 00:51:31 +1200 Subject: [PATCH 064/219] Format --- app/init/resources.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/init/resources.php b/app/init/resources.php index 14961ea44b..c75df2a362 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -52,7 +52,6 @@ use Utopia\Storage\Device\S3; use Utopia\Storage\Device\Wasabi; use Utopia\Storage\Storage; use Utopia\System\System; -use Utopia\Telemetry\Adapter as Telemetry; use Utopia\Telemetry\Adapter\None as NoTelemetry; use Utopia\Validator\Hostname; use Utopia\Validator\WhiteList; From 9321f585f5d67e23944a3c979fd27629957e3439 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 22 May 2025 15:22:40 +0200 Subject: [PATCH 065/219] Update app/worker.php --- app/worker.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/app/worker.php b/app/worker.php index 1277162bfa..597e8a9943 100644 --- a/app/worker.php +++ b/app/worker.php @@ -240,9 +240,6 @@ Server::setResource('timelimit', function (\Redis $redis) { Server::setResource('log', fn () => new Log()); -Server::setResource('plan', function (array $plan = []) { - return []; -}); Server::setResource('publisher', function (Group $pools) { return new BrokerPool(publisher: $pools->get('publisher')); From 71e34464988503e4613ee1f8793956f118ad1a4b Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 23 May 2025 02:55:29 +1200 Subject: [PATCH 066/219] Change internal ID to sequence --- CHANGES.md | 2 +- CONTRIBUTING.md | 10 +- app/cli.php | 12 +- app/config/console.php | 2 +- app/controllers/api/account.php | 70 ++--- app/controllers/api/avatars.php | 12 +- app/controllers/api/databases.php | 260 +++++++++--------- app/controllers/api/messaging.php | 28 +- app/controllers/api/migrations.php | 2 +- app/controllers/api/project.php | 18 +- app/controllers/api/projects.php | 46 ++-- app/controllers/api/proxy.php | 8 +- app/controllers/api/storage.php | 80 +++--- app/controllers/api/teams.php | 24 +- app/controllers/api/users.php | 30 +- app/controllers/api/vcs.php | 32 +-- app/controllers/general.php | 20 +- app/controllers/mock.php | 4 +- app/controllers/shared/api.php | 8 +- app/http.php | 4 +- app/init/database/filters.php | 32 +-- app/init/resources.php | 22 +- app/realtime.php | 10 +- app/worker.php | 16 +- src/Appwrite/Deletes/Targets.php | 4 +- src/Appwrite/Event/Event.php | 2 +- src/Appwrite/Migration/Migration.php | 12 +- src/Appwrite/Migration/Version/V15.php | 30 +- src/Appwrite/Migration/Version/V16.php | 2 +- src/Appwrite/Migration/Version/V17.php | 4 +- src/Appwrite/Migration/Version/V18.php | 16 +- src/Appwrite/Migration/Version/V19.php | 24 +- src/Appwrite/Migration/Version/V20.php | 24 +- src/Appwrite/Migration/Version/V21.php | 8 +- src/Appwrite/Migration/Version/V22.php | 8 +- .../Platform/Modules/Compute/Base.php | 20 +- .../Functions/Http/Deployments/Create.php | 8 +- .../Functions/Http/Deployments/Delete.php | 4 +- .../Http/Deployments/Duplicate/Create.php | 6 +- .../Http/Deployments/Status/Update.php | 2 +- .../Http/Deployments/Template/Create.php | 4 +- .../Functions/Http/Deployments/XList.php | 2 +- .../Functions/Http/Executions/Create.php | 14 +- .../Functions/Http/Executions/Delete.php | 2 +- .../Modules/Functions/Http/Executions/Get.php | 2 +- .../Functions/Http/Executions/XList.php | 2 +- .../Functions/Http/Functions/Create.php | 26 +- .../Http/Functions/Deployment/Update.php | 6 +- .../Functions/Http/Functions/Update.php | 14 +- .../Modules/Functions/Http/Usage/Get.php | 22 +- .../Functions/Http/Variables/Create.php | 2 +- .../Functions/Http/Variables/Delete.php | 2 +- .../Modules/Functions/Http/Variables/Get.php | 2 +- .../Functions/Http/Variables/Update.php | 2 +- .../Modules/Functions/Workers/Builds.php | 74 ++--- .../Modules/Projects/Http/DevKeys/Create.php | 2 +- .../Modules/Projects/Http/DevKeys/Delete.php | 2 +- .../Modules/Projects/Http/DevKeys/Get.php | 2 +- .../Modules/Projects/Http/DevKeys/Update.php | 2 +- .../Modules/Projects/Http/DevKeys/XList.php | 2 +- .../Modules/Proxy/Http/Rules/API/Create.php | 2 +- .../Proxy/Http/Rules/Function/Create.php | 6 +- .../Proxy/Http/Rules/Redirect/Create.php | 2 +- .../Modules/Proxy/Http/Rules/Site/Create.php | 6 +- .../Modules/Sites/Http/Deployments/Create.php | 16 +- .../Modules/Sites/Http/Deployments/Delete.php | 4 +- .../Http/Deployments/Duplicate/Create.php | 12 +- .../Sites/Http/Deployments/Status/Update.php | 2 +- .../Http/Deployments/Template/Create.php | 10 +- .../Modules/Sites/Http/Deployments/XList.php | 2 +- .../Modules/Sites/Http/Logs/Delete.php | 2 +- .../Platform/Modules/Sites/Http/Logs/Get.php | 2 +- .../Modules/Sites/Http/Logs/XList.php | 2 +- .../Modules/Sites/Http/Sites/Create.php | 10 +- .../Sites/Http/Sites/Deployment/Update.php | 6 +- .../Modules/Sites/Http/Sites/Update.php | 14 +- .../Platform/Modules/Sites/Http/Usage/Get.php | 28 +- .../Modules/Sites/Http/Variables/Create.php | 2 +- .../Modules/Sites/Http/Variables/Delete.php | 2 +- .../Modules/Sites/Http/Variables/Get.php | 2 +- .../Modules/Sites/Http/Variables/Update.php | 2 +- .../Http/Tokens/Buckets/Files/Action.php | 4 +- .../Http/Tokens/Buckets/Files/Create.php | 2 +- .../Http/Tokens/Buckets/Files/XList.php | 2 +- src/Appwrite/Platform/Tasks/ScheduleBase.php | 10 +- .../Platform/Tasks/ScheduleExecutions.php | 4 +- .../Platform/Tasks/ScheduleMessages.php | 2 +- .../Platform/Tasks/StatsResources.php | 2 +- src/Appwrite/Platform/Workers/Audits.php | 14 +- .../Platform/Workers/Certificates.php | 2 +- src/Appwrite/Platform/Workers/Databases.php | 44 +-- src/Appwrite/Platform/Workers/Deletes.php | 42 +-- src/Appwrite/Platform/Workers/Functions.php | 12 +- src/Appwrite/Platform/Workers/Messaging.php | 4 +- src/Appwrite/Platform/Workers/Migrations.php | 2 +- .../Platform/Workers/StatsResources.php | 70 ++--- src/Appwrite/Platform/Workers/StatsUsage.php | 46 ++-- .../Platform/Workers/StatsUsageDump.php | 4 +- src/Appwrite/Platform/Workers/Webhooks.php | 4 +- .../Database/Validator/Queries/Base.php | 6 +- .../Utopia/Response/Model/Document.php | 2 +- .../e2e/Services/Databases/DatabasesBase.php | 12 +- 102 files changed, 768 insertions(+), 768 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index bc903e4b31..fa4db4acc5 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -607,7 +607,7 @@ ### Fixes * Fix database exception wrapping by @abnegate in https://github.com/appwrite/appwrite/pull/7787 * Fix exception wrap order by @abnegate in https://github.com/appwrite/appwrite/pull/7818 -* Fix membership query to use internalId by @lohanidamodar in https://github.com/appwrite/appwrite/pull/7834 +* Fix membership query to use sequence by @lohanidamodar in https://github.com/appwrite/appwrite/pull/7834 * Fix vcs silent mode by @vermakhushboo in https://github.com/appwrite/appwrite/pull/7683 * Fix function domain permissions by @stnguyen90 in https://github.com/appwrite/appwrite/pull/7852 * Fix tests required for Cloud by @lohanidamodar in https://github.com/appwrite/appwrite/pull/7777 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 7746ef99af..277a509447 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -415,8 +415,8 @@ In addition, you will also need to add some logic to the `reduce()` method of th ```php case $document->getCollection() === 'buckets': - $files = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES))); - $storage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE))); + $files = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getSequence(), METRIC_BUCKET_ID_FILES))); + $storage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getSequence(), METRIC_BUCKET_ID_FILES_STORAGE))); if (!empty($files['value'])) { $metrics[] = [ @@ -463,9 +463,9 @@ $queueForStatsUsage ->addMetric(METRIC_BUILDS, 1) ->addMetric(METRIC_BUILDS_STORAGE, $build->getAttribute('size', 0)) ->addMetric(METRIC_BUILDS_COMPUTE, (int)$build->getAttribute('duration', 0) * 1000) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS), 1) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE), $build->getAttribute('size', 0)) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int)$build->getAttribute('duration', 0) * 1000) + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS), 1) + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_STORAGE), $build->getAttribute('size', 0)) + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int)$build->getAttribute('duration', 0) * 1000) ->setProject($project) ->trigger(); ``` diff --git a/app/cli.php b/app/cli.php index 9517347420..224f150a58 100644 --- a/app/cli.php +++ b/app/cli.php @@ -125,13 +125,13 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getInternalId()) + ->setTenant($project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); + ->setNamespace('_' . $project->getSequence()); } return $database; @@ -145,13 +145,13 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getInternalId()) + ->setTenant($project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); + ->setNamespace('_' . $project->getSequence()); } $database @@ -167,7 +167,7 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) { return function (?Document $project = null) use ($pools, $cache, $database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { - $database->setTenant($project->getInternalId()); + $database->setTenant($project->getSequence()); return $database; } @@ -182,7 +182,7 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) { // set tenant if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') { - $database->setTenant($project->getInternalId()); + $database->setTenant($project->getSequence()); } return $database; diff --git a/app/config/console.php b/app/config/console.php index e37c9b7836..1de3a99370 100644 --- a/app/config/console.php +++ b/app/config/console.php @@ -11,7 +11,7 @@ use Utopia\System\System; $console = [ '$id' => ID::custom('console'), - '$internalId' => ID::custom('console'), + '$sequence' => ID::custom('console'), 'name' => 'Appwrite', '$collection' => ID::custom('projects'), 'description' => 'Appwrite core engine', diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index ac01476314..0c53423325 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -190,7 +190,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res [ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'provider' => Auth::getSessionProviderByTokenType($verifiedToken->getAttribute('type')), 'secret' => Auth::hash($sessionSecret), // One way hash encryption to protect DB leak 'userAgent' => $request->getUserAgent('UNKNOWN'), @@ -387,7 +387,7 @@ App::post('/v1/account') 'search' => implode(' ', [$userId, $email, $name]), 'accessedAt' => DateTime::now(), ]); - $user->removeAttribute('$internalId'); + $user->removeAttribute('$sequence'); $user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); try { $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ @@ -397,7 +397,7 @@ App::post('/v1/account') Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'providerType' => MESSAGE_TYPE_EMAIL, 'identifier' => $email, ]))); @@ -907,7 +907,7 @@ App::post('/v1/account/sessions/email') [ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'provider' => Auth::SESSION_PROVIDER_EMAIL, 'providerUid' => $email, 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak @@ -1056,7 +1056,7 @@ App::post('/v1/account/sessions/anonymous') 'search' => $userId, 'accessedAt' => DateTime::now(), ]); - $user->removeAttribute('$internalId'); + $user->removeAttribute('$sequence'); Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); // Create session token @@ -1069,7 +1069,7 @@ App::post('/v1/account/sessions/anonymous') [ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'provider' => Auth::SESSION_PROVIDER_ANONYMOUS, 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'userAgent' => $request->getUserAgent('UNKNOWN'), @@ -1440,7 +1440,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), - Query::notEqual('userInternalId', $user->getInternalId()), + Query::notEqual('userInternalId', $user->getSequence()), ]); if (!$identityWithMatchingEmail->isEmpty()) { $failureRedirect(Exception::USER_ALREADY_EXISTS); @@ -1554,7 +1554,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'search' => implode(' ', [$userId, $email, $name]), 'accessedAt' => DateTime::now(), ]); - $user->removeAttribute('$internalId'); + $user->removeAttribute('$sequence'); $userDoc = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); $dbForProject->createDocument('targets', new Document([ '$permissions' => [ @@ -1563,7 +1563,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') Permission::delete(Role::user($user->getId())), ], 'userId' => $userDoc->getId(), - 'userInternalId' => $userDoc->getInternalId(), + 'userInternalId' => $userDoc->getSequence(), 'providerType' => MESSAGE_TYPE_EMAIL, 'identifier' => $email, ])); @@ -1582,7 +1582,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') } $identity = $dbForProject->findOne('identities', [ - Query::equal('userInternalId', [$user->getInternalId()]), + Query::equal('userInternalId', [$user->getSequence()]), Query::equal('provider', [$provider]), Query::equal('providerUid', [$oauth2ID]), ]); @@ -1592,7 +1592,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $identitiesWithMatchingEmail = $dbForProject->find('identities', [ Query::equal('providerEmail', [$email]), - Query::notEqual('userInternalId', $user->getInternalId()), + Query::notEqual('userInternalId', $user->getSequence()), ]); if (!empty($identitiesWithMatchingEmail)) { $failureRedirect(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */ @@ -1605,7 +1605,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') Permission::update(Role::user($userId)), Permission::delete(Role::user($userId)), ], - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'userId' => $userId, 'provider' => $provider, 'providerUid' => $oauth2ID, @@ -1648,7 +1648,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $token = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'type' => Auth::TOKEN_TYPE_OAUTH2, 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'expire' => $expire, @@ -1683,7 +1683,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $session = new Document(array_merge([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'provider' => $provider, 'providerUid' => $oauth2ID, 'providerAccessToken' => $accessToken, @@ -1736,7 +1736,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $target ->setAttribute('sessionId', $session->getId()) - ->setAttribute('sessionInternalId', $session->getInternalId()); + ->setAttribute('sessionInternalId', $session->getSequence()); $dbForProject->updateDocument('targets', $target->getId(), $target); } @@ -1931,7 +1931,7 @@ App::post('/v1/account/tokens/magic-url') 'accessedAt' => DateTime::now(), ]); - $user->removeAttribute('$internalId'); + $user->removeAttribute('$sequence'); Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); } @@ -1941,7 +1941,7 @@ App::post('/v1/account/tokens/magic-url') $token = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'type' => Auth::TOKEN_TYPE_MAGIC_URL, 'secret' => Auth::hash($tokenSecret), // One way hash encryption to protect DB leak 'expire' => $expire, @@ -2168,7 +2168,7 @@ App::post('/v1/account/tokens/email') 'accessedAt' => DateTime::now(), ]); - $user->removeAttribute('$internalId'); + $user->removeAttribute('$sequence'); Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); } @@ -2178,7 +2178,7 @@ App::post('/v1/account/tokens/email') $token = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'type' => Auth::TOKEN_TYPE_EMAIL, 'secret' => Auth::hash($tokenSecret), // One way hash encryption to protect DB leak 'expire' => $expire, @@ -2460,7 +2460,7 @@ App::post('/v1/account/tokens/phone') 'accessedAt' => DateTime::now(), ]); - $user->removeAttribute('$internalId'); + $user->removeAttribute('$sequence'); Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); try { $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ @@ -2470,7 +2470,7 @@ App::post('/v1/account/tokens/phone') Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'providerType' => MESSAGE_TYPE_SMS, 'identifier' => $phone, ]))); @@ -2501,7 +2501,7 @@ App::post('/v1/account/tokens/phone') $token = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'type' => Auth::TOKEN_TYPE_PHONE, 'secret' => Auth::hash($secret), 'expire' => $expire, @@ -2703,7 +2703,7 @@ App::get('/v1/account/logs') $audit = new EventAudit($dbForProject); - $logs = $audit->getLogsByUser($user->getInternalId(), $queries); + $logs = $audit->getLogsByUser($user->getSequence(), $queries); $output = []; @@ -2732,7 +2732,7 @@ App::get('/v1/account/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByUser($user->getInternalId(), $queries), + 'total' => $audit->countLogsByUser($user->getSequence(), $queries), 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -2900,7 +2900,7 @@ App::patch('/v1/account/email') // Makes sure this email is not already used in another identity $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), - Query::notEqual('userInternalId', $user->getInternalId()), + Query::notEqual('userInternalId', $user->getSequence()), ]); if (!$identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */ @@ -3183,7 +3183,7 @@ App::post('/v1/account/recovery') $recovery = new Document([ '$id' => ID::unique(), 'userId' => $profile->getId(), - 'userInternalId' => $profile->getInternalId(), + 'userInternalId' => $profile->getSequence(), 'type' => Auth::TOKEN_TYPE_RECOVERY, 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'expire' => $expire, @@ -3438,7 +3438,7 @@ App::post('/v1/account/verification') $verification = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'type' => Auth::TOKEN_TYPE_VERIFICATION, 'secret' => Auth::hash($verificationSecret), // One way hash encryption to protect DB leak 'expire' => $expire, @@ -3685,7 +3685,7 @@ App::post('/v1/account/verification/phone') $verification = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'type' => Auth::TOKEN_TYPE_PHONE, 'secret' => Auth::hash($secret), 'expire' => $expire, @@ -3979,7 +3979,7 @@ App::post('/v1/account/mfa/authenticators/:type') $authenticator = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'type' => Type::TOTP, 'verified' => false, 'data' => [ @@ -4292,7 +4292,7 @@ App::post('/v1/account/mfa/challenge') $code = Auth::codeGenerator(); $challenge = new Document([ 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'type' => $factor, 'token' => Auth::tokenGenerator(), 'code' => $code, @@ -4621,12 +4621,12 @@ App::post('/v1/account/targets/push') Permission::delete(Role::user($user->getId())), ], 'providerId' => !empty($providerId) ? $providerId : null, - 'providerInternalId' => !empty($providerId) ? $provider->getInternalId() : null, + 'providerInternalId' => !empty($providerId) ? $provider->getSequence() : null, 'providerType' => MESSAGE_TYPE_PUSH, 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'sessionId' => $session->getId(), - 'sessionInternalId' => $session->getInternalId(), + 'sessionInternalId' => $session->getSequence(), 'identifier' => $identifier, 'name' => "{$device['deviceBrand']} {$device['deviceModel']}" ])); @@ -4745,7 +4745,7 @@ App::delete('/v1/account/targets/:targetId/push') throw new Exception(Exception::USER_TARGET_NOT_FOUND); } - if ($user->getInternalId() !== $target->getAttribute('userInternalId')) { + if ($user->getSequence() !== $target->getAttribute('userInternalId')) { throw new Exception(Exception::USER_TARGET_NOT_FOUND); } @@ -4794,7 +4794,7 @@ App::get('/v1/account/identities') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $queries[] = Query::equal('userInternalId', [$user->getInternalId()]); + $queries[] = Query::equal('userInternalId', [$user->getSequence()]); /** * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index 779a188089..3a7b4aa582 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -669,7 +669,7 @@ App::get('/v1/cards/cloud') } } - $isPlatinum = $user->getInternalId() % 100 === 0; + $isPlatinum = $user->getSequence() % 100 === 0; } else { $name = $mock === 'normal-long' ? 'Sir First Walter O\'Brian Junior' : 'Walter O\'Brian'; $createdAt = new \DateTime('now'); @@ -859,7 +859,7 @@ App::get('/v1/cards/cloud-back') $isEmployee = \array_key_exists($email, $employees); $isGolden = $isEmployee || $isHero || $isContributor; - $isPlatinum = $user->getInternalId() % 100 === 0; + $isPlatinum = $user->getSequence() % 100 === 0; } else { $userId = '63e0bcf3c3eb803ba530'; @@ -926,9 +926,9 @@ App::get('/v1/cards/cloud-og') } if (!$mock) { - $internalId = $user->getInternalId(); - $bgVariation = $internalId % 3 === 0 ? '1' : ($internalId % 3 === 1 ? '2' : '3'); - $cardVariation = $internalId % 3 === 0 ? '1' : ($internalId % 3 === 1 ? '2' : '3'); + $sequence = $user->getSequence(); + $bgVariation = $sequence % 3 === 0 ? '1' : ($sequence % 3 === 1 ? '2' : '3'); + $cardVariation = $sequence % 3 === 0 ? '1' : ($sequence % 3 === 1 ? '2' : '3'); $name = $user->getAttribute('name', 'Anonymous'); $email = $user->getAttribute('email', ''); @@ -958,7 +958,7 @@ App::get('/v1/cards/cloud-og') } } - $isPlatinum = $user->getInternalId() % 100 === 0; + $isPlatinum = $user->getSequence() % 100 === 0; } else { $bgVariation = \str_ends_with($mock, '-bg2') ? '2' : (\str_ends_with($mock, '-bg3') ? '3' : '1'); $cardVariation = \str_ends_with($mock, '-right') ? '2' : (\str_ends_with($mock, '-middle') ? '3' : '1'); diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 352503b730..9ea5b2a197 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -107,7 +107,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -130,7 +130,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att if ($type === Database::VAR_RELATIONSHIP) { $options['side'] = Database::RELATION_SIDE_PARENT; - $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection'] ?? ''); + $relatedCollection = $dbForProject->getDocument('database_' . $database->getSequence(), $options['relatedCollection'] ?? ''); if ($relatedCollection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND, 'The related collection was not found.'); } @@ -138,11 +138,11 @@ function createAttribute(string $databaseId, string $collectionId, Document $att try { $attribute = new Document([ - '$id' => ID::custom($database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key), + '$id' => ID::custom($database->getSequence() . '_' . $collection->getSequence() . '_' . $key), 'key' => $key, - 'databaseInternalId' => $database->getInternalId(), + 'databaseInternalId' => $database->getSequence(), 'databaseId' => $database->getId(), - 'collectionInternalId' => $collection->getInternalId(), + 'collectionInternalId' => $collection->getSequence(), 'collectionId' => $collectionId, 'type' => $type, 'status' => 'processing', // processing, available, failed, deleting, stuck @@ -164,13 +164,13 @@ function createAttribute(string $databaseId, string $collectionId, Document $att } catch (LimitException) { throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); } catch (\Throwable $e) { - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); throw $e; } - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { $twoWayKey = $options['twoWayKey']; @@ -181,11 +181,11 @@ function createAttribute(string $databaseId, string $collectionId, Document $att try { try { $twoWayAttribute = new Document([ - '$id' => ID::custom($database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $twoWayKey), + '$id' => ID::custom($database->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $twoWayKey), 'key' => $twoWayKey, - 'databaseInternalId' => $database->getInternalId(), + 'databaseInternalId' => $database->getSequence(), 'databaseId' => $database->getId(), - 'collectionInternalId' => $relatedCollection->getInternalId(), + 'collectionInternalId' => $relatedCollection->getSequence(), 'collectionId' => $relatedCollection->getId(), 'type' => $type, 'status' => 'processing', // processing, available, failed, deleting, stuck @@ -213,13 +213,13 @@ function createAttribute(string $databaseId, string $collectionId, Document $att $dbForProject->deleteDocument('attributes', $attribute->getId()); throw $e; } finally { - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); } // If operation succeeded, purge the cache for the related collection too - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $relatedCollection->getId()); + $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence()); } $queueForDatabase @@ -262,12 +262,12 @@ function updateAttribute( throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $attribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $collection->getSequence() . '_' . $key); if ($attribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); } @@ -292,7 +292,7 @@ function updateAttribute( throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for array attributes'); } - $collectionId = 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(); + $collectionId = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(); $attribute ->setAttribute('default', $default) @@ -378,8 +378,8 @@ function updateAttribute( } if ($primaryDocumentOptions['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $primaryDocumentOptions['relatedCollection']); - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey']); + $relatedCollection = $dbForProject->getDocument('database_' . $database->getSequence(), $primaryDocumentOptions['relatedCollection']); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $primaryDocumentOptions['twoWayKey']); if (!empty($newKey) && $newKey !== $key) { $options['twoWayKey'] = $newKey; @@ -389,8 +389,8 @@ function updateAttribute( $relatedAttribute->setAttribute('options', $relatedOptions); - $dbForProject->updateDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey'], $relatedAttribute); - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); + $dbForProject->updateDocument('attributes', $database->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $primaryDocumentOptions['twoWayKey'], $relatedAttribute); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $relatedCollection->getId()); } } else { try { @@ -418,7 +418,7 @@ function updateAttribute( $originalUid = $attribute->getId(); $attribute - ->setAttribute('$id', ID::custom($database->getInternalId() . '_' . $collection->getInternalId() . '_' . $newKey)) + ->setAttribute('$id', ID::custom($database->getSequence() . '_' . $collection->getSequence() . '_' . $newKey)) ->setAttribute('key', $newKey); try { @@ -444,10 +444,10 @@ function updateAttribute( } } } else { - $attribute = $dbForProject->updateDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key, $attribute); + $attribute = $dbForProject->updateDocument('attributes', $database->getSequence() . '_' . $collection->getSequence() . '_' . $key, $attribute); } - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collection->getId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collection->getId()); $queueForEvents ->setContext('collection', $collection) @@ -536,7 +536,7 @@ App::post('/v1/databases') } try { - $dbForProject->createCollection('database_' . $database->getInternalId(), $attributes, $indexes); + $dbForProject->createCollection('database_' . $database->getSequence(), $attributes, $indexes); } catch (DuplicateException) { throw new Exception(Exception::DATABASE_ALREADY_EXISTS); } catch (IndexException) { @@ -839,7 +839,7 @@ App::delete('/v1/databases/:databaseId') } $dbForProject->purgeCachedDocument('databases', $database->getId()); - $dbForProject->purgeCachedCollection('databases_' . $database->getInternalId()); + $dbForProject->purgeCachedCollection('databases_' . $database->getSequence()); $queueForDatabase ->setType(DATABASE_TYPE_DELETE_DATABASE) @@ -899,9 +899,9 @@ App::post('/v1/databases/:databaseId/collections') $permissions = Permission::aggregate($permissions) ?? []; try { - $collection = $dbForProject->createDocument('database_' . $database->getInternalId(), new Document([ + $collection = $dbForProject->createDocument('database_' . $database->getSequence(), new Document([ '$id' => $collectionId, - 'databaseInternalId' => $database->getInternalId(), + 'databaseInternalId' => $database->getSequence(), 'databaseId' => $databaseId, '$permissions' => $permissions, 'documentSecurity' => $documentSecurity, @@ -919,7 +919,7 @@ App::post('/v1/databases/:databaseId/collections') try { $dbForProject->createCollection( - id: 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + id: 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), permissions: $permissions, documentSecurity: $documentSecurity ); @@ -1000,7 +1000,7 @@ App::get('/v1/databases/:databaseId/collections') $collectionId = $cursor->getValue(); - $cursorDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $cursorDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Collection '{$collectionId}' for the 'cursor' value not found."); @@ -1009,7 +1009,7 @@ App::get('/v1/databases/:databaseId/collections') $cursor->setValue($cursorDocument); } - $collectionId = 'database_' . $database->getInternalId(); + $collectionId = 'database_' . $database->getSequence(); try { $collections = $dbForProject->find($collectionId, $queries); @@ -1057,7 +1057,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -1100,8 +1100,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); + $collectionDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $database->getSequence() . '_collection_' . $collectionDocument->getSequence()); if ($collectionDocument->isEmpty() || $collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -1215,7 +1215,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -1236,12 +1236,12 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') ->setAttribute('search', \implode(' ', [$collectionId, $name])); $collection = $dbForProject->updateDocument( - 'database_' . $database->getInternalId(), + 'database_' . $database->getSequence(), $collectionId, $collection ); - $dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $permissions, $documentSecurity); + $dbForProject->updateCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $permissions, $documentSecurity); $queueForEvents ->setContext('database', $database) @@ -1287,17 +1287,17 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - if (!$dbForProject->deleteDocument('database_' . $database->getInternalId(), $collectionId)) { + if (!$dbForProject->deleteDocument('database_' . $database->getSequence(), $collectionId)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB'); } - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); $queueForDatabase ->setType(DATABASE_TYPE_DELETE_COLLECTION) @@ -1882,15 +1882,15 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $relatedCollectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); - $relatedCollection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollectionDocument->getInternalId()); + $relatedCollectionDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId); + $relatedCollection = $dbForProject->getCollection('database_' . $database->getSequence() . '_collection_' . $relatedCollectionDocument->getSequence()); if ($relatedCollection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -1991,7 +1991,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -2004,8 +2004,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') \array_push( $queries, - Query::equal('databaseInternalId', [$database->getInternalId()]), - Query::equal('collectionInternalId', [$collection->getInternalId()]), + Query::equal('databaseInternalId', [$database->getSequence()]), + Query::equal('collectionInternalId', [$collection->getSequence()]), ); /** @@ -2027,8 +2027,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') try { $cursorDocument = $dbForProject->findOne('attributes', [ - Query::equal('databaseInternalId', [$database->getInternalId()]), - Query::equal('collectionInternalId', [$collection->getInternalId()]), + Query::equal('databaseInternalId', [$database->getSequence()]), + Query::equal('collectionInternalId', [$collection->getSequence()]), Query::equal('key', [$attributeId]), ]); } catch (QueryException $e) { @@ -2099,13 +2099,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $attribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $collection->getSequence() . '_' . $key); if ($attribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); @@ -2712,13 +2712,13 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $attribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $collection->getSequence() . '_' . $key); if ($attribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); @@ -2741,19 +2741,19 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key $attribute = $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'deleting')); } - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { $options = $attribute->getAttribute('options'); if ($options['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); + $relatedCollection = $dbForProject->getDocument('database_' . $database->getSequence(), $options['relatedCollection']); if ($relatedCollection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $options['twoWayKey']); if ($relatedAttribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); @@ -2763,8 +2763,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'deleting')); } - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $options['relatedCollection']); - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $options['relatedCollection']); + $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence()); } } @@ -2846,7 +2846,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -2855,8 +2855,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') $limit = $dbForProject->getLimitForIndexes(); $count = $dbForProject->count('indexes', [ - Query::equal('collectionInternalId', [$collection->getInternalId()]), - Query::equal('databaseInternalId', [$database->getInternalId()]) + Query::equal('collectionInternalId', [$collection->getSequence()]), + Query::equal('databaseInternalId', [$database->getSequence()]) ], max: $limit); @@ -2926,12 +2926,12 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') } $index = new Document([ - '$id' => ID::custom($database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key), + '$id' => ID::custom($database->getSequence() . '_' . $collection->getSequence() . '_' . $key), 'key' => $key, 'status' => 'processing', // processing, available, failed, deleting, stuck - 'databaseInternalId' => $database->getInternalId(), + 'databaseInternalId' => $database->getSequence(), 'databaseId' => $databaseId, - 'collectionInternalId' => $collection->getInternalId(), + 'collectionInternalId' => $collection->getSequence(), 'collectionId' => $collectionId, 'type' => $type, 'attributes' => $attributes, @@ -2955,7 +2955,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') throw new Exception(Exception::INDEX_ALREADY_EXISTS); } - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); $queueForDatabase ->setType(DATABASE_TYPE_CREATE_INDEX) @@ -3007,7 +3007,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -3038,8 +3038,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') $indexId = $cursor->getValue(); $cursorDocument = Authorization::skip(fn () => $dbForProject->find('indexes', [ - Query::equal('collectionInternalId', [$collection->getInternalId()]), - Query::equal('databaseInternalId', [$database->getInternalId()]), + Query::equal('collectionInternalId', [$collection->getSequence()]), + Query::equal('databaseInternalId', [$database->getSequence()]), Query::equal('key', [$indexId]), Query::limit(1) ])); @@ -3098,7 +3098,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -3151,13 +3151,13 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $index = $dbForProject->getDocument('indexes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $index = $dbForProject->getDocument('indexes', $database->getSequence() . '_' . $collection->getSequence() . '_' . $key); if ($index->isEmpty()) { throw new Exception(Exception::INDEX_NOT_FOUND); @@ -3168,7 +3168,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') $index = $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'deleting')); } - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); $queueForDatabase ->setType(DATABASE_TYPE_DELETE_INDEX) @@ -3304,7 +3304,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -3413,7 +3413,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($relations as &$relation) { @@ -3427,7 +3427,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') } if ($relation instanceof Document) { $current = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId()) + fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId()) ); if ($current->isEmpty()) { @@ -3482,7 +3482,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') try { $dbForProject->createDocuments( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documents ); } catch (DuplicateException) { @@ -3524,7 +3524,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -3541,7 +3541,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); // per collection + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); // per collection $response->setStatusCode(Response::STATUS_CODE_CREATED); @@ -3599,7 +3599,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -3627,7 +3627,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $documentId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Document '{$documentId}' for the 'cursor' value not found."); @@ -3636,8 +3636,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $cursor->setValue($cursorDocument); } try { - $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries); - $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT); + $documents = $dbForProject->find('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $queries); + $total = $dbForProject->count('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $queries, APP_LIMIT_COUNT); } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } catch (QueryException $e) { @@ -3681,7 +3681,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $relatedCollectionId = $relationship->getAttribute('relatedCollection'); // todo: Use local cache for this getDocument - $relatedCollection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId)); + $relatedCollection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId)); foreach ($relations as $index => $doc) { if ($doc instanceof Document) { @@ -3707,7 +3707,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_READS, \max(1, $operations)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), \max(1, $operations)); + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_READS), \max(1, $operations)); $select = \array_reduce($queries, function ($result, $query) { return $result || ($query->getMethod() === Query::TYPE_SELECT); @@ -3778,7 +3778,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -3790,7 +3790,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen } try { - $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId, $queries); + $document = $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId, $queries); } catch (QueryException $e) { throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } @@ -3834,7 +3834,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -3849,7 +3849,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_READS, \max(1, $operations)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), \max(1, $operations)); + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_READS), \max(1, $operations)); $response->dynamic($document, Response::MODEL_DOCUMENT); }); @@ -3888,12 +3888,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); + $document = $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); @@ -4017,13 +4017,13 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } // Read permission should not be required for update - $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); } @@ -4092,7 +4092,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($relations as &$relation) { @@ -4107,7 +4107,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum } if ($relation instanceof Document) { $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( - 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); $relation->removeAttribute('$collectionId'); @@ -4115,7 +4115,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum // Attribute $collection is required for Utopia. $relation->setAttribute( '$collection', - 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId() + 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence() ); if ($oldDocument->isEmpty()) { @@ -4139,11 +4139,11 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); try { $document = $dbForProject->updateDocument( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $document->getId(), $newDocument ); @@ -4179,7 +4179,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -4261,7 +4261,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -4326,7 +4326,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($relations as &$relation) { @@ -4341,7 +4341,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen } if ($relation instanceof Document) { $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( - 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); $relation->removeAttribute('$collectionId'); @@ -4349,7 +4349,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen // Attribute $collection is required for Utopia. $relation->setAttribute( '$collection', - 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId() + 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence() ); if ($oldDocument->isEmpty()) { @@ -4373,12 +4373,12 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); $upserted = []; try { $modified = $dbForProject->createOrUpdateDocuments( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), [$newDocument], onNext: function (Document $document) use (&$upserted) { $upserted[] = $document; @@ -4417,7 +4417,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -4496,7 +4496,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -4527,7 +4527,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents') try { $modified = $dbForProject->updateDocuments( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), new Document($data), $queries, onNext: function (Document $document) use ($plan, &$documents) { @@ -4551,7 +4551,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $modified)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); $response->dynamic(new Document([ 'total' => $modified, @@ -4596,7 +4596,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -4618,7 +4618,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents') try { $modified = $dbForProject->createOrUpdateDocuments( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documents, onNext: function (Document $document) use ($plan, &$upserted) { if (\count($upserted) < ($plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH)) { @@ -4643,7 +4643,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $modified)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); $response->dynamic(new Document([ 'total' => $modified, @@ -4694,20 +4694,20 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } // Read permission should not be required for delete - $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); } try { $dbForProject->deleteDocument( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId ); } catch (ConflictException) { @@ -4742,7 +4742,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -4757,7 +4757,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); $relationships = \array_map( fn ($document) => $document->getAttribute('key'), @@ -4816,7 +4816,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -4840,7 +4840,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents') try { $modified = $dbForProject->deleteDocuments( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $queries, onNext: function (Document $document) use ($plan, &$documents) { if (\count($documents) < ($plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH)) { @@ -4861,7 +4861,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $modified)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); $response->dynamic(new Document([ 'total' => $modified, @@ -4997,11 +4997,11 @@ App::get('/v1/databases/:databaseId/usage') $stats = $usage = []; $days = $periods[$range]; $metrics = [ - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS), - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS), - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_STORAGE), - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES) + str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_COLLECTIONS), + str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_DOCUMENTS), + str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_STORAGE), + str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_READS), + str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES) ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { @@ -5090,8 +5090,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') ->inject('dbForProject') ->action(function (string $databaseId, string $range, string $collectionId, Response $response, Database $dbForProject) { $database = $dbForProject->getDocument('databases', $databaseId); - $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); + $collectionDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $database->getSequence() . '_collection_' . $collectionDocument->getSequence()); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -5101,7 +5101,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') $stats = $usage = []; $days = $periods[$range]; $metrics = [ - str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collectionDocument->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), + str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getSequence(), $collectionDocument->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 1d11e6c392..c74314e905 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -2511,11 +2511,11 @@ App::post('/v1/messaging/topics/:topicId/subscribers') Permission::delete(Role::user($user->getId())), ], 'topicId' => $topicId, - 'topicInternalId' => $topic->getInternalId(), + 'topicInternalId' => $topic->getSequence(), 'targetId' => $targetId, - 'targetInternalId' => $target->getInternalId(), + 'targetSequence' => $target->getSequence(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'providerType' => $target->getAttribute('providerType'), 'search' => implode(' ', [ $subscriberId, @@ -2597,7 +2597,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') throw new Exception(Exception::TOPIC_NOT_FOUND); } - $queries[] = Query::equal('topicInternalId', [$topic->getInternalId()]); + $queries[] = Query::equal('topicInternalId', [$topic->getSequence()]); /** * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries @@ -2947,7 +2947,7 @@ App::post('/v1/messaging/messages/email') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -2989,7 +2989,7 @@ App::post('/v1/messaging/messages/email') 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), - 'resourceInternalId' => $message->getInternalId(), + 'resourceInternalId' => $message->getSequence(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -3112,7 +3112,7 @@ App::post('/v1/messaging/messages/sms') 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), - 'resourceInternalId' => $message->getInternalId(), + 'resourceInternalId' => $message->getSequence(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -3232,7 +3232,7 @@ App::post('/v1/messaging/messages/push') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -3330,7 +3330,7 @@ App::post('/v1/messaging/messages/push') 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), - 'resourceInternalId' => $message->getInternalId(), + 'resourceInternalId' => $message->getSequence(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -3731,7 +3731,7 @@ App::patch('/v1/messaging/messages/email/:messageId') 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), - 'resourceInternalId' => $message->getInternalId(), + 'resourceInternalId' => $message->getSequence(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -3796,7 +3796,7 @@ App::patch('/v1/messaging/messages/email/:messageId') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -3933,7 +3933,7 @@ App::patch('/v1/messaging/messages/sms/:messageId') 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), - 'resourceInternalId' => $message->getInternalId(), + 'resourceInternalId' => $message->getSequence(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -4107,7 +4107,7 @@ App::patch('/v1/messaging/messages/push/:messageId') 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), - 'resourceInternalId' => $message->getInternalId(), + 'resourceInternalId' => $message->getSequence(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -4210,7 +4210,7 @@ App::patch('/v1/messaging/messages/push/:messageId') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 494ccfcaac..92fca88744 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -345,7 +345,7 @@ App::post('/v1/migrations/csv') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index 047179b888..d09470ff39 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -150,7 +150,7 @@ App::get('/v1/project/usage') $executionsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS); + $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -166,7 +166,7 @@ App::get('/v1/project/usage') $executionsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS); + $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -182,7 +182,7 @@ App::get('/v1/project/usage') $buildsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS); + $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -198,7 +198,7 @@ App::get('/v1/project/usage') $bucketsBreakdown = array_map(function ($bucket) use ($dbForProject) { $id = $bucket->getId(); $name = $bucket->getAttribute('name'); - $metric = str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE); + $metric = str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_STORAGE); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -214,7 +214,7 @@ App::get('/v1/project/usage') $databasesStorageBreakdown = array_map(function ($database) use ($dbForProject) { $id = $database->getId(); $name = $database->getAttribute('name'); - $metric = str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_STORAGE); + $metric = str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_STORAGE); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), @@ -231,13 +231,13 @@ App::get('/v1/project/usage') $functionsStorageBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $deploymentMetric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE); + $deploymentMetric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE); $deploymentValue = $dbForProject->findOne('stats', [ Query::equal('metric', [$deploymentMetric]), Query::equal('period', ['inf']) ]); - $buildMetric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE); + $buildMetric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE); $buildValue = $dbForProject->findOne('stats', [ Query::equal('metric', [$buildMetric]), Query::equal('period', ['inf']) @@ -255,7 +255,7 @@ App::get('/v1/project/usage') $executionsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS); + $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -271,7 +271,7 @@ App::get('/v1/project/usage') $buildsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS); + $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 5eda8e9a0e..51cbc097f5 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -182,7 +182,7 @@ App::post('/v1/projects') Permission::delete(Role::team(ID::custom($teamId), 'developer')), ], 'name' => $name, - 'teamInternalId' => $team->getInternalId(), + 'teamInternalId' => $team->getSequence(), 'teamId' => $team->getId(), 'region' => $region, 'description' => $description, @@ -230,13 +230,13 @@ App::post('/v1/projects') if ($sharedTables) { $dbForProject ->setSharedTables(true) - ->setTenant($sharedTablesV1 ? $project->getInternalId() : null) + ->setTenant($sharedTablesV1 ? $project->getSequence() : null) ->setNamespace($dsn->getParam('namespace')); } else { $dbForProject ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); + ->setNamespace('_' . $project->getSequence()); } $create = true; @@ -504,12 +504,12 @@ App::patch('/v1/projects/:projectId/team') $project ->setAttribute('teamId', $teamId) - ->setAttribute('teamInternalId', $team->getInternalId()) + ->setAttribute('teamInternalId', $team->getSequence()) ->setAttribute('$permissions', $permissions); $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project); $installations = $dbForPlatform->find('installations', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); foreach ($installations as $installation) { $installation->getAttribute('$permissions', $permissions); @@ -517,7 +517,7 @@ App::patch('/v1/projects/:projectId/team') } $repositories = $dbForPlatform->find('repositories', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); foreach ($repositories as $repository) { $repository->getAttribute('$permissions', $permissions); @@ -525,7 +525,7 @@ App::patch('/v1/projects/:projectId/team') } $vcsComments = $dbForPlatform->find('vcsComments', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); foreach ($vcsComments as $vcsComment) { $vcsComment->getAttribute('$permissions', $permissions); @@ -1229,7 +1229,7 @@ App::post('/v1/projects/:projectId/webhooks') Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'projectId' => $project->getId(), 'name' => $name, 'events' => $events, @@ -1279,7 +1279,7 @@ App::get('/v1/projects/:projectId/webhooks') } $webhooks = $dbForPlatform->find('webhooks', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), Query::limit(5000), ]); @@ -1320,7 +1320,7 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId') $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($webhook->isEmpty()) { @@ -1370,7 +1370,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($webhook->isEmpty()) { @@ -1427,7 +1427,7 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature') $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($webhook->isEmpty()) { @@ -1474,7 +1474,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($webhook->isEmpty()) { @@ -1528,7 +1528,7 @@ App::post('/v1/projects/:projectId/keys') Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'projectId' => $project->getId(), 'name' => $name, 'scopes' => $scopes, @@ -1576,7 +1576,7 @@ App::get('/v1/projects/:projectId/keys') } $keys = $dbForPlatform->find('keys', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), Query::limit(5000), ]); @@ -1617,7 +1617,7 @@ App::get('/v1/projects/:projectId/keys/:keyId') $key = $dbForPlatform->findOne('keys', [ Query::equal('$id', [$keyId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($key->isEmpty()) { @@ -1661,7 +1661,7 @@ App::put('/v1/projects/:projectId/keys/:keyId') $key = $dbForPlatform->findOne('keys', [ Query::equal('$id', [$keyId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($key->isEmpty()) { @@ -1712,7 +1712,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId') $key = $dbForPlatform->findOne('keys', [ Query::equal('$id', [$keyId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($key->isEmpty()) { @@ -1811,7 +1811,7 @@ App::post('/v1/projects/:projectId/platforms') Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'projectId' => $project->getId(), 'type' => $type, 'name' => $name, @@ -1858,7 +1858,7 @@ App::get('/v1/projects/:projectId/platforms') } $platforms = $dbForPlatform->find('platforms', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), Query::limit(5000), ]); @@ -1899,7 +1899,7 @@ App::get('/v1/projects/:projectId/platforms/:platformId') $platform = $dbForPlatform->findOne('platforms', [ Query::equal('$id', [$platformId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($platform->isEmpty()) { @@ -1943,7 +1943,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId') $platform = $dbForPlatform->findOne('platforms', [ Query::equal('$id', [$platformId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($platform->isEmpty()) { @@ -1997,7 +1997,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') $platform = $dbForPlatform->findOne('platforms', [ Query::equal('$id', [$platformId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($platform->isEmpty()) { diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index c1c8d8e4a0..417ea602ba 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -58,7 +58,7 @@ App::get('/v1/proxy/rules') $queries[] = Query::search('search', $search); } - $queries[] = Query::equal('projectInternalId', [$project->getInternalId()]); + $queries[] = Query::equal('projectInternalId', [$project->getSequence()]); /** * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries @@ -124,7 +124,7 @@ App::get('/v1/proxy/rules/:ruleId') ->action(function (string $ruleId, Response $response, Document $project, Database $dbForPlatform) { $rule = $dbForPlatform->getDocument('rules', $ruleId); - if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getInternalId()) { + if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getSequence()) { throw new Exception(Exception::RULE_NOT_FOUND); } @@ -165,7 +165,7 @@ App::delete('/v1/proxy/rules/:ruleId') ->action(function (string $ruleId, Response $response, Document $project, Database $dbForPlatform, Delete $queueForDeletes, Event $queueForEvents) { $rule = $dbForPlatform->getDocument('rules', $ruleId); - if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getInternalId()) { + if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getSequence()) { throw new Exception(Exception::RULE_NOT_FOUND); } @@ -210,7 +210,7 @@ App::patch('/v1/proxy/rules/:ruleId/verification') ->action(function (string $ruleId, Response $response, Certificate $queueForCertificates, Event $queueForEvents, Document $project, Database $dbForPlatform, Log $log) { $rule = $dbForPlatform->getDocument('rules', $ruleId); - if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getInternalId()) { + if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getSequence()) { throw new Exception(Exception::RULE_NOT_FOUND); } diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index b3b8fb906a..a25241ec4b 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -145,7 +145,7 @@ App::post('/v1/storage/buckets') $bucket = $dbForProject->getDocument('buckets', $bucketId); - $dbForProject->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes, permissions: $permissions ?? [], documentSecurity: $fileSecurity); + $dbForProject->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes, permissions: $permissions ?? [], documentSecurity: $fileSecurity); } catch (DuplicateException) { throw new Exception(Exception::STORAGE_BUCKET_ALREADY_EXISTS); } @@ -326,7 +326,7 @@ App::put('/v1/storage/buckets/:bucketId') ->setAttribute('compression', $compression) ->setAttribute('antivirus', $antivirus)); - $dbForProject->updateCollection('bucket_' . $bucket->getInternalId(), $permissions, $fileSecurity); + $dbForProject->updateCollection('bucket_' . $bucket->getSequence(), $permissions, $fileSecurity); $queueForEvents ->setParam('bucketId', $bucket->getId()); @@ -558,7 +558,7 @@ App::post('/v1/storage/buckets/:bucketId/files') $path = $deviceForFiles->getPath($fileId . '.' . \pathinfo($fileName, PATHINFO_EXTENSION)); $path = str_ireplace($deviceForFiles->getRoot(), $deviceForFiles->getRoot() . DIRECTORY_SEPARATOR . $bucket->getId(), $path); // Add bucket id to path after root - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); $metadata = ['content_type' => $deviceForLocal->getFileMimeType($fileTmpName)]; if (!$file->isEmpty()) { @@ -652,7 +652,7 @@ App::post('/v1/storage/buckets/:bucketId/files') '$id' => $fileId, '$permissions' => $permissions, 'bucketId' => $bucket->getId(), - 'bucketInternalId' => $bucket->getInternalId(), + 'bucketInternalId' => $bucket->getSequence(), 'name' => $fileName, 'path' => $path, 'signature' => $fileHash, @@ -671,7 +671,7 @@ App::post('/v1/storage/buckets/:bucketId/files') 'metadata' => $metadata, ]); - $file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc); + $file = $dbForProject->createDocument('bucket_' . $bucket->getSequence(), $doc); } else { $file = $file ->setAttribute('$permissions', $permissions) @@ -696,7 +696,7 @@ App::post('/v1/storage/buckets/:bucketId/files') if (!$validator->isValid($bucket->getCreate())) { throw new Exception(Exception::USER_UNAUTHORIZED); } - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file)); + $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } } else { if ($file->isEmpty()) { @@ -704,7 +704,7 @@ App::post('/v1/storage/buckets/:bucketId/files') '$id' => ID::custom($fileId), '$permissions' => $permissions, 'bucketId' => $bucket->getId(), - 'bucketInternalId' => $bucket->getInternalId(), + 'bucketInternalId' => $bucket->getSequence(), 'name' => $fileName, 'path' => $path, 'signature' => '', @@ -720,7 +720,7 @@ App::post('/v1/storage/buckets/:bucketId/files') ]); try { - $file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc); + $file = $dbForProject->createDocument('bucket_' . $bucket->getSequence(), $doc); } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -741,7 +741,7 @@ App::post('/v1/storage/buckets/:bucketId/files') } try { - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file)); + $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -826,9 +826,9 @@ App::get('/v1/storage/buckets/:bucketId/files') $fileId = $cursor->getValue(); if ($fileSecurity && !$valid) { - $cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($cursorDocument->isEmpty()) { @@ -842,11 +842,11 @@ App::get('/v1/storage/buckets/:bucketId/files') try { if ($fileSecurity && !$valid) { - $files = $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries); - $total = $dbForProject->count('bucket_' . $bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT); + $files = $dbForProject->find('bucket_' . $bucket->getSequence(), $queries); + $total = $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT); } else { - $files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries)); - $total = Authorization::skip(fn () => $dbForProject->count('bucket_' . $bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT)); + $files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries)); + $total = Authorization::skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -902,9 +902,9 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId') } if ($fileSecurity && !$valid) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($file->isEmpty()) { @@ -973,7 +973,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getInternalId(); + $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); @@ -982,12 +982,12 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') } if ($fileSecurity && !$valid && !$isToken) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } - if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getInternalId()) { + if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -1150,7 +1150,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getInternalId(); + $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); @@ -1159,12 +1159,12 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') } if ($fileSecurity && !$valid) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } - if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getInternalId()) { + if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -1309,7 +1309,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getInternalId(); + $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); @@ -1318,12 +1318,12 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') } if ($fileSecurity && !$valid) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } - if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getInternalId()) { + if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -1478,7 +1478,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -1643,7 +1643,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') } // Read permission should not be required for update - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -1689,9 +1689,9 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') try { if ($fileSecurity && !$valid) { - $file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file); + $file = $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file); } else { - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file)); + $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -1757,7 +1757,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') } // Read permission should not be required for delete - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -1787,9 +1787,9 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') try { if ($fileSecurity && !$valid) { - $deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId); + $deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $deleted = Authorization::skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $deleted = Authorization::skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -1937,14 +1937,14 @@ App::get('/v1/storage/:bucketId/usage') $stats = $usage = []; $days = $periods[$range]; $metrics = [ - str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES), - str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE), - str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED), + str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES), + str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_STORAGE), + str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED), ]; Authorization::skip(function () use ($dbForProject, $dbForLogs, $bucket, $days, $metrics, &$stats) { foreach ($metrics as $metric) { - $db = ($metric === str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED)) + $db = ($metric === str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED)) ? $dbForLogs : $dbForProject; diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 49d9005c54..c83cad7eb1 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -123,9 +123,9 @@ App::post('/v1/teams') Permission::delete(Role::team($team->getId(), 'owner')), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'teamId' => $team->getId(), - 'teamInternalId' => $team->getInternalId(), + 'teamInternalId' => $team->getSequence(), 'roles' => $roles, 'invited' => DateTime::now(), 'joined' => DateTime::now(), @@ -595,8 +595,8 @@ App::post('/v1/teams/:teamId/memberships') } $membership = $dbForProject->findOne('memberships', [ - Query::equal('userInternalId', [$invitee->getInternalId()]), - Query::equal('teamInternalId', [$team->getInternalId()]), + Query::equal('userInternalId', [$invitee->getSequence()]), + Query::equal('teamInternalId', [$team->getSequence()]), ]); $secret = Auth::tokenGenerator(); @@ -612,9 +612,9 @@ App::post('/v1/teams/:teamId/memberships') Permission::delete(Role::team($team->getId(), 'owner')), ], 'userId' => $invitee->getId(), - 'userInternalId' => $invitee->getInternalId(), + 'userInternalId' => $invitee->getSequence(), 'teamId' => $team->getId(), - 'teamInternalId' => $team->getInternalId(), + 'teamInternalId' => $team->getSequence(), 'roles' => $roles, 'invited' => DateTime::now(), 'joined' => ($isPrivilegedUser || $isAppUser) ? DateTime::now() : null, @@ -842,7 +842,7 @@ App::get('/v1/teams/:teamId/memberships') } // Set internal queries - $queries[] = Query::equal('teamInternalId', [$team->getInternalId()]); + $queries[] = Query::equal('teamInternalId', [$team->getSequence()]); /** * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries @@ -1092,7 +1092,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') collection: 'memberships', queries: [ Query::contains('roles', ['owner']), - Query::equal('teamInternalId', [$team->getInternalId()]) + Query::equal('teamInternalId', [$team->getSequence()]) ], max: 2 ); @@ -1180,7 +1180,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') throw new Exception(Exception::TEAM_NOT_FOUND); } - if ($membership->getAttribute('teamInternalId') !== $team->getInternalId()) { + if ($membership->getAttribute('teamInternalId') !== $team->getSequence()) { throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH); } @@ -1197,7 +1197,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $user->setAttributes($dbForProject->getDocument('users', $userId)->getArrayCopy()); // Get user } - if ($membership->getAttribute('userInternalId') !== $user->getInternalId()) { + if ($membership->getAttribute('userInternalId') !== $user->getSequence()) { throw new Exception(Exception::TEAM_INVITE_MISMATCH, 'Invite does not belong to current user (' . $user->getAttribute('email') . ')'); } @@ -1229,7 +1229,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'provider' => Auth::SESSION_PROVIDER_EMAIL, 'providerUid' => $user->getAttribute('email'), 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak @@ -1338,7 +1338,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') throw new Exception(Exception::TEAM_NOT_FOUND); } - if ($membership->getAttribute('teamInternalId') !== $team->getInternalId()) { + if ($membership->getAttribute('teamInternalId') !== $team->getSequence()) { throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH); } diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index bc9de0fd42..4b6e5abe6b 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -140,7 +140,7 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'providerType' => 'email', 'identifier' => $email, ])); @@ -164,7 +164,7 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'providerType' => 'sms', 'identifier' => $phone, ])); @@ -564,10 +564,10 @@ App::post('/v1/users/:userId/targets') Permission::delete(Role::user($user->getId())), ], 'providerId' => empty($provider->getId()) ? null : $provider->getId(), - 'providerInternalId' => $provider->isEmpty() ? null : $provider->getInternalId(), + 'providerInternalId' => $provider->isEmpty() ? null : $provider->getSequence(), 'providerType' => $providerType, 'userId' => $userId, - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'identifier' => $identifier, 'name' => ($name !== '') ? $name : null, ])); @@ -846,7 +846,7 @@ App::get('/v1/users/:userId/memberships') } // Set internal queries - $queries[] = Query::equal('userInternalId', [$user->getInternalId()]); + $queries[] = Query::equal('userInternalId', [$user->getSequence()]); $memberships = array_map(function ($membership) use ($dbForProject, $user) { $team = $dbForProject->getDocument('teams', $membership->getAttribute('teamId')); @@ -910,7 +910,7 @@ App::get('/v1/users/:userId/logs') $audit = new Audit($dbForProject); - $logs = $audit->getLogsByUser($user->getInternalId(), $queries); + $logs = $audit->getLogsByUser($user->getSequence(), $queries); $output = []; @@ -957,7 +957,7 @@ App::get('/v1/users/:userId/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByUser($user->getInternalId(), $queries), + 'total' => $audit->countLogsByUser($user->getSequence(), $queries), 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -1396,7 +1396,7 @@ App::patch('/v1/users/:userId/email') // Makes sure this email is not already used in another identity $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), - Query::notEqual('userInternalId', $user->getInternalId()), + Query::notEqual('userInternalId', $user->getSequence()), ]); if (!$identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); @@ -1440,7 +1440,7 @@ App::patch('/v1/users/:userId/email') Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'providerType' => 'email', 'identifier' => $email, ])); @@ -1529,7 +1529,7 @@ App::patch('/v1/users/:userId/phone') Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'providerType' => 'sms', 'identifier' => $number, ])); @@ -1711,7 +1711,7 @@ App::patch('/v1/users/:userId/targets/:targetId') $target ->setAttribute('providerId', $provider->getId()) - ->setAttribute('providerInternalId', $provider->getInternalId()); + ->setAttribute('providerInternalId', $provider->getSequence()); } if ($name) { @@ -2051,7 +2051,7 @@ App::post('/v1/users/:userId/sessions') [ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'provider' => Auth::SESSION_PROVIDER_SERVER, 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'userAgent' => $request->getUserAgent('UNKNOWN'), @@ -2131,7 +2131,7 @@ App::post('/v1/users/:userId/tokens') $token = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'type' => Auth::TOKEN_TYPE_GENERIC, 'secret' => Auth::hash($secret), 'expire' => $expire, @@ -2293,8 +2293,8 @@ App::delete('/v1/users/:userId') $clone = clone $user; $dbForProject->deleteDocument('users', $userId); - DeleteIdentities::delete($dbForProject, Query::equal('userInternalId', [$user->getInternalId()])); - DeleteTargets::delete($dbForProject, Query::equal('userInternalId', [$user->getInternalId()])); + DeleteIdentities::delete($dbForProject, Query::equal('userInternalId', [$user->getSequence()])); + DeleteTargets::delete($dbForProject, Query::equal('userInternalId', [$user->getSequence()])); $queueForDeletes ->setType(DELETE_TYPE_DOCUMENT) diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 571c7ddca7..746f61c59c 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -78,11 +78,11 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $resourceCollection = $resourceType === "function" ? 'functions' : 'sites'; $resourceId = $repository->getAttribute('resourceId'); $resource = Authorization::skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId)); - $resourceInternalId = $resource->getInternalId(); + $resourceInternalId = $resource->getSequence(); $deploymentId = ID::unique(); $repositoryId = $repository->getId(); - $repositoryInternalId = $repository->getInternalId(); + $repositoryInternalId = $repository->getSequence(); $providerRepositoryId = $repository->getAttribute('providerRepositoryId'); $installationId = $repository->getAttribute('installationId'); $installationInternalId = $repository->getAttribute('installationInternalId'); @@ -157,7 +157,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId ], 'installationInternalId' => $installationInternalId, 'installationId' => $installationId, - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'projectId' => $project->getId(), 'providerRepositoryId' => $providerRepositoryId, 'providerBranch' => $providerBranch, @@ -257,7 +257,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $resource = $resource ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); Authorization::skip(fn () => $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource)); @@ -273,12 +273,12 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'domain' => $domain, 'type' => 'deployment', 'trigger' => 'deployment', 'deploymentId' => $deployment->getId(), - 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->getSequence(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $resourceId, 'deploymentResourceInternalId' => $resourceInternalId, @@ -300,12 +300,12 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'domain' => $domain, 'type' => 'deployment', 'trigger' => 'deployment', 'deploymentId' => $deployment->getId(), - 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->getSequence(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $resourceId, 'deploymentResourceInternalId' => $resourceInternalId, @@ -331,12 +331,12 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'domain' => $domain, 'type' => 'deployment', 'trigger' => 'deployment', 'deploymentId' => $deployment->getId(), - 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->getSequence(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $resourceId, 'deploymentResourceInternalId' => $resourceInternalId, @@ -503,7 +503,7 @@ App::get('/v1/vcs/github/callback') $github->initializeVariables($providerInstallationId, $privateKey, $githubAppId); $owner = $github->getOwnerName($providerInstallationId) ?? ''; - $projectInternalId = $project->getInternalId(); + $projectInternalId = $project->getSequence(); $installation = $dbForPlatform->findOne('installations', [ Query::equal('providerInstallationId', [$providerInstallationId]), @@ -999,7 +999,7 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories') if (empty($accessToken) || empty($refreshToken) || empty($accessTokenExpiry)) { $identity = $dbForPlatform->findOne('identities', [ Query::equal('provider', ['github']), - Query::equal('userInternalId', [$user->getInternalId()]), + Query::equal('userInternalId', [$user->getSequence()]), ]); if ($identity->isEmpty()) { throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); @@ -1246,7 +1246,7 @@ App::post('/v1/vcs/github/events') foreach ($installations as $installation) { $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ - Query::equal('installationInternalId', [$installation->getInternalId()]), + Query::equal('installationInternalId', [$installation->getSequence()]), Query::limit(1000) ])); @@ -1349,7 +1349,7 @@ App::get('/v1/vcs/installations') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $queries[] = Query::equal('projectInternalId', [$project->getInternalId()]); + $queries[] = Query::equal('projectInternalId', [$project->getSequence()]); if (!empty($search)) { $queries[] = Query::search('search', $search); @@ -1422,7 +1422,7 @@ App::get('/v1/vcs/installations/:installationId') throw new Exception(Exception::INSTALLATION_NOT_FOUND); } - if ($installation->getAttribute('projectInternalId') !== $project->getInternalId()) { + if ($installation->getAttribute('projectInternalId') !== $project->getSequence()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); } @@ -1505,7 +1505,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor } $repository = Authorization::skip(fn () => $dbForPlatform->getDocument('repositories', $repositoryId, [ - Query::equal('projectInternalId', [$project->getInternalId()]) + Query::equal('projectInternalId', [$project->getSequence()]) ])); if ($repository->isEmpty()) { diff --git a/app/controllers/general.php b/app/controllers/general.php index bff701792e..90a108c7c6 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -391,9 +391,9 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $execution = new Document([ '$id' => $executionId, '$permissions' => [], - 'resourceInternalId' => $resource->getInternalId(), + 'resourceInternalId' => $resource->getSequence(), 'resourceId' => $resource->getId(), - 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->getSequence(), 'deploymentId' => $deployment->getId(), 'responseStatusCode' => 0, 'responseHeaders' => [], @@ -692,11 +692,11 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $metricTypeExecutions = str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_EXECUTIONS); - $metricTypeIdExecutions = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS); + $metricTypeIdExecutions = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS); $metricTypeExecutionsCompute = str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE); - $metricTypeIdExecutionsCompute = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE); + $metricTypeIdExecutionsCompute = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE); $metricTypeExecutionsMbSeconds = str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS); - $metricTypeIdExecutionsMBSeconds = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS); + $metricTypeIdExecutionsMBSeconds = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS); if ($deployment->getAttribute('resourceType') === 'sites') { $queueForStatsUsage ->disableMetric(METRIC_NETWORK_REQUESTS) @@ -719,9 +719,9 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw ->addMetric(METRIC_SITES_REQUESTS, 1) ->addMetric(METRIC_SITES_INBOUND, $request->getSize() + $fileSize) ->addMetric(METRIC_SITES_OUTBOUND, $response->getSize()) - ->addMetric(str_replace('{siteInternalId}', $resource->getInternalId(), METRIC_SITES_ID_REQUESTS), 1) - ->addMetric(str_replace('{siteInternalId}', $resource->getInternalId(), METRIC_SITES_ID_INBOUND), $request->getSize() + $fileSize) - ->addMetric(str_replace('{siteInternalId}', $resource->getInternalId(), METRIC_SITES_ID_OUTBOUND), $response->getSize()) + ->addMetric(str_replace('{siteInternalId}', $resource->getSequence(), METRIC_SITES_ID_REQUESTS), 1) + ->addMetric(str_replace('{siteInternalId}', $resource->getSequence(), METRIC_SITES_ID_INBOUND), $request->getSize() + $fileSize) + ->addMetric(str_replace('{siteInternalId}', $resource->getSequence(), METRIC_SITES_ID_OUTBOUND), $response->getSize()) ; } @@ -914,7 +914,7 @@ App::init() 'type' => 'api', 'status' => 'verifying', 'projectId' => $console->getId(), - 'projectInternalId' => $console->getInternalId(), + 'projectInternalId' => $console->getSequence(), 'search' => implode(' ', [$ruleId, $domain->get()]), 'owner' => $owner, 'region' => $console->getAttribute('region') @@ -964,7 +964,7 @@ App::init() )[0] ?? new Document(); } - if (!$rule->isEmpty() && $rule->getAttribute('projectInternalId') === $project->getInternalId()) { + if (!$rule->isEmpty() && $rule->getAttribute('projectInternalId') === $project->getSequence()) { $refDomainOrigin = $origin; } } diff --git a/app/controllers/mock.php b/app/controllers/mock.php index 16d8e03841..fd7b9ab495 100644 --- a/app/controllers/mock.php +++ b/app/controllers/mock.php @@ -185,7 +185,7 @@ App::post('/v1/mock/api-key-unprefixed') Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'projectId' => $project->getId(), 'name' => 'Outdated key', 'scopes' => $scopes, @@ -235,7 +235,7 @@ App::get('/v1/mock/github/callback') $github->initializeVariables($providerInstallationId, $privateKey, $githubAppId); $owner = $github->getOwnerName($providerInstallationId) ?? ''; - $projectInternalId = $project->getInternalId(); + $projectInternalId = $project->getSequence(); $teamId = $project->getAttribute('teamId', ''); diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index 937f245099..f99ebbce07 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -574,7 +574,7 @@ App::init() $bucketId = $parts[1] ?? null; $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getInternalId(); + $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -593,12 +593,12 @@ App::init() $fileId = $parts[1] ?? null; if ($fileSecurity && !$valid && !$isToken) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } - if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getInternalId()) { + if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { throw new Exception(Exception::USER_UNAUTHORIZED); } diff --git a/app/http.php b/app/http.php index 6064dfdd4c..30f4013821 100644 --- a/app/http.php +++ b/app/http.php @@ -309,7 +309,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg 'orders' => $index['orders'], ]), $files['indexes']); - $dbForPlatform->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes); + $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes); } if (Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) { @@ -357,7 +357,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg 'orders' => $index['orders'], ]), $files['indexes']); - Authorization::skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes)); + Authorization::skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes)); } }); diff --git a/app/init/database/filters.php b/app/init/database/filters.php index f110fe1554..7f2282747e 100644 --- a/app/init/database/filters.php +++ b/app/init/database/filters.php @@ -71,7 +71,7 @@ Database::addFilter( }, function (mixed $value, Document $document, Database $database) { $attributes = $database->find('attributes', [ - Query::equal('collectionInternalId', [$document->getInternalId()]), + Query::equal('collectionInternalId', [$document->getSequence()]), Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), Query::limit($database->getLimitForAttributes()), ]); @@ -98,7 +98,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return $database ->find('indexes', [ - Query::equal('collectionInternalId', [$document->getInternalId()]), + Query::equal('collectionInternalId', [$document->getSequence()]), Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), Query::limit($database->getLimitForIndexes()), ]); @@ -113,7 +113,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return $database ->find('platforms', [ - Query::equal('projectInternalId', [$document->getInternalId()]), + Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ]); } @@ -127,7 +127,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return $database ->find('keys', [ - Query::equal('projectInternalId', [$document->getInternalId()]), + Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ]); } @@ -141,7 +141,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return $database ->find('devKeys', [ - Query::equal('projectInternalId', [$document->getInternalId()]), + Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ]); } @@ -155,7 +155,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return $database ->find('webhooks', [ - Query::equal('projectInternalId', [$document->getInternalId()]), + Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ]); } @@ -168,7 +168,7 @@ Database::addFilter( }, function (mixed $value, Document $document, Database $database) { return Authorization::skip(fn () => $database->find('sessions', [ - Query::equal('userInternalId', [$document->getInternalId()]), + Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ])); } @@ -182,7 +182,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return Authorization::skip(fn () => $database ->find('tokens', [ - Query::equal('userInternalId', [$document->getInternalId()]), + Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ])); } @@ -196,7 +196,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return Authorization::skip(fn () => $database ->find('challenges', [ - Query::equal('userInternalId', [$document->getInternalId()]), + Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ])); } @@ -210,7 +210,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return Authorization::skip(fn () => $database ->find('authenticators', [ - Query::equal('userInternalId', [$document->getInternalId()]), + Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ])); } @@ -224,7 +224,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return Authorization::skip(fn () => $database ->find('memberships', [ - Query::equal('userInternalId', [$document->getInternalId()]), + Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ])); } @@ -238,7 +238,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return $database ->find('variables', [ - Query::equal('resourceInternalId', [$document->getInternalId()]), + Query::equal('resourceInternalId', [$document->getSequence()]), Query::equal('resourceType', ['function', 'site']), Query::limit(APP_LIMIT_SUBQUERY), ]); @@ -316,7 +316,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return Authorization::skip(fn () => $database ->find('targets', [ - Query::equal('userInternalId', [$document->getInternalId()]), + Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY) ])); } @@ -329,15 +329,15 @@ Database::addFilter( }, function (mixed $value, Document $document, Database $database) { $targetIds = Authorization::skip(fn () => \array_map( - fn ($document) => $document->getAttribute('targetInternalId'), + fn ($document) => $document->getAttribute('targetSequence'), $database->find('subscribers', [ - Query::equal('topicInternalId', [$document->getInternalId()]), + Query::equal('topicInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBSCRIBERS_SUBQUERY) ]) )); if (\count($targetIds) > 0) { return $database->skipValidation(fn () => $database->find('targets', [ - Query::equal('$internalId', $targetIds) + Query::equal('$sequence', $targetIds) ])); } return []; diff --git a/app/init/resources.php b/app/init/resources.php index c75df2a362..7c3df681b1 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -347,13 +347,13 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getInternalId()) + ->setTenant($project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); + ->setNamespace('_' . $project->getSequence()); } return $database; @@ -400,13 +400,13 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getInternalId()) + ->setTenant($project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); + ->setNamespace('_' . $project->getSequence()); } }); @@ -430,7 +430,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) { return function (?Document $project = null) use ($pools, $cache, &$database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { - $database->setTenant($project->getInternalId()); + $database->setTenant($project->getSequence()); return $database; } @@ -445,7 +445,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) { // set tenant if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') { - $database->setTenant($project->getInternalId()); + $database->setTenant($project->getSequence()); } return $database; @@ -836,7 +836,7 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A $team = Authorization::skip(function () use ($dbForPlatform, $teamInternalId) { return $dbForPlatform->findOne('teams', [ - Query::equal('$internalId', [$teamInternalId]), + Query::equal('$sequence', [$teamInternalId]), ]); }); @@ -915,10 +915,10 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { return match ($token->getAttribute('resourceType')) { TOKENS_RESOURCE_TYPE_FILES => (function () use ($token, $dbForProject) { - $internalIds = explode(':', $token->getAttribute('resourceInternalId')); + $sequences = explode(':', $token->getAttribute('resourceInternalId')); $ids = explode(':', $token->getAttribute('resourceId')); - if (count($internalIds) !== 2 || count($ids) !== 2) { + if (count($sequences) !== 2 || count($ids) !== 2) { return new Document([]); } @@ -931,8 +931,8 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { return new Document([ 'bucketId' => $ids[0], 'fileId' => $ids[1], - 'bucketInternalId' => $internalIds[0], - 'fileInternalId' => $internalIds[1], + 'bucketInternalId' => $sequences[0], + 'fileInternalId' => $sequences[1], ]); })(), diff --git a/app/realtime.php b/app/realtime.php index 7e6fc0e311..96484c8a35 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -79,8 +79,8 @@ if (!function_exists('getProjectDB')) { static $databases = []; - if (isset($databases[$project->getInternalId()])) { - return $databases[$project->getInternalId()]; + if (isset($databases[$project->getSequence()])) { + return $databases[$project->getSequence()]; } /** @var Group $pools */ @@ -105,20 +105,20 @@ if (!function_exists('getProjectDB')) { if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getInternalId()) + ->setTenant($project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); + ->setNamespace('_' . $project->getSequence()); } $database ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()); - return $databases[$project->getInternalId()] = $database; + return $databases[$project->getSequence()] = $database; } } diff --git a/app/worker.php b/app/worker.php index 597e8a9943..2b6726c855 100644 --- a/app/worker.php +++ b/app/worker.php @@ -90,13 +90,13 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getInternalId()) + ->setTenant($project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); + ->setNamespace('_' . $project->getSequence()); } $database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); @@ -127,13 +127,13 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getInternalId()) + ->setTenant($project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); + ->setNamespace('_' . $project->getSequence()); } return $database; @@ -149,13 +149,13 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getInternalId()) + ->setTenant($project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); + ->setNamespace('_' . $project->getSequence()); } $database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); @@ -168,7 +168,7 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = null; return function (?Document $project = null) use ($pools, $cache, $database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { - $database->setTenant($project->getInternalId()); + $database->setTenant($project->getSequence()); return $database; } @@ -183,7 +183,7 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) { // set tenant if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') { - $database->setTenant($project->getInternalId()); + $database->setTenant($project->getSequence()); } return $database; diff --git a/src/Appwrite/Deletes/Targets.php b/src/Appwrite/Deletes/Targets.php index 95e744ddf1..68a9d675b6 100644 --- a/src/Appwrite/Deletes/Targets.php +++ b/src/Appwrite/Deletes/Targets.php @@ -27,7 +27,7 @@ class Targets $database->deleteDocuments( 'subscribers', [ - Query::equal('targetInternalId', [$target->getInternalId()]), + Query::equal('targetSequence', [$target->getSequence()]), Query::orderAsc(), ], Database::DELETE_BATCH_SIZE, @@ -35,7 +35,7 @@ class Targets $topicId = $subscriber->getAttribute('topicId'); $topicInternalId = $subscriber->getAttribute('topicInternalId'); $topic = $database->getDocument('topics', $topicId); - if (!$topic->isEmpty() && $topic->getInternalId() === $topicInternalId) { + if (!$topic->isEmpty() && $topic->getSequence() === $topicInternalId) { $totalAttribute = match ($target->getAttribute('providerType')) { MESSAGE_TYPE_EMAIL => 'emailTotal', MESSAGE_TYPE_SMS => 'smsTotal', diff --git a/src/Appwrite/Event/Event.php b/src/Appwrite/Event/Event.php index 2c735ef2d4..934647f7c3 100644 --- a/src/Appwrite/Event/Event.php +++ b/src/Appwrite/Event/Event.php @@ -320,7 +320,7 @@ class Event if ($this->project) { $trimmed['project'] = new Document([ '$id' => $this->project->getId(), - '$internalId' => $this->project->getInternalId(), + '$sequence' => $this->project->getSequence(), 'database' => $this->project->getAttribute('database') ]); } diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 81ea1ef263..73d16394c0 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -155,7 +155,7 @@ abstract class Migration */ public function forEachDocument(callable $callback): void { - $projectInternalId = $this->project->getInternalId(); + $projectInternalId = $this->project->getSequence(); $collections = match ($projectInternalId) { 'console' => $this->collections['console'], @@ -208,7 +208,7 @@ abstract class Migration { $name ??= $id; - $collectionType = match ($this->project->getInternalId()) { + $collectionType = match ($this->project->getSequence()) { 'console' => 'console', default => 'projects', }; @@ -259,7 +259,7 @@ abstract class Migration ): void { $from ??= $collectionId; - $collectionType = match ($this->project->getInternalId()) { + $collectionType = match ($this->project->getSequence()) { 'console' => 'console', default => 'projects', }; @@ -324,7 +324,7 @@ abstract class Migration ): void { $from ??= $collectionId; - $collectionType = match ($this->project->getInternalId()) { + $collectionType = match ($this->project->getSequence()) { 'console' => 'console', default => 'projects', }; @@ -382,7 +382,7 @@ abstract class Migration { $from ??= $collectionId; - $collectionType = match ($this->project->getInternalId()) { + $collectionType = match ($this->project->getSequence()) { 'console' => 'console', default => 'projects', }; @@ -428,7 +428,7 @@ abstract class Migration */ protected function changeAttributeInternalType(string $collection, string $attribute, string $type): void { - $stmt = $this->pdo->prepare("ALTER TABLE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$collection}` MODIFY `$attribute` $type;"); + $stmt = $this->pdo->prepare("ALTER TABLE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}_{$collection}` MODIFY `$attribute` $type;"); try { $stmt->execute(); diff --git a/src/Appwrite/Migration/Version/V15.php b/src/Appwrite/Migration/Version/V15.php index 8eab916f19..15331e9a37 100644 --- a/src/Appwrite/Migration/Version/V15.php +++ b/src/Appwrite/Migration/Version/V15.php @@ -95,7 +95,7 @@ class V15 extends Migration $this->migrateStatsMetric('storage.files.delete', 'files.$all.requests.delete'); foreach ($this->documentsIterator('buckets') as $bucket) { - $bucketTable = "bucket_{$bucket->getInternalId()}"; + $bucketTable = "bucket_{$bucket->getSequence()}"; $this->createPermissionsColumn($bucketTable); $this->migrateDateTimeAttribute($bucketTable, '_createdAt'); @@ -178,7 +178,7 @@ class V15 extends Migration * Migrate every Database. */ foreach ($this->documentsIterator('databases') as $database) { - $databaseTable = "database_{$database->getInternalId()}"; + $databaseTable = "database_{$database->getSequence()}"; $this->createPermissionsColumn($databaseTable); $this->migrateDateTimeAttribute($databaseTable, '_createdAt'); $this->migrateDateTimeAttribute($databaseTable, '_updatedAt'); @@ -216,7 +216,7 @@ class V15 extends Migration */ Console::info("Migrating Collections of {$database->getId()} ({$database->getAttribute('name')})"); foreach ($this->documentsIterator($databaseTable) as $collection) { - $collectionTable = "{$databaseTable}_collection_{$collection->getInternalId()}"; + $collectionTable = "{$databaseTable}_collection_{$collection->getSequence()}"; $this->createPermissionsColumn($collectionTable); $this->migrateDateTimeAttribute($collectionTable, '_createdAt'); $this->migrateDateTimeAttribute($collectionTable, '_updatedAt'); @@ -277,7 +277,7 @@ class V15 extends Migration $this->removeWritePermissions($databaseTable); try { - $this->dbForProject->deleteAttribute("database_{$database->getInternalId()}", 'permission'); + $this->dbForProject->deleteAttribute("database_{$database->getSequence()}", 'permission'); } catch (\Throwable $th) { Console::warning("'permission' from {$databaseTable}: {$th->getMessage()}"); } @@ -293,7 +293,7 @@ class V15 extends Migration protected function removeWritePermissions(string $table): void { try { - $this->pdo->prepare("DELETE FROM `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}_perms` WHERE _type = 'write'")->execute(); + $this->pdo->prepare("DELETE FROM `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}_{$table}_perms` WHERE _type = 'write'")->execute(); } catch (\Throwable $th) { Console::warning("Remove 'write' permissions from {$table}: {$th->getMessage()}"); } @@ -309,7 +309,7 @@ class V15 extends Migration */ protected function getSQLColumnTypes(string $table): array { - $query = $this->pdo->prepare("SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '_{$this->project->getInternalId()}_{$table}' AND table_schema = '{$this->dbForProject->getDatabase()}'"); + $query = $this->pdo->prepare("SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '_{$this->project->getSequence()}_{$table}' AND table_schema = '{$this->dbForProject->getDatabase()}'"); $query->execute(); return array_reduce($query->fetchAll(), function (array $carry, array $item) { @@ -331,8 +331,8 @@ class V15 extends Migration if ($columns[$attribute] === 'int') { try { - $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` MODIFY {$attribute} VARCHAR(64)")->execute(); - $this->pdo->prepare("UPDATE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` SET {$attribute} = IF({$attribute} = 0, NULL, FROM_UNIXTIME({$attribute}))")->execute(); + $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}_{$table}` MODIFY {$attribute} VARCHAR(64)")->execute(); + $this->pdo->prepare("UPDATE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}_{$table}` SET {$attribute} = IF({$attribute} = 0, NULL, FROM_UNIXTIME({$attribute}))")->execute(); $columns[$attribute] = 'varchar'; } catch (\Throwable $th) { Console::warning($th->getMessage()); @@ -341,7 +341,7 @@ class V15 extends Migration if ($columns[$attribute] === 'varchar') { try { - $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` MODIFY {$attribute} DATETIME(3)")->execute(); + $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}_{$table}` MODIFY {$attribute} DATETIME(3)")->execute(); } catch (\Throwable $th) { Console::warning($th->getMessage()); } @@ -387,7 +387,7 @@ class V15 extends Migration if (!array_key_exists('_permissions', $columns)) { try { - $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` ADD `_permissions` MEDIUMTEXT DEFAULT NULL")->execute(); + $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}_{$table}` ADD `_permissions` MEDIUMTEXT DEFAULT NULL")->execute(); } catch (\Throwable $th) { Console::warning("Add '_permissions' column to '{$table}': {$th->getMessage()}"); } @@ -408,7 +408,7 @@ class V15 extends Migration { $table ??= $document->getCollection(); - $query = $this->pdo->prepare("SELECT * FROM `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}_perms` WHERE _document = '{$document->getId()}'"); + $query = $this->pdo->prepare("SELECT * FROM `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}_{$table}_perms` WHERE _document = '{$document->getId()}'"); $query->execute(); $results = $query->fetchAll(); $permissions = []; @@ -466,7 +466,7 @@ class V15 extends Migration Console::log("Migrating Collection \"{$id}\""); - $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); + $this->dbForProject->setNamespace("_{$this->project->getSequence()}"); switch ($id) { case '_metadata': @@ -746,7 +746,7 @@ class V15 extends Migration Permission::delete(Role::any()), ], 'functionId' => $function->getId(), - 'functionInternalId' => $function->getInternalId(), + 'functionInternalId' => $function->getSequence(), 'key' => (string) $key, 'value' => (string) $value, 'search' => implode(' ', [$variableId, $key, $function->getId()]) @@ -1470,9 +1470,9 @@ class V15 extends Migration $from = $this->pdo->quote($from); $to = $this->pdo->quote($to); - $this->pdo->prepare("UPDATE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_stats` SET metric = {$to} WHERE metric = {$from}")->execute(); + $this->pdo->prepare("UPDATE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}_stats` SET metric = {$to} WHERE metric = {$from}")->execute(); } catch (\Throwable $th) { - Console::warning("Migrating steps from {$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_stats:" . $th->getMessage()); + Console::warning("Migrating steps from {$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}_stats:" . $th->getMessage()); } } diff --git a/src/Appwrite/Migration/Version/V16.php b/src/Appwrite/Migration/Version/V16.php index 34407a0471..9d72af9563 100644 --- a/src/Appwrite/Migration/Version/V16.php +++ b/src/Appwrite/Migration/Version/V16.php @@ -45,7 +45,7 @@ class V16 extends Migration Console::log("Migrating Collection \"{$id}\""); - $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); + $this->dbForProject->setNamespace("_{$this->project->getSequence()}"); switch ($id) { case 'sessions': diff --git a/src/Appwrite/Migration/Version/V17.php b/src/Appwrite/Migration/Version/V17.php index f7cb08d6f4..fbbd4bfde0 100644 --- a/src/Appwrite/Migration/Version/V17.php +++ b/src/Appwrite/Migration/Version/V17.php @@ -44,7 +44,7 @@ class V17 extends Migration protected function migrateBuckets(): void { foreach ($this->documentsIterator('buckets') as $bucket) { - $id = "bucket_{$bucket->getInternalId()}"; + $id = "bucket_{$bucket->getSequence()}"; try { $this->dbForProject->updateAttribute($id, 'mimeType', Database::VAR_STRING, 255, true, false); @@ -67,7 +67,7 @@ class V17 extends Migration Console::log("Migrating Collection \"{$id}\""); - $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); + $this->dbForProject->setNamespace("_{$this->project->getSequence()}"); switch ($id) { case 'builds': diff --git a/src/Appwrite/Migration/Version/V18.php b/src/Appwrite/Migration/Version/V18.php index a5fae3789b..aa2ad35cca 100644 --- a/src/Appwrite/Migration/Version/V18.php +++ b/src/Appwrite/Migration/Version/V18.php @@ -26,7 +26,7 @@ class V18 extends Migration } Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); - $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); + $this->dbForProject->setNamespace("_{$this->project->getSequence()}"); $this->addDocumentSecurityToProject(); Console::info('Migrating Databases'); @@ -48,12 +48,12 @@ class V18 extends Migration private function migrateDatabases(): void { foreach ($this->documentsIterator('databases') as $database) { - $databaseTable = "database_{$database->getInternalId()}"; + $databaseTable = "database_{$database->getSequence()}"; Console::info("Migrating Collections of {$database->getId()} ({$database->getAttribute('name')})"); foreach ($this->documentsIterator($databaseTable) as $collection) { - $collectionTable = "{$databaseTable}_collection_{$collection->getInternalId()}"; + $collectionTable = "{$databaseTable}_collection_{$collection->getSequence()}"; foreach ($collection['attributes'] ?? [] as $attribute) { if ($attribute['type'] !== Database::VAR_FLOAT) { @@ -197,7 +197,7 @@ class V18 extends Migration * Set the bucket permission in the metadata table */ try { - $internalBucketId = "bucket_{$this->project->getInternalId()}"; + $internalBucketId = "bucket_{$this->project->getSequence()}"; $permissions = $document->getPermissions(); $fileSecurity = $document->getAttribute('fileSecurity', false); $this->dbForProject->updateCollection($internalBucketId, $permissions, $fileSecurity); @@ -224,8 +224,8 @@ class V18 extends Migration // Nonetheless, there's nothing else we can do here. break; } - $internalId = $user->getInternalId(); - $document->setAttribute('userId', $internalId); + $sequence = $user->getSequence(); + $document->setAttribute('userId', $sequence); $data = $document->getAttribute('data', []); $data['userId'] = $user->getId(); $document->setAttribute('data', $data); @@ -244,7 +244,7 @@ class V18 extends Migration /** * Create 'documentSecurity' column */ - $this->pdo->prepare("ALTER TABLE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}__metadata` ADD COLUMN IF NOT EXISTS documentSecurity TINYINT(1);")->execute(); + $this->pdo->prepare("ALTER TABLE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}__metadata` ADD COLUMN IF NOT EXISTS documentSecurity TINYINT(1);")->execute(); } catch (\Throwable $th) { Console::warning($th->getMessage()); } @@ -253,7 +253,7 @@ class V18 extends Migration /** * Set 'documentSecurity' column to 1 if NULL */ - $this->pdo->prepare("UPDATE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}__metadata` SET documentSecurity = 1 WHERE documentSecurity IS NULL")->execute(); + $this->pdo->prepare("UPDATE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}__metadata` SET documentSecurity = 1 WHERE documentSecurity IS NULL")->execute(); } catch (\Throwable $th) { Console::warning($th->getMessage()); } diff --git a/src/Appwrite/Migration/Version/V19.php b/src/Appwrite/Migration/Version/V19.php index cae27cc6ed..d4dda02d75 100644 --- a/src/Appwrite/Migration/Version/V19.php +++ b/src/Appwrite/Migration/Version/V19.php @@ -28,7 +28,7 @@ class V19 extends Migration } Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); - $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); + $this->dbForProject->setNamespace("_{$this->project->getSequence()}"); Console::info('Migrating Collections'); $this->migrateCollections(); @@ -100,7 +100,7 @@ class V19 extends Migration protected function migrateBuckets(): void { foreach ($this->documentsIterator('buckets') as $bucket) { - $id = "bucket_{$bucket->getInternalId()}"; + $id = "bucket_{$bucket->getSequence()}"; Console::log("Migrating Bucket {$id} {$bucket->getId()} ({$bucket->getAttribute('name')})"); try { @@ -121,7 +121,7 @@ class V19 extends Migration */ private function migrateCollections(): void { - $internalProjectId = $this->project->getInternalId(); + $internalProjectId = $this->project->getSequence(); $collectionType = match ($internalProjectId) { 'console' => 'console', default => 'projects', @@ -680,7 +680,7 @@ class V19 extends Migration case 'builds': $deploymentId = $document->getAttribute('deploymentId'); $deployment = $this->dbForProject->getDocument('deployments', $deploymentId); - $document->setAttribute('deploymentInternalId', $deployment->getInternalId()); + $document->setAttribute('deploymentInternalId', $deployment->getSequence()); $stdout = $document->getAttribute('stdout', ''); $stderr = $document->getAttribute('stderr', ''); @@ -692,12 +692,12 @@ class V19 extends Migration case 'deployments': $resourceId = $document->getAttribute('resourceId'); $function = $this->dbForProject->getDocument('functions', $resourceId); - $document->setAttribute('resourceInternalId', $function->getInternalId()); + $document->setAttribute('resourceInternalId', $function->getSequence()); $buildId = $document->getAttribute('buildId'); if (!empty($buildId)) { $build = $this->dbForProject->getDocument('builds', $buildId); - $document->setAttribute('buildInternalId', $build->getInternalId()); + $document->setAttribute('buildInternalId', $build->getSequence()); } $commands = $this->getFunctionCommands($function); @@ -707,11 +707,11 @@ class V19 extends Migration case 'executions': $functionId = $document->getAttribute('functionId'); $function = $this->dbForProject->getDocument('functions', $functionId); - $document->setAttribute('functionInternalId', $function->getInternalId()); + $document->setAttribute('functionInternalId', $function->getSequence()); $deploymentId = $document->getAttribute('deploymentId'); $deployment = $this->dbForProject->getDocument('deployments', $deploymentId); - $document->setAttribute('deploymentInternalId', $deployment->getInternalId()); + $document->setAttribute('deploymentInternalId', $deployment->getSequence()); break; case 'functions': $document->setAttribute('live', $document->getAttribute('live', true)); @@ -721,7 +721,7 @@ class V19 extends Migration if (!empty($deploymentId)) { $deployment = $this->dbForProject->getDocument('deployments', $deploymentId); - $document->setAttribute('deploymentInternalId', $deployment->getInternalId()); + $document->setAttribute('deploymentInternalId', $deployment->getSequence()); $document->setAttribute('entrypoint', $deployment->getAttribute('entrypoint')); } @@ -733,7 +733,7 @@ class V19 extends Migration 'region' => $project->getAttribute('region'), 'resourceType' => 'function', 'resourceId' => $document->getId(), - 'resourceInternalId' => $document->getInternalId(), + 'resourceInternalId' => $document->getSequence(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $this->project->getId(), 'schedule' => $document->getAttribute('schedule'), @@ -741,7 +741,7 @@ class V19 extends Migration ])); $document->setAttribute('scheduleId', $schedule->getId()); - $document->setAttribute('scheduleInternalId', $schedule->getInternalId()); + $document->setAttribute('scheduleInternalId', $schedule->getSequence()); } break; @@ -799,7 +799,7 @@ class V19 extends Migration */ public function forEachDocument(callable $callback): void { - $internalProjectId = $this->project->getInternalId(); + $internalProjectId = $this->project->getSequence(); $collections = match ($internalProjectId) { 'console' => $this->collections['console'], diff --git a/src/Appwrite/Migration/Version/V20.php b/src/Appwrite/Migration/Version/V20.php index 3a9bba6772..9ff041eb33 100644 --- a/src/Appwrite/Migration/Version/V20.php +++ b/src/Appwrite/Migration/Version/V20.php @@ -36,13 +36,13 @@ class V20 extends Migration } Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); - $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); + $this->dbForProject->setNamespace("_{$this->project->getSequence()}"); Console::info('Migrating Collections'); $this->migrateCollections(); // No need to migrate stats for console - if ($this->project->getInternalId() !== 'console') { + if ($this->project->getSequence() !== 'console') { $this->migrateUsageMetrics('project.$all.network.requests', 'network.requests'); $this->migrateUsageMetrics('project.$all.network.outbound', 'network.outbound'); $this->migrateUsageMetrics('project.$all.network.inbound', 'network.inbound'); @@ -71,7 +71,7 @@ class V20 extends Migration */ private function migrateCollections(): void { - $internalProjectId = $this->project->getInternalId(); + $internalProjectId = $this->project->getSequence(); $collectionType = match ($internalProjectId) { 'console' => 'console', default => 'projects', @@ -510,7 +510,7 @@ class V20 extends Migration Console::log("Migrating Functions usage stats of {$function->getId()} ({$function->getAttribute('name')})"); $functionId = $function->getId(); - $functionInternalId = $function->getInternalId(); + $functionInternalId = $function->getSequence(); $this->migrateUsageMetrics("deployment.$functionId.storage.size", "function.$functionInternalId.deployments.storage"); $this->migrateUsageMetrics("builds.$functionId.compute.total", "$functionInternalId.builds"); @@ -536,22 +536,22 @@ class V20 extends Migration foreach ($this->documentsIterator('databases') as $database) { Console::log("Migrating Collections of {$database->getId()} ({$database->getAttribute('name')})"); - $databaseTable = "database_{$database->getInternalId()}"; + $databaseTable = "database_{$database->getSequence()}"; // Database level $databaseId = $database->getId(); - $databaseInternalId = $database->getInternalId(); + $databaseInternalId = $database->getSequence(); $this->migrateUsageMetrics("collections.$databaseId.count.total", "$databaseInternalId.collections"); $this->migrateUsageMetrics("documents.$databaseId.count.total", "$databaseInternalId.documents"); foreach ($this->documentsIterator($databaseTable) as $collection) { - $collectionTable = "{$databaseTable}_collection_{$collection->getInternalId()}"; + $collectionTable = "{$databaseTable}_collection_{$collection->getSequence()}"; Console::log("Migrating Collections of {$collectionTable} {$collection->getId()} ({$collection->getAttribute('name')})"); // Collection level $collectionId = $collection->getId(); - $collectionInternalId = $collection->getInternalId(); + $collectionInternalId = $collection->getSequence(); $this->migrateUsageMetrics("documents.$databaseId/$collectionId.count.total", "$databaseInternalId.$collectionInternalId.documents"); } @@ -573,12 +573,12 @@ class V20 extends Migration $this->migrateUsageMetrics('files.$all.storage.size', 'files.storage'); foreach ($this->documentsIterator('buckets') as $bucket) { - $id = "bucket_{$bucket->getInternalId()}"; + $id = "bucket_{$bucket->getSequence()}"; Console::log("Migrating Bucket {$id} {$bucket->getId()} ({$bucket->getAttribute('name')})"); // Bucket level $bucketId = $bucket->getId(); - $bucketInternalId = $bucket->getInternalId(); + $bucketInternalId = $bucket->getSequence(); $this->migrateUsageMetrics("files.$bucketId.count.total", "$bucketInternalId.files"); $this->migrateUsageMetrics("files.$bucketId.storage.size", "$bucketInternalId.files.storage"); @@ -605,7 +605,7 @@ class V20 extends Migration $target = new Document([ '$id' => ID::unique(), 'userId' => $document->getId(), - 'userInternalId' => $document->getInternalId(), + 'userInternalId' => $document->getSequence(), 'providerType' => MESSAGE_TYPE_EMAIL, 'identifier' => $document->getAttribute('email'), ]); @@ -620,7 +620,7 @@ class V20 extends Migration $target = new Document([ '$id' => ID::unique(), 'userId' => $document->getId(), - 'userInternalId' => $document->getInternalId(), + 'userInternalId' => $document->getSequence(), 'providerType' => MESSAGE_TYPE_SMS, 'identifier' => $document->getAttribute('phone'), ]); diff --git a/src/Appwrite/Migration/Version/V21.php b/src/Appwrite/Migration/Version/V21.php index 38e8a8d513..891d2a92fe 100644 --- a/src/Appwrite/Migration/Version/V21.php +++ b/src/Appwrite/Migration/Version/V21.php @@ -29,12 +29,12 @@ class V21 extends Migration } Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); - $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); + $this->dbForProject->setNamespace("_{$this->project->getSequence()}"); Console::info('Migrating Collections'); $this->migrateCollections(); - if ($this->project->getInternalId() !== 'console') { + if ($this->project->getSequence() !== 'console') { Console::info('Migrating Buckets'); $this->migrateBuckets(); } @@ -51,7 +51,7 @@ class V21 extends Migration */ private function migrateCollections(): void { - $internalProjectId = $this->project->getInternalId(); + $internalProjectId = $this->project->getSequence(); $collectionType = match ($internalProjectId) { 'console' => 'console', default => 'projects', @@ -251,7 +251,7 @@ class V21 extends Migration private function migrateBuckets(): void { $this->dbForProject->forEach('buckets', function (Document $bucket) { - $bucketId = 'bucket_' . $bucket['$internalId']; + $bucketId = 'bucket_' . $bucket['$sequence']; Console::log("Migrating Bucket {$bucketId} {$bucket->getId()} ({$bucket->getAttribute('name')})"); diff --git a/src/Appwrite/Migration/Version/V22.php b/src/Appwrite/Migration/Version/V22.php index 50d5bdbb85..a99e07de59 100644 --- a/src/Appwrite/Migration/Version/V22.php +++ b/src/Appwrite/Migration/Version/V22.php @@ -49,7 +49,7 @@ class V22 extends Migration */ private function migrateCollections(): void { - $projectInternalId = $this->project->getInternalId(); + $projectInternalId = $this->project->getSequence(); if (empty($projectInternalId)) { throw new Exception('Project ID is null'); @@ -394,7 +394,7 @@ class V22 extends Migration 2. Fill "deploymentCreatedAt" with deployment's "$createdAt" --- Fetch latestDeployment using find() 3. Fill latestDeploymentId with latestDeployment's "$id" - 4. Fill latestDeploymentInternalId with latestDeployment's "$internalId" + 4. Fill latestDeploymentInternalId with latestDeployment's "$sequence" 5. Fill latestDeploymentCreatedAt with latestDeployment's "$createdAt" 6. Fill latestDeploymentStatus with latestDeployment's build's "status" */ @@ -433,7 +433,7 @@ class V22 extends Migration $document ->setAttribute('latestDeploymentId', $latestDeployment->getId()) - ->setAttribute('latestDeploymentInternalId', $latestDeployment->getInternalId()) + ->setAttribute('latestDeploymentInternalId', $latestDeployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $latestDeployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $latestBuild->getAttribute('status', $document->getAttribute('latestDeploymentStatus', ''))); break; @@ -497,7 +497,7 @@ class V22 extends Migration private function cleanCollections(): void { - $projectInternalId = $this->project->getInternalId(); + $projectInternalId = $this->project->getSequence(); $collectionType = match ($projectInternalId) { 'console' => 'console', diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php index 47529a142b..71c436b0a0 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -69,13 +69,13 @@ class Base extends Action Permission::delete(Role::any()), ], 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceType' => 'functions', 'entrypoint' => $entrypoint, 'buildCommands' => $function->getAttribute('commands', ''), 'type' => 'vcs', 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), + 'installationInternalId' => $installation->getSequence(), 'providerRepositoryId' => $providerRepositoryId, 'repositoryId' => $function->getAttribute('repositoryId', ''), 'repositoryInternalId' => $function->getAttribute('repositoryInternalId', ''), @@ -95,7 +95,7 @@ class Base extends Action $function = $function ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); @@ -166,7 +166,7 @@ class Base extends Action Permission::delete(Role::any()), ], 'resourceId' => $site->getId(), - 'resourceInternalId' => $site->getInternalId(), + 'resourceInternalId' => $site->getSequence(), 'resourceType' => 'sites', 'buildCommands' => implode(' && ', $commands), 'buildOutput' => $site->getAttribute('outputDirectory', ''), @@ -174,7 +174,7 @@ class Base extends Action 'fallbackFile' => $site->getAttribute('fallbackFile', ''), 'type' => 'vcs', 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), + 'installationInternalId' => $installation->getSequence(), 'providerRepositoryId' => $providerRepositoryId, 'repositoryId' => $site->getAttribute('repositoryId', ''), 'repositoryInternalId' => $site->getAttribute('repositoryInternalId', ''), @@ -194,7 +194,7 @@ class Base extends Action $site = $site ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('sites', $site->getId(), $site); @@ -209,15 +209,15 @@ class Base extends Action fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'domain' => $domain, 'trigger' => 'deployment', 'type' => 'deployment', 'deploymentId' => $deployment->getId(), - 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->getSequence(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $site->getId(), - 'deploymentResourceInternalId' => $site->getInternalId(), + 'deploymentResourceInternalId' => $site->getSequence(), 'deploymentVcsProviderBranch' => $providerBranch, 'status' => 'verified', 'certificateId' => '', @@ -244,7 +244,7 @@ class Base extends Action do { $queries = \array_merge([ Query::limit($limit), - Query::equal("projectInternalId", [$project->getInternalId()]) + Query::equal("projectInternalId", [$project->getSequence()]) ], $queries); if ($cursor !== null) { diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php index cda6dc38bf..ad3ea18b98 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php @@ -237,7 +237,7 @@ class Create extends Action Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceId' => $function->getId(), 'resourceType' => 'functions', 'entrypoint' => $entrypoint, @@ -252,7 +252,7 @@ class Create extends Action $function = $function ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); @@ -274,7 +274,7 @@ class Create extends Action Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceId' => $function->getId(), 'resourceType' => 'functions', 'entrypoint' => $entrypoint, @@ -291,7 +291,7 @@ class Create extends Action $function = $function ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php index 84878055d8..912e12bdc1 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php @@ -101,7 +101,7 @@ class Delete extends Action if ($function->getAttribute('latestDeploymentId') === $deployment->getId()) { $latestDeployment = $dbForProject->findOne('deployments', [ Query::equal('resourceType', ['functions']), - Query::equal('resourceInternalId', [$function->getInternalId()]), + Query::equal('resourceInternalId', [$function->getSequence()]), Query::orderDesc('$createdAt'), ]); $function = $dbForProject->updateDocument( @@ -109,7 +109,7 @@ class Delete extends Action $function->getId(), $function ->setAttribute('latestDeploymentCreatedAt', $latestDeployment->isEmpty() ? '' : $latestDeployment->getCreatedAt()) - ->setAttribute('latestDeploymentInternalId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getInternalId()) + ->setAttribute('latestDeploymentInternalId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getSequence()) ->setAttribute('latestDeploymentId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getId()) ->setAttribute('latestDeploymentStatus', $latestDeployment->isEmpty() ? '' : $latestDeployment->getAttribute('status', '')) ); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php index 8f739dd37f..0a07440dff 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php @@ -96,9 +96,9 @@ class Create extends Action $destination = $deviceForFunctions->getPath($deploymentId . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION)); $deviceForFunctions->transfer($path, $destination, $deviceForFunctions); - $deployment->removeAttribute('$internalId'); + $deployment->removeAttribute('$sequence'); $deployment = $dbForProject->createDocument('deployments', $deployment->setAttributes([ - '$internalId' => '', + '$sequence' => '', '$id' => $deploymentId, 'sourcePath' => $destination, 'totalSize' => $deployment->getAttribute('sourceSize', 0), @@ -115,7 +115,7 @@ class Create extends Action $function = $function ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php index c5436d1d05..4c924a64d1 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php @@ -97,7 +97,7 @@ class Update extends Action 'status' => 'canceled' ])); - if ($deployment->getInternalId() === $function->getAttribute('latestDeploymentInternalId', '')) { + if ($deployment->getSequence() === $function->getAttribute('latestDeploymentInternalId', '')) { $function = $function->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php index 55230bd4a5..f1bd4b71e4 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php @@ -142,7 +142,7 @@ class Create extends Base Permission::delete(Role::any()), ], 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceType' => 'functions', 'entrypoint' => $function->getAttribute('entrypoint', ''), 'buildCommands' => $function->getAttribute('commands', ''), @@ -152,7 +152,7 @@ class Create extends Base $function = $function ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php index 38f1f38e89..2ffcfc5d11 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php @@ -84,7 +84,7 @@ class XList extends Action } // Set resource queries - $queries[] = Query::equal('resourceInternalId', [$function->getInternalId()]); + $queries[] = Query::equal('resourceInternalId', [$function->getSequence()]); $queries[] = Query::equal('resourceType', ['functions']); /** diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php index fd1b2076a8..0aec31e5fd 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -253,10 +253,10 @@ class Create extends Base $execution = new Document([ '$id' => $executionId, '$permissions' => !$user->isEmpty() ? [Permission::read(Role::user($user->getId()))] : [], - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceId' => $function->getId(), 'resourceType' => 'functions', - 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->getSequence(), 'deploymentId' => $deployment->getId(), 'trigger' => (!is_null($scheduledAt)) ? 'schedule' : 'http', 'status' => $status, // waiting / processing / completed / failed / scheduled @@ -305,7 +305,7 @@ class Create extends Base 'region' => $project->getAttribute('region'), 'resourceType' => ScheduleExecutions::getSupportedResource(), 'resourceId' => $execution->getId(), - 'resourceInternalId' => $execution->getInternalId(), + 'resourceInternalId' => $execution->getSequence(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -315,7 +315,7 @@ class Create extends Base $execution = $execution ->setAttribute('scheduleId', $schedule->getId()) - ->setAttribute('scheduleInternalId', $schedule->getInternalId()) + ->setAttribute('scheduleInternalId', $schedule->getSequence()) ->setAttribute('scheduledAt', $scheduledAt); $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); @@ -439,13 +439,13 @@ class Create extends Base $queueForStatsUsage ->addMetric(METRIC_EXECUTIONS, 1) ->addMetric(str_replace(['{resourceType}'], [RESOURCE_TYPE_FUNCTIONS], METRIC_RESOURCE_TYPE_EXECUTIONS), 1) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), 1) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), 1) ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000)) // per project ->addMetric(str_replace(['{resourceType}'], [RESOURCE_TYPE_FUNCTIONS], METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function ->addMetric(METRIC_EXECUTIONS_MB_SECONDS, (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ->addMetric(str_replace(['{resourceType}'], [RESOURCE_TYPE_FUNCTIONS], METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ; $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php index cd85b5e534..8a3d5f2a49 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php @@ -84,7 +84,7 @@ class Delete extends Base throw new Exception(Exception::EXECUTION_NOT_FOUND); } - if ($execution->getAttribute('resourceType') !== 'functions' && $execution->getAttribute('resourceInternalId') !== $function->getInternalId()) { + if ($execution->getAttribute('resourceType') !== 'functions' && $execution->getAttribute('resourceInternalId') !== $function->getSequence()) { throw new Exception(Exception::EXECUTION_NOT_FOUND); } $status = $execution->getAttribute('status'); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php index 892ce30f47..659682ab55 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php @@ -72,7 +72,7 @@ class Get extends Base $execution = $dbForProject->getDocument('executions', $executionId); - if ($execution->getAttribute('resourceType') !== 'functions' || $execution->getAttribute('resourceInternalId') !== $function->getInternalId()) { + if ($execution->getAttribute('resourceType') !== 'functions' || $execution->getAttribute('resourceInternalId') !== $function->getSequence()) { throw new Exception(Exception::EXECUTION_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php index a31e95b1c8..91683c915b 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php @@ -83,7 +83,7 @@ class XList extends Base } // Set internal queries - $queries[] = Query::equal('resourceInternalId', [$function->getInternalId()]); + $queries[] = Query::equal('resourceInternalId', [$function->getSequence()]); $queries[] = Query::equal('resourceType', ['functions']); /** diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php index fd8da657eb..c644c681d8 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php @@ -222,7 +222,7 @@ class Create extends Base 'search' => implode(' ', [$functionId, $name, $runtime]), 'version' => 'v5', 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), + 'installationInternalId' => $installation->getSequence(), 'providerRepositoryId' => $providerRepositoryId, 'repositoryId' => '', 'repositoryInternalId' => '', @@ -237,7 +237,7 @@ class Create extends Base 'region' => $project->getAttribute('region'), 'resourceType' => 'function', 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $function->getAttribute('schedule'), @@ -246,7 +246,7 @@ class Create extends Base ); $function->setAttribute('scheduleId', $schedule->getId()); - $function->setAttribute('scheduleInternalId', $schedule->getInternalId()); + $function->setAttribute('scheduleInternalId', $schedule->getSequence()); // Git connect logic if (!empty($providerRepositoryId)) { @@ -262,18 +262,18 @@ class Create extends Base Permission::delete(Role::team(ID::custom($teamId), 'developer')), ], 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), + 'installationInternalId' => $installation->getSequence(), 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'providerRepositoryId' => $providerRepositoryId, 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceType' => 'function', 'providerPullRequestIds' => [] ])); $function->setAttribute('repositoryId', $repository->getId()); - $function->setAttribute('repositoryInternalId', $repository->getInternalId()); + $function->setAttribute('repositoryInternalId', $repository->getSequence()); } $function = $dbForProject->updateDocument('functions', $function->getId(), $function); @@ -316,7 +316,7 @@ class Create extends Base $function = $function ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); @@ -331,7 +331,7 @@ class Create extends Base Permission::delete(Role::any()), ], 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceType' => 'functions', 'entrypoint' => $function->getAttribute('entrypoint', ''), 'buildCommands' => $function->getAttribute('commands', ''), @@ -341,7 +341,7 @@ class Create extends Base $function = $function ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); @@ -364,16 +364,16 @@ class Create extends Base fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'domain' => $domain, 'status' => 'verified', 'type' => 'deployment', 'trigger' => 'manual', 'deploymentId' => !isset($deployment) || $deployment->isEmpty() ? '' : $deployment->getId(), - 'deploymentInternalId' => !isset($deployment) || $deployment->isEmpty() ? '' : $deployment->getInternalId(), + 'deploymentInternalId' => !isset($deployment) || $deployment->isEmpty() ? '' : $deployment->getSequence(), 'deploymentResourceType' => 'function', 'deploymentResourceId' => $function->getId(), - 'deploymentResourceInternalId' => $function->getInternalId(), + 'deploymentResourceInternalId' => $function->getSequence(), 'deploymentVcsProviderBranch' => '', 'certificateId' => '', 'search' => implode(' ', [$ruleId, $domain]), diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php index 6de71cfae6..1f3e39dee1 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -92,7 +92,7 @@ class Update extends Base $oldDeploymentInternalId = $function->getAttribute('deploymentInternalId', ''); $function = $dbForProject->updateDocument('functions', $function->getId(), new Document(array_merge($function->getArrayCopy(), [ - 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->getSequence(), 'deploymentId' => $deployment->getId(), 'deploymentCreatedAt' => $deployment->getCreatedAt(), ]))); @@ -109,7 +109,7 @@ class Update extends Base Query::equal('trigger', 'manual'), Query::equal("type", ["deployment"]), Query::equal("deploymentResourceType", ["function"]), - Query::equal("deploymentResourceInternalId", [$function->getInternalId()]), + Query::equal("deploymentResourceInternalId", [$function->getSequence()]), ]; if (empty($oldDeploymentInternalId)) { @@ -121,7 +121,7 @@ class Update extends Base $this->listRules($project, $queries, $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) - ->setAttribute('deploymentInternalId', $deployment->getInternalId()); + ->setAttribute('deploymentInternalId', $deployment->getSequence()); $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); }); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php index a19ec1e278..2bfe8b1344 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php @@ -175,8 +175,8 @@ class Update extends Base // Git disconnect logic. Disconnecting only when providerRepositoryId is empty, allowing for continue updates without disconnecting git if ($isConnected && ($providerRepositoryId !== null && empty($providerRepositoryId))) { $repositories = $dbForPlatform->find('repositories', [ - Query::equal('projectInternalId', [$project->getInternalId()]), - Query::equal('resourceInternalId', [$function->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('resourceInternalId', [$function->getSequence()]), Query::equal('resourceType', ['function']), Query::limit(100), ]); @@ -208,18 +208,18 @@ class Update extends Base Permission::delete(Role::team(ID::custom($teamId), 'developer')), ], 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), + 'installationInternalId' => $installation->getSequence(), 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'providerRepositoryId' => $providerRepositoryId, 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceType' => 'function', 'providerPullRequestIds' => [] ])); $repositoryId = $repository->getId(); - $repositoryInternalId = $repository->getInternalId(); + $repositoryInternalId = $repository->getSequence(); } $live = true; @@ -260,7 +260,7 @@ class Update extends Base 'commands' => $commands, 'scopes' => $scopes, 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), + 'installationInternalId' => $installation->getSequence(), 'providerRepositoryId' => $providerRepositoryId, 'repositoryId' => $repositoryId, 'repositoryInternalId' => $repositoryInternalId, diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php index e0d659c9ba..947da4cd37 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php @@ -70,17 +70,17 @@ class Get extends Base $stats = $usage = []; $days = $periods[$range]; $metrics = [ - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php index 9300524c64..ee892fe1ed 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php @@ -96,7 +96,7 @@ class Create extends Base Permission::delete(Role::team(ID::custom($teamId), 'owner')), Permission::delete(Role::team(ID::custom($teamId), 'developer')), ], - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceId' => $function->getId(), 'resourceType' => 'function', 'key' => $key, diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php index 3d6bfebcb9..dda1f97f6b 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php @@ -74,7 +74,7 @@ class Delete extends Base } $variable = $dbForProject->getDocument('variables', $variableId); - if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $function->getInternalId() || $variable->getAttribute('resourceType') !== 'function') { + if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $function->getSequence() || $variable->getAttribute('resourceType') !== 'function') { throw new Exception(Exception::VARIABLE_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Get.php index 70cc66219a..98119c4a66 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Get.php @@ -68,7 +68,7 @@ class Get extends Base if ( $variable === false || $variable->isEmpty() || - $variable->getAttribute('resourceInternalId') !== $function->getInternalId() || + $variable->getAttribute('resourceInternalId') !== $function->getSequence() || $variable->getAttribute('resourceType') !== 'function' ) { throw new Exception(Exception::VARIABLE_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php index 4102022267..7a6acf88e3 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php @@ -81,7 +81,7 @@ class Update extends Base } $variable = $dbForProject->getDocument('variables', $variableId); - if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $function->getInternalId() || $variable->getAttribute('resourceType') !== 'function') { + if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $function->getSequence() || $variable->getAttribute('resourceType') !== 'function') { throw new Exception(Exception::VARIABLE_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 6ff2161c1a..e43f92a24a 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -273,7 +273,7 @@ class Builds extends Action $deployment->setAttribute('status', 'processing'); $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); - if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) { + if ($deployment->getSequence() === $resource->getAttribute('latestDeploymentInternalId', '')) { $resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource); } @@ -523,7 +523,7 @@ class Builds extends Action $deployment->setAttribute('status', 'building'); $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); - if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) { + if ($deployment->getSequence() === $resource->getAttribute('latestDeploymentInternalId', '')) { $resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource); } @@ -886,9 +886,9 @@ class Builds extends Action if ($resource->getCollection() === 'sites') { try { $rule = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ - Query::equal("projectInternalId", [$project->getInternalId()]), + Query::equal("projectInternalId", [$project->getSequence()]), Query::equal("type", ["deployment"]), - Query::equal('deploymentInternalId', [$deployment->getInternalId()]), + Query::equal('deploymentInternalId', [$deployment->getSequence()]), ])); if ($rule->isEmpty()) { @@ -927,9 +927,9 @@ class Builds extends Action str_replace(["{resourceType}"], [RESOURCE_TYPE_SITES], METRIC_RESOURCE_TYPE_EXECUTIONS), str_replace(["{resourceType}"], [RESOURCE_TYPE_SITES], METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE), str_replace(["{resourceType}"], [RESOURCE_TYPE_SITES], METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS), - str_replace(["{resourceType}", "{resourceInternalId}"], [RESOURCE_TYPE_SITES, $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), - str_replace(["{resourceType}", "{resourceInternalId}"], [RESOURCE_TYPE_SITES, $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), - str_replace(["{resourceType}", "{resourceInternalId}"], [RESOURCE_TYPE_SITES, $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), + str_replace(["{resourceType}", "{resourceInternalId}"], [RESOURCE_TYPE_SITES, $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), + str_replace(["{resourceType}", "{resourceInternalId}"], [RESOURCE_TYPE_SITES, $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), + str_replace(["{resourceType}", "{resourceInternalId}"], [RESOURCE_TYPE_SITES, $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), ], 'bannerDisabled' => true, 'projectCheckDisabled' => true, @@ -999,7 +999,7 @@ class Builds extends Action Permission::read(Role::team(ID::custom($teamId))), ], 'bucketId' => $bucket->getId(), - 'bucketInternalId' => $bucket->getInternalId(), + 'bucketInternalId' => $bucket->getSequence(), 'name' => $fileName, 'path' => $path, 'signature' => $deviceForFiles->getFileHash($path), @@ -1018,7 +1018,7 @@ class Builds extends Action 'metadata' => ['content_type' => $deviceForFiles->getFileMimeType($path)], ]); - Authorization::skip(fn () => $dbForPlatform->createDocument('bucket_' . $bucket->getInternalId(), $file)); + Authorization::skip(fn () => $dbForPlatform->createDocument('bucket_' . $bucket->getSequence(), $file)); $deployment->setAttribute($key, $fileId); } @@ -1054,7 +1054,7 @@ class Builds extends Action $deployment->setAttribute('status', 'ready'); $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment); - if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) { + if ($deployment->getSequence() === $resource->getAttribute('latestDeploymentInternalId', '')) { $resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource); } @@ -1077,14 +1077,14 @@ class Builds extends Action $oldDeploymentInternalId = $resource->getAttribute('deploymentInternalId', ''); $resource->setAttribute('deploymentId', $deployment->getId()); - $resource->setAttribute('deploymentInternalId', $deployment->getInternalId()); + $resource->setAttribute('deploymentInternalId', $deployment->getSequence()); $resource->setAttribute('deploymentCreatedAt', $deployment->getCreatedAt()); $resource = $dbForProject->updateDocument('functions', $resource->getId(), $resource); $queries = [ - Query::equal("projectInternalId", [$project->getInternalId()]), + Query::equal("projectInternalId", [$project->getSequence()]), Query::equal("type", ["deployment"]), - Query::equal("deploymentResourceInternalId", [$resource->getInternalId()]), + Query::equal("deploymentResourceInternalId", [$resource->getSequence()]), Query::equal('deploymentResourceType', ['function']), Query::equal('trigger', ['manual']), ]; @@ -1100,7 +1100,7 @@ class Builds extends Action $rulesUpdated = true; $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) - ->setAttribute('deploymentInternalId', $deployment->getInternalId()); + ->setAttribute('deploymentInternalId', $deployment->getSequence()); $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); }); break; @@ -1108,15 +1108,15 @@ class Builds extends Action $oldDeploymentInternalId = $resource->getAttribute('deploymentInternalId', ''); $resource->setAttribute('deploymentId', $deployment->getId()); - $resource->setAttribute('deploymentInternalId', $deployment->getInternalId()); + $resource->setAttribute('deploymentInternalId', $deployment->getSequence()); $resource->setAttribute('deploymentScreenshotDark', $deployment->getAttribute('screenshotDark', '')); $resource->setAttribute('deploymentScreenshotLight', $deployment->getAttribute('screenshotLight', '')); $resource->setAttribute('deploymentCreatedAt', $deployment->getCreatedAt()); $resource = $dbForProject->updateDocument('sites', $resource->getId(), $resource); $queries = [ - Query::equal("projectInternalId", [$project->getInternalId()]), + Query::equal("projectInternalId", [$project->getSequence()]), Query::equal("type", ["deployment"]), - Query::equal("deploymentResourceInternalId", [$resource->getInternalId()]), + Query::equal("deploymentResourceInternalId", [$resource->getSequence()]), Query::equal('deploymentResourceType', ['site']), Query::equal('trigger', ['manual']), ]; @@ -1130,7 +1130,7 @@ class Builds extends Action $this->listRules($project, $queries, $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) - ->setAttribute('deploymentInternalId', $deployment->getInternalId()); + ->setAttribute('deploymentInternalId', $deployment->getSequence()); $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); }); @@ -1150,15 +1150,15 @@ class Builds extends Action $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'domain' => $domain, 'type' => 'deployment', 'trigger' => 'deployment', 'deploymentId' => $deployment->getId(), - 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->getSequence(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $deployment->getId(), - 'deploymentResourceInternalId' => $deployment->getInternalId(), + 'deploymentResourceInternalId' => $deployment->getSequence(), 'deploymentVcsProviderBranch' => $branchName, 'status' => 'verified', 'certificateId' => '', @@ -1170,21 +1170,21 @@ class Builds extends Action $rule = $dbForPlatform->getDocument('rules', $ruleId); $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) - ->setAttribute('deploymentInternalId', $deployment->getInternalId()); + ->setAttribute('deploymentInternalId', $deployment->getSequence()); $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); } $this->listRules($project, [ - Query::equal("projectInternalId", [$project->getInternalId()]), + Query::equal("projectInternalId", [$project->getSequence()]), Query::equal("type", ["deployment"]), - Query::equal("deploymentResourceInternalId", [$resource->getInternalId()]), + Query::equal("deploymentResourceInternalId", [$resource->getSequence()]), Query::equal('deploymentResourceType', ['site']), Query::equal("deploymentVcsProviderBranch", [$branchName]), Query::equal("trigger", ['manual']), ], $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) - ->setAttribute('deploymentInternalId', $deployment->getInternalId()); + ->setAttribute('deploymentInternalId', $deployment->getSequence()); $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); }); } @@ -1249,7 +1249,7 @@ class Builds extends Action $deployment->setAttribute('buildLogs', $message); $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment); - if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) { + if ($deployment->getSequence() === $resource->getAttribute('latestDeploymentInternalId', '')) { $resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource); } @@ -1284,8 +1284,8 @@ class Builds extends Action ->addMetric(METRIC_BUILDS_COMPUTE_SUCCESS, (int)$deployment->getAttribute('buildDuration', 0) * 1000) ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_SUCCESS), 1) // per function ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_COMPUTE_SUCCESS), (int)$deployment->getAttribute('buildDuration', 0) * 1000) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS), 1) // per function - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_SUCCESS), (int)$deployment->getAttribute('buildDuration', 0) * 1000); + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS), 1) // per function + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_SUCCESS), (int)$deployment->getAttribute('buildDuration', 0) * 1000); break; case 'failed': $queue @@ -1293,8 +1293,8 @@ class Builds extends Action ->addMetric(METRIC_BUILDS_COMPUTE_FAILED, (int)$deployment->getAttribute('buildDuration', 0) * 1000) ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_FAILED), 1) // per function ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_COMPUTE_FAILED), (int)$deployment->getAttribute('buildDuration', 0) * 1000) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), 1) // per function - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_FAILED), (int)$deployment->getAttribute('buildDuration', 0) * 1000); + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), 1) // per function + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_FAILED), (int)$deployment->getAttribute('buildDuration', 0) * 1000); break; } @@ -1307,10 +1307,10 @@ class Builds extends Action ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_STORAGE), $deployment->getAttribute('buildSize', 0)) ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_COMPUTE), (int)$deployment->getAttribute('buildDuration', 0) * 1000) ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $deployment->getAttribute('buildDuration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS), 1) // per function - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $deployment->getAttribute('buildSize', 0)) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE), (int)$deployment->getAttribute('buildDuration', 0) * 1000) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $deployment->getAttribute('buildDuration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS), 1) // per function + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $deployment->getAttribute('buildSize', 0)) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE), (int)$deployment->getAttribute('buildDuration', 0) * 1000) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $deployment->getAttribute('buildDuration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ->setProject($project) ->trigger(); } @@ -1468,9 +1468,9 @@ class Builds extends Action }; $rule = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ - Query::equal("projectInternalId", [$project->getInternalId()]), + Query::equal("projectInternalId", [$project->getSequence()]), Query::equal("type", ["deployment"]), - Query::equal("deploymentInternalId", [$deployment->getInternalId()]), + Query::equal("deploymentInternalId", [$deployment->getSequence()]), ])); $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; @@ -1498,7 +1498,7 @@ class Builds extends Action do { $queries = \array_merge([ Query::limit($limit), - Query::equal("projectInternalId", [$project->getInternalId()]) + Query::equal("projectInternalId", [$project->getSequence()]) ], $queries); if ($cursor !== null) { diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Create.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Create.php index 43f7d4ac02..54ff189c20 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Create.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Create.php @@ -76,7 +76,7 @@ class Create extends Action Permission::update(Role::user($user->getId())), Permission::delete(Role::user($user->getId())), ], - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'projectId' => $project->getId(), 'name' => $name, 'expire' => $expire, diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Delete.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Delete.php index f6cb966f50..eac42be5f0 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Delete.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Delete.php @@ -63,7 +63,7 @@ class Delete extends Action $key = $dbForPlatform->getDocument('devKeys', $keyId); - if ($key === false || $key->isEmpty() || $key->getAttribute('projectInternalId') !== $project->getInternalId()) { + if ($key === false || $key->isEmpty() || $key->getAttribute('projectInternalId') !== $project->getSequence()) { throw new Exception(Exception::KEY_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Get.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Get.php index bd472b26e7..6255976de4 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Get.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Get.php @@ -63,7 +63,7 @@ class Get extends Action $key = $dbForPlatform->getDocument('devKeys', $keyId); - if ($key === false || $key->isEmpty() || $key->getAttribute('projectInternalId') !== $project->getInternalId()) { + if ($key === false || $key->isEmpty() || $key->getAttribute('projectInternalId') !== $project->getSequence()) { throw new Exception(Exception::KEY_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Update.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Update.php index d5e6839174..33b91eb0b6 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Update.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Update.php @@ -65,7 +65,7 @@ class Update extends Action $key = $dbForPlatform->getDocument('devKeys', $keyId); - if ($key === false || $key->isEmpty() || $key->getAttribute('projectInternalId') !== $project->getInternalId()) { + if ($key === false || $key->isEmpty() || $key->getAttribute('projectInternalId') !== $project->getSequence()) { throw new Exception(Exception::KEY_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/XList.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/XList.php index 864531d32d..73e79a783a 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/XList.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/XList.php @@ -71,7 +71,7 @@ class XList extends Action throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $queries[] = Query::equal('projectInternalId', [$project->getInternalId()]); + $queries[] = Query::equal('projectInternalId', [$project->getSequence()]); $keys = $dbForPlatform->find('devKeys', $queries); diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php index e4d0d2899f..33eb5313a0 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php @@ -153,7 +153,7 @@ class Create extends Action $rule = new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'domain' => $domain->get(), 'status' => $status, 'type' => 'api', diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php index 6c5a87a68d..0b68b80aa3 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php @@ -165,16 +165,16 @@ class Create extends Action $rule = new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'domain' => $domain->get(), 'status' => $status, 'type' => 'deployment', 'trigger' => 'manual', 'deploymentId' => $deployment->isEmpty() ? '' : $deployment->getId(), - 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getSequence(), 'deploymentResourceType' => 'function', 'deploymentResourceId' => $function->getId(), - 'deploymentResourceInternalId' => $function->getInternalId(), + 'deploymentResourceInternalId' => $function->getSequence(), 'deploymentVcsProviderBranch' => $branch, 'certificateId' => '', 'search' => implode(' ', [$ruleId, $domain->get(), $branch]), diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php index d0c9dbbbe3..ed84b8498b 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php @@ -157,7 +157,7 @@ class Create extends Action $rule = new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'domain' => $domain->get(), 'status' => $status, 'type' => 'redirect', diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php index 894c954a32..7c2a640cdf 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php @@ -165,16 +165,16 @@ class Create extends Action $rule = new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'domain' => $domain->get(), 'status' => $status, 'type' => 'deployment', 'trigger' => 'manual', 'deploymentId' => $deployment->isEmpty() ? '' : $deployment->getId(), - 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getSequence(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $site->getId(), - 'deploymentResourceInternalId' => $site->getInternalId(), + 'deploymentResourceInternalId' => $site->getSequence(), 'deploymentVcsProviderBranch' => $branch, 'certificateId' => '', 'search' => implode(' ', [$ruleId, $domain->get(), $branch]), diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php index afa1dba7d8..68916a716f 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php @@ -246,7 +246,7 @@ class Create extends Action Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'resourceInternalId' => $site->getInternalId(), + 'resourceInternalId' => $site->getSequence(), 'resourceId' => $site->getId(), 'resourceType' => 'sites', 'buildCommands' => \implode(' && ', $commands), @@ -263,7 +263,7 @@ class Create extends Action $site = $site ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('sites', $site->getId(), $site); @@ -278,15 +278,15 @@ class Create extends Action fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'domain' => $domain, 'type' => 'deployment', 'trigger' => 'deployment', 'deploymentId' => $deployment->isEmpty() ? '' : $deployment->getId(), - 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getSequence(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $site->getId(), - 'deploymentResourceInternalId' => $site->getInternalId(), + 'deploymentResourceInternalId' => $site->getSequence(), 'status' => 'verified', 'certificateId' => '', 'search' => implode(' ', [$ruleId, $domain]), @@ -312,7 +312,7 @@ class Create extends Action Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'resourceInternalId' => $site->getInternalId(), + 'resourceInternalId' => $site->getSequence(), 'resourceId' => $site->getId(), 'resourceType' => 'sites', 'buildCommands' => \implode(' && ', $commands), @@ -331,7 +331,7 @@ class Create extends Action $site = $site ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('sites', $site->getId(), $site); @@ -343,7 +343,7 @@ class Create extends Action fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'domain' => $domain, 'type' => 'deployment', 'trigger' => 'deployment', diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php index 27db10c484..8717d04fc2 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php @@ -101,7 +101,7 @@ class Delete extends Action if ($site->getAttribute('latestDeploymentId') === $deployment->getId()) { $latestDeployment = $dbForProject->findOne('deployments', [ Query::equal('resourceType', ['sites']), - Query::equal('resourceInternalId', [$site->getInternalId()]), + Query::equal('resourceInternalId', [$site->getSequence()]), Query::orderDesc('$createdAt'), ]); $site = $dbForProject->updateDocument( @@ -109,7 +109,7 @@ class Delete extends Action $site->getId(), $site ->setAttribute('latestDeploymentCreatedAt', $latestDeployment->isEmpty() ? '' : $latestDeployment->getCreatedAt()) - ->setAttribute('latestDeploymentInternalId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getInternalId()) + ->setAttribute('latestDeploymentInternalId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getSequence()) ->setAttribute('latestDeploymentId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getId()) ->setAttribute('latestDeploymentStatus', $latestDeployment->isEmpty() ? '' : $latestDeployment->getAttribute('status', '')) ); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php index bff0735328..739c701a2e 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php @@ -110,9 +110,9 @@ class Create extends Action $commands[] = $site->getAttribute('buildCommand', ''); } - $deployment->removeAttribute('$internalId'); + $deployment->removeAttribute('$sequence'); $deployment = $dbForProject->createDocument('deployments', $deployment->setAttributes([ - '$internalId' => '', + '$sequence' => '', '$id' => $deploymentId, 'sourcePath' => $destination, 'totalSize' => $deployment->getAttribute('sourceSize', 0), @@ -134,7 +134,7 @@ class Create extends Action $site = $site ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('sites', $site->getId(), $site); @@ -150,15 +150,15 @@ class Create extends Action fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'domain' => $domain, 'type' => 'deployment', 'trigger' => 'deployment', 'deploymentId' => $deployment->isEmpty() ? '' : $deployment->getId(), - 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getSequence(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $site->getId(), - 'deploymentResourceInternalId' => $site->getInternalId(), + 'deploymentResourceInternalId' => $site->getSequence(), 'status' => 'verified', 'certificateId' => '', 'owner' => 'Appwrite', diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php index 2c6da43893..046ddd1ac8 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php @@ -95,7 +95,7 @@ class Update extends Action 'status' => 'canceled' ])); - if ($deployment->getInternalId() === $site->getAttribute('latestDeploymentInternalId', '')) { + if ($deployment->getSequence() === $site->getAttribute('latestDeploymentInternalId', '')) { $site = $site->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('sites', $site->getId(), $site); } diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php index 5b29521ce5..5de688fbf8 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php @@ -153,7 +153,7 @@ class Create extends Base Permission::delete(Role::any()), ], 'resourceId' => $site->getId(), - 'resourceInternalId' => $site->getInternalId(), + 'resourceInternalId' => $site->getSequence(), 'resourceType' => 'sites', 'buildCommands' => \implode(' && ', $commands), 'buildOutput' => $site->getAttribute('outputDirectory', ''), @@ -165,7 +165,7 @@ class Create extends Base $site = $site ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) + ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('sites', $site->getId(), $site); @@ -180,15 +180,15 @@ class Create extends Base fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'domain' => $domain, 'type' => 'deployment', 'trigger' => 'deployment', 'deploymentId' => $deployment->isEmpty() ? '' : $deployment->getId(), - 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getSequence(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $site->getId(), - 'deploymentResourceInternalId' => $site->getInternalId(), + 'deploymentResourceInternalId' => $site->getSequence(), 'status' => 'verified', 'certificateId' => '', 'owner' => 'Appwrite', diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php index d7cfc1d3ad..306f756d87 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php @@ -79,7 +79,7 @@ class XList extends Action } // Set resource queries - $queries[] = Query::equal('resourceInternalId', [$site->getInternalId()]); + $queries[] = Query::equal('resourceInternalId', [$site->getSequence()]); $queries[] = Query::equal('resourceType', ['sites']); /** diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Logs/Delete.php b/src/Appwrite/Platform/Modules/Sites/Http/Logs/Delete.php index a411cee91f..2d87321086 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Logs/Delete.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Logs/Delete.php @@ -71,7 +71,7 @@ class Delete extends Base throw new Exception(Exception::LOG_NOT_FOUND); } - if ($log->getAttribute('resourceType') !== 'sites' && $log->getAttribute('resourceInternalId') !== $site->getInternalId()) { + if ($log->getAttribute('resourceType') !== 'sites' && $log->getAttribute('resourceInternalId') !== $site->getSequence()) { throw new Exception(Exception::LOG_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Logs/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Logs/Get.php index 3d1ace2d20..2ef7d75539 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Logs/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Logs/Get.php @@ -63,7 +63,7 @@ class Get extends Base $log = $dbForProject->getDocument('executions', $logId); - if ($log->getAttribute('resourceType') !== 'sites' && $log->getAttribute('resourceInternalId') !== $site->getInternalId()) { + if ($log->getAttribute('resourceType') !== 'sites' && $log->getAttribute('resourceInternalId') !== $site->getSequence()) { throw new Exception(Exception::LOG_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php index a873d32603..7e2c587797 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php @@ -75,7 +75,7 @@ class XList extends Base } // Set internal queries - $queries[] = Query::equal('resourceInternalId', [$site->getInternalId()]); + $queries[] = Query::equal('resourceInternalId', [$site->getSequence()]); $queries[] = Query::equal('resourceType', ['sites']); /** diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php index c509799024..6dd1865047 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php @@ -154,7 +154,7 @@ class Create extends Base 'search' => implode(' ', [$siteId, $name, $framework]), 'fallbackFile' => $fallbackFile, 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), + 'installationInternalId' => $installation->getSequence(), 'providerRepositoryId' => $providerRepositoryId, 'repositoryId' => '', 'repositoryInternalId' => '', @@ -180,18 +180,18 @@ class Create extends Base Permission::delete(Role::team(ID::custom($teamId), 'developer')), ], 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), + 'installationInternalId' => $installation->getSequence(), 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'providerRepositoryId' => $providerRepositoryId, 'resourceId' => $site->getId(), - 'resourceInternalId' => $site->getInternalId(), + 'resourceInternalId' => $site->getSequence(), 'resourceType' => 'site', 'providerPullRequestIds' => [] ])); $site->setAttribute('repositoryId', $repository->getId()); - $site->setAttribute('repositoryInternalId', $repository->getInternalId()); + $site->setAttribute('repositoryInternalId', $repository->getSequence()); } $site = $dbForProject->updateDocument('sites', $site->getId(), $site); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php index 7f1681c0f1..835068be88 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -89,7 +89,7 @@ class Update extends Base $oldDeploymentInternalId = $site->getAttribute('deploymentInternalId', ''); $site = $dbForProject->updateDocument('sites', $site->getId(), new Document(array_merge($site->getArrayCopy(), [ - 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->getSequence(), 'deploymentId' => $deployment->getId(), 'deploymentScreenshotDark' => $deployment->getAttribute('screenshotDark', ''), 'deploymentScreenshotLight' => $deployment->getAttribute('screenshotLight', ''), @@ -100,7 +100,7 @@ class Update extends Base Query::equal('trigger', 'manual'), Query::equal("type", ["deployment"]), Query::equal("deploymentResourceType", ["site"]), - Query::equal("deploymentResourceInternalId", [$site->getInternalId()]), + Query::equal("deploymentResourceInternalId", [$site->getSequence()]), ]; if (empty($oldDeploymentInternalId)) { @@ -112,7 +112,7 @@ class Update extends Base $this->listRules($project, $queries, $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) - ->setAttribute('deploymentInternalId', $deployment->getInternalId()); + ->setAttribute('deploymentInternalId', $deployment->getSequence()); $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); }); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php index 212b410178..85f1ee8845 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php @@ -173,8 +173,8 @@ class Update extends Base // Git disconnect logic. Disconnecting only when providerRepositoryId is empty, allowing for continue updates without disconnecting git if ($isConnected && ($providerRepositoryId !== null && empty($providerRepositoryId))) { $repositories = $dbForPlatform->find('repositories', [ - Query::equal('projectInternalId', [$project->getInternalId()]), - Query::equal('resourceInternalId', [$site->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('resourceInternalId', [$site->getSequence()]), Query::equal('resourceType', ['site']), Query::limit(100), ]); @@ -206,18 +206,18 @@ class Update extends Base Permission::delete(Role::team(ID::custom($teamId), 'developer')), ], 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), + 'installationInternalId' => $installation->getSequence(), 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'providerRepositoryId' => $providerRepositoryId, 'resourceId' => $site->getId(), - 'resourceInternalId' => $site->getInternalId(), + 'resourceInternalId' => $site->getSequence(), 'resourceType' => 'site', 'providerPullRequestIds' => [] ])); $repositoryId = $repository->getId(); - $repositoryInternalId = $repository->getInternalId(); + $repositoryInternalId = $repository->getSequence(); } $live = true; @@ -256,7 +256,7 @@ class Update extends Base 'buildCommand' => $buildCommand, 'outputDirectory' => $outputDirectory, 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), + 'installationInternalId' => $installation->getSequence(), 'providerRepositoryId' => $providerRepositoryId, 'repositoryId' => $repositoryId, 'repositoryInternalId' => $repositoryInternalId, diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php index 8bf19a9c28..f8df836085 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php @@ -74,20 +74,20 @@ class Get extends Base $stats = $usage = []; $days = $periods[$range]; $metrics = [ - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), - str_replace(['{siteInternalId}'], [$site->getInternalId()], METRIC_SITES_ID_REQUESTS), - str_replace(['{siteInternalId}'], [$site->getInternalId()], METRIC_SITES_ID_INBOUND), - str_replace(['{siteInternalId}'], [$site->getInternalId()], METRIC_SITES_ID_OUTBOUND), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), + str_replace(['{siteInternalId}'], [$site->getSequence()], METRIC_SITES_ID_REQUESTS), + str_replace(['{siteInternalId}'], [$site->getSequence()], METRIC_SITES_ID_INBOUND), + str_replace(['{siteInternalId}'], [$site->getSequence()], METRIC_SITES_ID_OUTBOUND), ]; diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Create.php index ff1a5c50ec..88da635fe4 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Create.php @@ -85,7 +85,7 @@ class Create extends Base Permission::delete(Role::team(ID::custom($teamId), 'owner')), Permission::delete(Role::team(ID::custom($teamId), 'developer')), ], - 'resourceInternalId' => $site->getInternalId(), + 'resourceInternalId' => $site->getSequence(), 'resourceId' => $site->getId(), 'resourceType' => 'site', 'key' => $key, diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Delete.php b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Delete.php index e4594a7c3d..ea927be367 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Delete.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Delete.php @@ -66,7 +66,7 @@ class Delete extends Base } $variable = $dbForProject->getDocument('variables', $variableId); - if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $site->getInternalId() || $variable->getAttribute('resourceType') !== 'site') { + if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $site->getSequence() || $variable->getAttribute('resourceType') !== 'site') { throw new Exception(Exception::VARIABLE_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Get.php index a14129d432..1c25f9e701 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Get.php @@ -68,7 +68,7 @@ class Get extends Base if ( $variable === false || $variable->isEmpty() || - $variable->getAttribute('resourceInternalId') !== $site->getInternalId() || + $variable->getAttribute('resourceInternalId') !== $site->getSequence() || $variable->getAttribute('resourceType') !== 'site' ) { throw new Exception(Exception::VARIABLE_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Update.php index cd438a0ebb..698992f79f 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Update.php @@ -77,7 +77,7 @@ class Update extends Base } $variable = $dbForProject->getDocument('variables', $variableId); - if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $site->getInternalId() || $variable->getAttribute('resourceType') !== 'site') { + if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $site->getSequence() || $variable->getAttribute('resourceType') !== 'site') { throw new Exception(Exception::VARIABLE_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php index 565ab7bab7..bcefaf353f 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php @@ -29,9 +29,9 @@ class Action extends UtopiaAction $fileSecurity = $bucket->getAttribute('fileSecurity', false); if ($fileSecurity) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($file->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php index fb96849ed2..dc1e5232b6 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php @@ -94,7 +94,7 @@ class Create extends Action '$id' => ID::unique(), 'secret' => Auth::tokenGenerator(128), 'resourceId' => $bucketId . ':' . $fileId, - 'resourceInternalId' => $bucket->getInternalId() . ':' . $file->getInternalId(), + 'resourceInternalId' => $bucket->getSequence() . ':' . $file->getSequence(), 'resourceType' => TOKENS_RESOURCE_TYPE_FILES, 'expire' => $expire, ])); diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php index 38fe10e2d9..628d9b768f 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php @@ -64,7 +64,7 @@ class XList extends Action $queries = Query::parseQueries($queries); $queries[] = Query::equal('resourceType', [TOKENS_RESOURCE_TYPE_FILES]); - $queries[] = Query::equal('resourceInternalId', [$bucket->getInternalId() . ':' . $file->getInternalId()]); + $queries[] = Query::equal('resourceInternalId', [$bucket->getSequence() . ':' . $file->getSequence()]); // Get cursor document if there was a cursor query $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index 286ffe45cb..6d0968a804 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -124,7 +124,7 @@ abstract class ScheduleBase extends Action ); return [ - '$internalId' => $schedule->getInternalId(), + '$sequence' => $schedule->getSequence(), '$id' => $schedule->getId(), 'resourceId' => $schedule->getAttribute('resourceId'), 'schedule' => $schedule->getAttribute('schedule'), @@ -175,19 +175,19 @@ abstract class ScheduleBase extends Action $total = $total + $sum; foreach ($results as $document) { - $localDocument = $this->schedules[$document->getInternalId()] ?? null; + $localDocument = $this->schedules[$document->getSequence()] ?? null; if ($localDocument !== null) { if (!$document['active']) { Console::info("Removing: {$document['resourceType']}::{$document['resourceId']}"); - unset($this->schedules[$document->getInternalId()]); + unset($this->schedules[$document->getSequence()]); } elseif (strtotime($localDocument['resourceUpdatedAt']) !== strtotime($document['resourceUpdatedAt'])) { Console::info("Updating: {$document['resourceType']}::{$document['resourceId']}"); - $this->schedules[$document->getInternalId()] = $getSchedule($document); + $this->schedules[$document->getSequence()] = $getSchedule($document); } } else { try { - $this->schedules[$document->getInternalId()] = $getSchedule($document); + $this->schedules[$document->getSequence()] = $getSchedule($document); } catch (\Throwable $th) { $collectionId = static::getCollectionId(); Console::error("Failed to load schedule for project {$document['projectId']} {$collectionId} {$document['resourceId']}"); diff --git a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php index 6bf2f93afe..27a7c1dbf1 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php @@ -39,7 +39,7 @@ class ScheduleExecutions extends ScheduleBase $schedule['$id'], ); - unset($this->schedules[$schedule['$internalId']]); + unset($this->schedules[$schedule['$sequence']]); continue; } @@ -81,7 +81,7 @@ class ScheduleExecutions extends ScheduleBase $schedule['$id'], ); - unset($this->schedules[$schedule['$internalId']]); + unset($this->schedules[$schedule['$sequence']]); } } } diff --git a/src/Appwrite/Platform/Tasks/ScheduleMessages.php b/src/Appwrite/Platform/Tasks/ScheduleMessages.php index 5e65f7a8a6..4d971e1b36 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleMessages.php +++ b/src/Appwrite/Platform/Tasks/ScheduleMessages.php @@ -57,7 +57,7 @@ class ScheduleMessages extends ScheduleBase ); $this->recordEnqueueDelay($scheduledAt); - unset($this->schedules[$schedule['$internalId']]); + unset($this->schedules[$schedule['$sequence']]); }); } } diff --git a/src/Appwrite/Platform/Tasks/StatsResources.php b/src/Appwrite/Platform/Tasks/StatsResources.php index ca2a6860ff..a0b5056b0f 100644 --- a/src/Appwrite/Platform/Tasks/StatsResources.php +++ b/src/Appwrite/Platform/Tasks/StatsResources.php @@ -73,7 +73,7 @@ class StatsResources extends Action $queue ->setProject($project) ->trigger(); - Console::success('project: ' . $project->getId() . '(' . $project->getInternalId() . ')' . ' queued'); + Console::success('project: ' . $project->getId() . '(' . $project->getSequence() . ')' . ' queued'); }); }, $interval); diff --git a/src/Appwrite/Platform/Workers/Audits.php b/src/Appwrite/Platform/Workers/Audits.php index 76309145b8..19ca5181ce 100644 --- a/src/Appwrite/Platform/Workers/Audits.php +++ b/src/Appwrite/Platform/Workers/Audits.php @@ -91,7 +91,7 @@ class Audits extends Action // Create event data $eventData = [ - 'userId' => $user->getInternalId(), + 'userId' => $user->getSequence(), 'event' => $event, 'resource' => $resource, 'userAgent' => $userAgent, @@ -108,13 +108,13 @@ class Audits extends Action 'timestamp' => date("Y-m-d H:i:s", $message->getTimestamp()), ]; - if (isset($this->logs[$project->getInternalId()])) { - $this->logs[$project->getInternalId()]['logs'][] = $eventData; + if (isset($this->logs[$project->getSequence()])) { + $this->logs[$project->getSequence()]['logs'][] = $eventData; } else { - $this->logs[$project->getInternalId()] = [ + $this->logs[$project->getSequence()] = [ 'project' => new Document([ '$id' => $project->getId(), - '$internalId' => $project->getInternalId(), + '$sequence' => $project->getSequence(), 'database' => $project->getAttribute('database'), ]), 'logs' => [$eventData] @@ -130,7 +130,7 @@ class Audits extends Action if ($shouldProcessBatch) { try { - foreach ($this->logs as $internalId => $projectLogs) { + foreach ($this->logs as $sequence => $projectLogs) { $dbForProject = $getProjectDB($projectLogs['project']); Console::log('Processing batch with ' . count($projectLogs['logs']) . ' events'); @@ -139,7 +139,7 @@ class Audits extends Action $audit->logBatch($projectLogs['logs']); Console::success('Audit logs processed successfully'); - unset($this->logs[$internalId]); + unset($this->logs[$sequence]); } } catch (Throwable $e) { Console::error('Error processing audit logs: ' . $e->getMessage()); diff --git a/src/Appwrite/Platform/Workers/Certificates.php b/src/Appwrite/Platform/Workers/Certificates.php index 0dce51cb52..a9104e0017 100644 --- a/src/Appwrite/Platform/Workers/Certificates.php +++ b/src/Appwrite/Platform/Workers/Certificates.php @@ -255,7 +255,7 @@ class Certificates extends Action $certificate = new Document(\array_merge($certificateDocument->getArrayCopy(), $certificate->getArrayCopy())); $certificate = $dbForPlatform->updateDocument('certificates', $certificate->getId(), $certificate); } else { - $certificate->removeAttribute('$internalId'); + $certificate->removeAttribute('$sequence'); $certificate = $dbForPlatform->createDocument('certificates', $certificate); } diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index b2691b420e..8c6f6f0252 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -147,15 +147,15 @@ class Databases extends Action try { switch ($type) { case Database::VAR_RELATIONSHIP: - $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); + $relatedCollection = $dbForProject->getDocument('database_' . $database->getSequence(), $options['relatedCollection']); if ($relatedCollection->isEmpty()) { throw new DatabaseException('Collection not found'); } if ( !$dbForProject->createRelationship( - collection: 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), - relatedCollection: 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), + collection: 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + relatedCollection: 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), type: $options['relationType'], twoWay: $options['twoWay'], id: $key, @@ -167,12 +167,12 @@ class Databases extends Action } if ($options['twoWay']) { - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $options['twoWayKey']); $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'available')); } break; default: - if (!$dbForProject->createAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) { + if (!$dbForProject->createAttribute('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) { throw new Exception('Failed to create Attribute'); } } @@ -207,10 +207,10 @@ class Databases extends Action $this->trigger($database, $collection, $project, $event, $queueForRealtime, $attribute); if (! $relatedCollection->isEmpty()) { - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $relatedCollection->getId()); } - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); } } @@ -257,18 +257,18 @@ class Databases extends Action try { if ($type === Database::VAR_RELATIONSHIP) { if ($options['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); + $relatedCollection = $dbForProject->getDocument('database_' . $database->getSequence(), $options['relatedCollection']); if ($relatedCollection->isEmpty()) { throw new DatabaseException('Collection not found'); } - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $options['twoWayKey']); } - if (!$dbForProject->deleteRelationship('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { + if (!$dbForProject->deleteRelationship('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $key)) { $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'stuck')); throw new DatabaseException('Failed to delete Relationship'); } - } elseif (!$dbForProject->deleteAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { + } elseif (!$dbForProject->deleteAttribute('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $key)) { throw new DatabaseException('Failed to delete Attribute'); } @@ -365,10 +365,10 @@ class Databases extends Action } } } finally { - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); if (! $relatedCollection->isEmpty()) { - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $relatedCollection->getId()); } } } @@ -408,7 +408,7 @@ class Databases extends Action $project = $dbForPlatform->getDocument('projects', $projectId); try { - if (!$dbForProject->createIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $attributes, $lengths, $orders)) { + if (!$dbForProject->createIndex('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $key, $type, $attributes, $lengths, $orders)) { throw new DatabaseException('Failed to create Index'); } $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'available')); @@ -426,7 +426,7 @@ class Databases extends Action throw $e; } finally { $this->trigger($database, $collection, $project, $event, $queueForRealtime, null, $index); - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); } } @@ -461,7 +461,7 @@ class Databases extends Action $project = $dbForPlatform->getDocument('projects', $projectId); try { - if ($status !== 'failed' && !$dbForProject->deleteIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { + if ($status !== 'failed' && !$dbForProject->deleteIndex('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $key)) { throw new DatabaseException('Failed to delete index'); } $dbForProject->deleteDocument('indexes', $index->getId()); @@ -482,7 +482,7 @@ class Databases extends Action } finally { $this->trigger($database, $collection, $project, $event, $queueForRealtime, null, $index); - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collection->getId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collection->getId()); } } @@ -495,11 +495,11 @@ class Databases extends Action */ protected function deleteDatabase(Document $database, Document $project, $dbForProject): void { - $this->deleteByGroup('database_' . $database->getInternalId(), [], $dbForProject, function ($collection) use ($database, $project, $dbForProject) { + $this->deleteByGroup('database_' . $database->getSequence(), [], $dbForProject, function ($collection) use ($database, $project, $dbForProject) { $this->deleteCollection($database, $collection, $project, $dbForProject); }); - $dbForProject->deleteCollection('database_' . $database->getInternalId()); + $dbForProject->deleteCollection('database_' . $database->getSequence()); } /** @@ -522,10 +522,10 @@ class Databases extends Action } $collectionId = $collection->getId(); - $collectionInternalId = $collection->getInternalId(); - $databaseInternalId = $database->getInternalId(); + $collectionInternalId = $collection->getSequence(); + $databaseInternalId = $database->getSequence(); - $dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $collection->getInternalId()); + $dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $collection->getSequence()); /** * Related collections relating to current collection diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 43bc55583d..8ed96c76a2 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -34,7 +34,7 @@ use Utopia\System\System; class Deletes extends Action { - protected array $selects = ['$internalId', '$id', '$collection', '$permissions', '$updatedAt']; + protected array $selects = ['$sequence', '$id', '$collection', '$permissions', '$updatedAt']; public static function getName(): string { @@ -277,7 +277,7 @@ class Deletes extends Action $this->deleteByGroup( 'subscribers', [ - Query::equal('topicInternalId', [$topic->getInternalId()]), + Query::equal('topicInternalId', [$topic->getSequence()]), Query::orderAsc(), ], $getProjectDB($project) @@ -298,7 +298,7 @@ class Deletes extends Action private function deleteSessionTargets(Document $project, callable $getProjectDB, Document $session): void { - Targets::delete($getProjectDB($project), Query::equal('sessionInternalId', [$session->getInternalId()])); + Targets::delete($getProjectDB($project), Query::equal('sessionInternalId', [$session->getSequence()])); } /** @@ -434,7 +434,7 @@ class Deletes extends Action public function deleteMemberships(callable $getProjectDB, Document $document, Document $project): void { $dbForProject = $getProjectDB($project); - $teamInternalId = $document->getInternalId(); + $teamInternalId = $document->getSequence(); // Delete Memberships $this->deleteByGroup( @@ -466,7 +466,7 @@ class Deletes extends Action { $projects = $dbForPlatform->find('projects', [ - Query::equal('teamInternalId', [$document->getInternalId()]), + Query::equal('teamInternalId', [$document->getSequence()]), Query::equal('region', [System::getEnv('_APP_REGION', 'default')]) ]); @@ -497,7 +497,7 @@ class Deletes extends Action */ private function deleteProject(Database $dbForPlatform, callable $getProjectDB, Device $deviceForFiles, Device $deviceForSites, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, Document $document): void { - $projectInternalId = $document->getInternalId(); + $projectInternalId = $document->getSequence(); $projectId = $document->getId(); try { @@ -637,7 +637,7 @@ class Deletes extends Action private function deleteUser(callable $getProjectDB, Document $document, Document $project): void { $userId = $document->getId(); - $userInternalId = $document->getInternalId(); + $userInternalId = $document->getSequence(); $dbForProject = $getProjectDB($project); // Delete all sessions of this user from the sessions table and update the sessions field of the user record @@ -769,7 +769,7 @@ class Deletes extends Action { $dbForProject = $getProjectDB($project); $siteId = $document->getId(); - $siteInternalId = $document->getInternalId(); + $siteInternalId = $document->getSequence(); /** * Delete rules for site @@ -779,7 +779,7 @@ class Deletes extends Action Query::equal('type', ['deployment']), Query::equal('deploymentResourceType', ['site']), Query::equal('deploymentResourceInternalId', [$siteInternalId]), - Query::equal('projectInternalId', [$project->getInternalId()]) + Query::equal('projectInternalId', [$project->getSequence()]) ], $dbForPlatform, function (Document $document) use ($dbForPlatform, $certificates) { $this->deleteRule($dbForPlatform, $document, $certificates); }); @@ -804,7 +804,7 @@ class Deletes extends Action Query::equal('resourceType', ['site']), Query::orderAsc() ], $dbForProject, function (Document $document) use ($project, $certificates, $deviceForSites, $deviceForBuilds, $deviceForFiles, $dbForPlatform, &$deploymentInternalIds) { - $deploymentInternalIds[] = $document->getInternalId(); + $deploymentInternalIds[] = $document->getSequence(); $deploymentIds[] = $document->getId(); $this->deleteBuildFiles($deviceForBuilds, $document); $this->deleteDeploymentFiles($deviceForSites, $document); @@ -827,7 +827,7 @@ class Deletes extends Action */ Console::info("Deleting VCS repositories and comments linked to site " . $siteId); $this->deleteByGroup('repositories', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), Query::equal('resourceInternalId', [$siteInternalId]), Query::equal('resourceType', ['site']), ], $dbForPlatform, function (Document $document) use ($dbForPlatform) { @@ -855,7 +855,7 @@ class Deletes extends Action $projectId = $project->getId(); $dbForProject = $getProjectDB($project); $functionId = $document->getId(); - $functionInternalId = $document->getInternalId(); + $functionInternalId = $document->getSequence(); /** * Delete rules @@ -865,7 +865,7 @@ class Deletes extends Action Query::equal('type', ['deployment']), Query::equal('deploymentResourceType', ['function']), Query::equal('deploymentResourceInternalId', [$functionInternalId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), Query::orderAsc() ], $dbForPlatform, function (Document $document) use ($project, $dbForPlatform, $certificates) { $this->deleteRule($dbForPlatform, $document, $certificates); @@ -892,7 +892,7 @@ class Deletes extends Action Query::equal('resourceType', ['function']), Query::orderAsc() ], $dbForProject, function (Document $document) use ($dbForPlatform, $project, $certificates, $deviceForFunctions, $deviceForBuilds, &$deploymentInternalIds) { - $deploymentInternalIds[] = $document->getInternalId(); + $deploymentInternalIds[] = $document->getSequence(); $this->deleteDeploymentFiles($deviceForFunctions, $document); $this->deleteBuildFiles($deviceForBuilds, $document); }); @@ -913,7 +913,7 @@ class Deletes extends Action */ Console::info("Deleting VCS repositories and comments linked to function " . $functionId); $this->deleteByGroup('repositories', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), Query::equal('resourceInternalId', [$functionInternalId]), Query::equal('resourceType', ['function']), Query::orderAsc() @@ -957,7 +957,7 @@ class Deletes extends Action } foreach ($screenshotIds as $id) { - $file = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('bucket_' . $bucket->getInternalId(), $id)); + $file = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $id)); if ($file->isEmpty()) { Console::error('Failed to get deployment screenshot: ' . $id); @@ -1060,7 +1060,7 @@ class Deletes extends Action $projectId = $project->getId(); $dbForProject = $getProjectDB($project); $deploymentId = $document->getId(); - $deploymentInternalId = $document->getInternalId(); + $deploymentInternalId = $document->getSequence(); /** * Delete deployment files @@ -1089,7 +1089,7 @@ class Deletes extends Action Query::equal('trigger', ['deployment']), Query::equal('type', ['deployment']), Query::equal('deploymentInternalId', [$deploymentInternalId]), - Query::equal('projectInternalId', [$project->getInternalId()]) + Query::equal('projectInternalId', [$project->getSequence()]) ], $dbForPlatform, function (Document $document) use ($dbForPlatform, $certificates) { $this->deleteRule($dbForPlatform, $document, $certificates); }); @@ -1211,7 +1211,7 @@ class Deletes extends Action { $dbForProject = $getProjectDB($project); - $dbForProject->deleteCollection('bucket_' . $document->getInternalId()); + $dbForProject->deleteCollection('bucket_' . $document->getSequence()); $deviceForFiles->deletePath($document->getId()); } @@ -1229,7 +1229,7 @@ class Deletes extends Action $dbForProject = $getProjectDB($project); $this->listByGroup('functions', [ - Query::equal('installationInternalId', [$document->getInternalId()]) + Query::equal('installationInternalId', [$document->getSequence()]) ], $dbForProject, function ($function) use ($dbForProject, $dbForPlatform) { $dbForPlatform->deleteDocument('repositories', $function->getAttribute('repositoryId')); @@ -1260,7 +1260,7 @@ class Deletes extends Action $this->listByGroup( 'deployments', [ - Query::equal('resourceInternalId', [$function->getInternalId()]), + Query::equal('resourceInternalId', [$function->getSequence()]), Query::equal('resourceType', ['functions']), ], $getProjectDB($project), diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index c8c68a58ba..a9126583ce 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -280,7 +280,7 @@ class Functions extends Action $execution = new Document([ '$id' => $executionId, '$permissions' => $user->isEmpty() ? [] : [Permission::read(Role::user($user->getId()))], - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceId' => $function->getId(), 'resourceType' => 'functions', 'deploymentInternalId' => '', @@ -420,10 +420,10 @@ class Functions extends Action $execution = new Document([ '$id' => $executionId, '$permissions' => $user->isEmpty() ? [] : [Permission::read(Role::user($user->getId()))], - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceId' => $function->getId(), 'resourceType' => 'functions', - 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->getSequence(), 'deploymentId' => $deployment->getId(), 'trigger' => $trigger, 'status' => 'processing', @@ -572,13 +572,13 @@ class Functions extends Action ->setProject($project) ->addMetric(METRIC_EXECUTIONS, 1) ->addMetric(str_replace(['{resourceType}'], [RESOURCE_TYPE_FUNCTIONS], METRIC_RESOURCE_TYPE_EXECUTIONS), 1) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), 1) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), 1) ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000))// per project ->addMetric(str_replace(['{resourceType}'], [RESOURCE_TYPE_FUNCTIONS], METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) ->addMetric(METRIC_EXECUTIONS_MB_SECONDS, (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ->addMetric(str_replace(['{resourceType}'], [RESOURCE_TYPE_FUNCTIONS], METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ->trigger() ; } diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index 8491e91a6c..2ee107a319 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -373,7 +373,7 @@ class Messaging extends Action throw new \Exception('Storage bucket with the requested ID could not be found'); } - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); if ($file->isEmpty()) { throw new \Exception('Storage file with the requested ID could not be found'); } @@ -558,7 +558,7 @@ class Messaging extends Action throw new \Exception('Storage bucket with the requested ID could not be found'); } - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); if ($file->isEmpty()) { throw new \Exception('Storage file with the requested ID could not be found'); } diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index b746365f20..395ec1351e 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -368,7 +368,7 @@ class Migrations extends Action $this->updateMigrationDocument($migration, $projectDocument, $queueForRealtime); if ($migration->getAttribute('status', '') === 'failed') { - Console::error('Migration('.$migration->getInternalId().':'.$migration->getId().') failed, Project('.$this->project->getInternalId().':'.$this->project->getId().')'); + Console::error('Migration('.$migration->getSequence().':'.$migration->getId().') failed, Project('.$this->project->getSequence().':'.$this->project->getId().')'); if ($destination) { $destination->error(); diff --git a/src/Appwrite/Platform/Workers/StatsResources.php b/src/Appwrite/Platform/Workers/StatsResources.php index 19d1223d95..c68465f8df 100644 --- a/src/Appwrite/Platform/Workers/StatsResources.php +++ b/src/Appwrite/Platform/Workers/StatsResources.php @@ -80,7 +80,7 @@ class StatsResources extends Action $this->countForProject($dbForPlatform, $getLogsDB, $getProjectDB, $project); $endTime = microtime(true); $executionTime = $endTime - $startTime; - Console::info('Project: ' . $project->getId() . '(' . $project->getInternalId() . ') aggregated in ' . $executionTime .' seconds'); + Console::info('Project: ' . $project->getId() . '(' . $project->getSequence() . ') aggregated in ' . $executionTime .' seconds'); } protected function countForProject(Database $dbForPlatform, callable $getLogsDB, callable $getProjectDB, Document $project): void @@ -105,17 +105,17 @@ class StatsResources extends Action $region = $project->getAttribute('region'); $platforms = $dbForPlatform->count('platforms', [ - Query::equal('projectInternalId', [$project->getInternalId()]) + Query::equal('projectInternalId', [$project->getSequence()]) ]); $webhooks = $dbForPlatform->count('webhooks', [ - Query::equal('projectInternalId', [$project->getInternalId()]) + Query::equal('projectInternalId', [$project->getSequence()]) ]); $keys = $dbForPlatform->count('keys', [ - Query::equal('projectInternalId', [$project->getInternalId()]) + Query::equal('projectInternalId', [$project->getSequence()]) ]); $domains = $dbForPlatform->count('rules', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), Query::equal('owner', ['']), ]); @@ -216,13 +216,13 @@ class StatsResources extends Action $totalFiles = 0; $totalStorage = 0; $this->foreachDocument($dbForProject, 'buckets', [], function ($bucket) use ($dbForProject, $dbForLogs, $region, &$totalFiles, &$totalStorage) { - $files = $dbForProject->count('bucket_' . $bucket->getInternalId()); + $files = $dbForProject->count('bucket_' . $bucket->getSequence()); - $metric = str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES); + $metric = str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES); $this->createStatsDocuments($region, $metric, $files); - $storage = $dbForProject->sum('bucket_' . $bucket->getInternalId(), 'sizeActual'); - $metric = str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE); + $storage = $dbForProject->sum('bucket_' . $bucket->getSequence(), 'sizeActual'); + $metric = str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_STORAGE); $this->createStatsDocuments($region, $metric, $storage); $totalStorage += $storage; @@ -241,10 +241,10 @@ class StatsResources extends Action $totalImageTransformations = 0; $last30Days = (new \DateTime())->sub(\DateInterval::createFromDateString('30 days'))->format('Y-m-d 00:00:00'); $this->foreachDocument($dbForProject, 'buckets', [], function ($bucket) use ($dbForProject, $last30Days, $region, &$totalImageTransformations) { - $imageTransformations = $dbForProject->count('bucket_' . $bucket->getInternalId(), [ + $imageTransformations = $dbForProject->count('bucket_' . $bucket->getSequence(), [ Query::greaterThanEqual('transformedAt', $last30Days), ]); - $metric = str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED); + $metric = str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED); $this->createStatsDocuments($region, $metric, $imageTransformations); $totalImageTransformations += $imageTransformations; }); @@ -260,9 +260,9 @@ class StatsResources extends Action $totalDatabaseStorage = 0; $this->foreachDocument($dbForProject, 'databases', [], function ($database) use ($dbForProject, $region, &$totalCollections, &$totalDocuments, &$totalDatabaseStorage) { - $collections = $dbForProject->count('database_' . $database->getInternalId()); + $collections = $dbForProject->count('database_' . $database->getSequence()); - $metric = str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS); + $metric = str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_COLLECTIONS); $this->createStatsDocuments($region, $metric, $collections); [$documents, $storage] = $this->countForCollections($dbForProject, $database, $region); @@ -280,23 +280,23 @@ class StatsResources extends Action { $databaseDocuments = 0; $databaseStorage = 0; - $this->foreachDocument($dbForProject, 'database_' . $database->getInternalId(), [], function ($collection) use ($dbForProject, $database, $region, &$databaseStorage, &$databaseDocuments) { - $documents = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); - $metric = str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS); + $this->foreachDocument($dbForProject, 'database_' . $database->getSequence(), [], function ($collection) use ($dbForProject, $database, $region, &$databaseStorage, &$databaseDocuments) { + $documents = $dbForProject->count('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); + $metric = str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getSequence(), $collection->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS); $this->createStatsDocuments($region, $metric, $documents); $databaseDocuments += $documents; - $collectionStorage = $dbForProject->getSizeOfCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); - $metric = str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE); + $collectionStorage = $dbForProject->getSizeOfCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); + $metric = str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getSequence(), $collection->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE); $this->createStatsDocuments($region, $metric, $collectionStorage); $databaseStorage += $collectionStorage; }); - $metric = str_replace(['{databaseInternalId}'], [$database->getInternalId()], METRIC_DATABASE_ID_DOCUMENTS); + $metric = str_replace(['{databaseInternalId}'], [$database->getSequence()], METRIC_DATABASE_ID_DOCUMENTS); $this->createStatsDocuments($region, $metric, $databaseDocuments); - $metric = str_replace(['{databaseInternalId}'], [$database->getInternalId()], METRIC_DATABASE_ID_STORAGE); + $metric = str_replace(['{databaseInternalId}'], [$database->getSequence()], METRIC_DATABASE_ID_STORAGE); $this->createStatsDocuments($region, $metric, $databaseStorage); return [$databaseDocuments, $databaseStorage]; @@ -337,33 +337,33 @@ class StatsResources extends Action $this->foreachDocument($dbForProject, 'functions', [], function (Document $function) use ($dbForProject, $region) { $functionDeploymentsStorage = $dbForProject->sum('deployments', 'sourceSize', [ - Query::equal('resourceInternalId', [$function->getInternalId()]), + Query::equal('resourceInternalId', [$function->getSequence()]), Query::equal('resourceType', [RESOURCE_TYPE_FUNCTIONS]), ]); - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), $functionDeploymentsStorage); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), $functionDeploymentsStorage); $functionDeployments = $dbForProject->count('deployments', [ - Query::equal('resourceInternalId', [$function->getInternalId()]), + Query::equal('resourceInternalId', [$function->getSequence()]), Query::equal('resourceType', [RESOURCE_TYPE_FUNCTIONS]), ]); - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), $functionDeployments); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), $functionDeployments); /** * As deployments and builds have 1-1 relationship, * the count for one should match the other */ - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS), $functionDeployments); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS), $functionDeployments); $functionBuildsStorage = 0; $this->foreachDocument($dbForProject, 'deployments', [ - Query::equal('resourceInternalId', [$function->getInternalId()]), + Query::equal('resourceInternalId', [$function->getSequence()]), Query::equal('resourceType', [RESOURCE_TYPE_FUNCTIONS]), ], function (Document $deployment) use (&$functionBuildsStorage): void { $functionBuildsStorage += $deployment->getAttribute('buildSize', 0); }); - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $functionBuildsStorage); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $functionBuildsStorage); }); } @@ -387,29 +387,29 @@ class StatsResources extends Action $this->foreachDocument($dbForProject, 'sites', [], function (Document $site) use ($dbForProject, $region) { $siteDeploymentsStorage = $dbForProject->sum('deployments', 'sourceSize', [ - Query::equal('resourceInternalId', [$site->getInternalId()]), + Query::equal('resourceInternalId', [$site->getSequence()]), Query::equal('resourceType', [RESOURCE_TYPE_SITES]), ]); - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), $siteDeploymentsStorage); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), $siteDeploymentsStorage); $siteDeployments = $dbForProject->count('deployments', [ - Query::equal('resourceInternalId', [$site->getInternalId()]), + Query::equal('resourceInternalId', [$site->getSequence()]), Query::equal('resourceType', [RESOURCE_TYPE_SITES]), ]); - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), $siteDeployments); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), $siteDeployments); /** * As deployments and builds have 1-1 relationship, * the count for one should match the other */ - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS), $siteDeployments); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS), $siteDeployments); $siteBuildsStorage = $dbForProject->sum('deployments', 'buildSize', [ - Query::equal('resourceInternalId', [$site->getInternalId()]), + Query::equal('resourceInternalId', [$site->getSequence()]), Query::equal('resourceType', [RESOURCE_TYPE_SITES]), ]); - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $siteBuildsStorage); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $siteBuildsStorage); }); } @@ -437,6 +437,6 @@ class StatsResources extends Action $this->documents ); $this->documents = []; - Console::success('Stats written to logs db for project: ' . $project->getId() . '(' . $project->getInternalId() . ')'); + Console::success('Stats written to logs db for project: ' . $project->getId() . '(' . $project->getSequence() . ')'); } } diff --git a/src/Appwrite/Platform/Workers/StatsUsage.php b/src/Appwrite/Platform/Workers/StatsUsage.php index 25c80fabdc..59b5a15ada 100644 --- a/src/Appwrite/Platform/Workers/StatsUsage.php +++ b/src/Appwrite/Platform/Workers/StatsUsage.php @@ -145,7 +145,7 @@ class StatsUsage extends Action $aggregationInterval = (int) System::getEnv('_APP_USAGE_AGGREGATION_INTERVAL', '20'); $project = new Document($payload['project'] ?? []); - $projectId = $project->getInternalId(); + $projectId = $project->getSequence(); foreach ($payload['reduce'] ?? [] as $document) { if (empty($document)) { continue; @@ -211,8 +211,8 @@ class StatsUsage extends Action } break; case $document->getCollection() === 'databases': // databases - $collections = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS))); - $documents = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS))); + $collections = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getSequence(), METRIC_DATABASE_ID_COLLECTIONS))); + $documents = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getSequence(), METRIC_DATABASE_ID_DOCUMENTS))); if (!empty($collections['value'])) { $metrics[] = [ 'key' => METRIC_COLLECTIONS, @@ -232,7 +232,7 @@ class StatsUsage extends Action $databaseInternalId = $parts[1] ?? 0; $documents = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace( ['{databaseInternalId}', '{collectionInternalId}'], - [$databaseInternalId, $document->getInternalId()], + [$databaseInternalId, $document->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS ))); @@ -249,8 +249,8 @@ class StatsUsage extends Action break; case $document->getCollection() === 'buckets': - $files = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES))); - $storage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE))); + $files = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getSequence(), METRIC_BUCKET_ID_FILES))); + $storage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getSequence(), METRIC_BUCKET_ID_FILES_STORAGE))); if (!empty($files['value'])) { $metrics[] = [ @@ -268,13 +268,13 @@ class StatsUsage extends Action break; case $document->getCollection() === 'functions' || $document->getCollection() === 'sites': - $deployments = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS))); - $deploymentsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE))); - $builds = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS))); - $buildsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE))); - $buildsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE))); - $executions = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS))); - $executionsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE))); + $deployments = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS))); + $deploymentsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE))); + $builds = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS))); + $buildsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE))); + $buildsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE))); + $executions = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS))); + $executionsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE))); if (!empty($deployments['value'])) { $metrics[] = [ @@ -357,7 +357,7 @@ class StatsUsage extends Action break; } } catch (Throwable $e) { - Console::error("[reducer] " . " {DateTime::now()} " . " {$project->getInternalId()} " . " {$e->getMessage()}"); + Console::error("[reducer] " . " {DateTime::now()} " . " {$project->getSequence()} " . " {$e->getMessage()}"); } } @@ -376,7 +376,7 @@ class StatsUsage extends Action continue; } - Console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); + Console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getSequence(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); try { foreach ($stats['keys'] ?? [] as $key => $value) { @@ -402,23 +402,23 @@ class StatsUsage extends Action ]); - $this->projects[$project->getInternalId()]['project'] = new Document([ + $this->projects[$project->getSequence()]['project'] = new Document([ '$id' => $project->getId(), - '$internalId' => $project->getInternalId(), + '$sequence' => $project->getSequence(), 'database' => $project->getAttribute('database'), ]); - $this->projects[$project->getInternalId()]['stats'][] = $document; + $this->projects[$project->getSequence()]['stats'][] = $document; $this->prepareForLogsDB($project, $document); } } } catch (Exception $e) { - Console::error('[' . DateTime::now() . '] project [' . $project->getInternalId() . '] database [' . $project['database'] . '] ' . ' ' . $e->getMessage()); + Console::error('[' . DateTime::now() . '] project [' . $project->getSequence() . '] database [' . $project['database'] . '] ' . ' ' . $e->getMessage()); } } - foreach ($this->projects as $internalId => $projectStats) { - if (empty($internalId)) { + foreach ($this->projects as $sequence => $projectStats) { + if (empty($sequence)) { continue; } try { @@ -427,7 +427,7 @@ class StatsUsage extends Action $dbForProject->createOrUpdateDocumentsWithIncrease('stats', 'value', $projectStats['stats']); Console::success('Batch successfully written to DB'); - unset($this->projects[$internalId]); + unset($this->projects[$sequence]); } catch (Throwable $e) { Console::error('Error processing stats: ' . $e->getMessage()); } @@ -451,7 +451,7 @@ class StatsUsage extends Action } } $documentClone = clone $stat; - $documentClone->setAttribute('$tenant', (int) $project->getInternalId()); + $documentClone->setAttribute('$tenant', (int) $project->getSequence()); $this->statDocuments[] = $documentClone; } diff --git a/src/Appwrite/Platform/Workers/StatsUsageDump.php b/src/Appwrite/Platform/Workers/StatsUsageDump.php index 77ec3f13e6..7c2da8fd4d 100644 --- a/src/Appwrite/Platform/Workers/StatsUsageDump.php +++ b/src/Appwrite/Platform/Workers/StatsUsageDump.php @@ -126,7 +126,7 @@ class StatsUsageDump extends Action continue; } - Console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); + Console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getSequence(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); try { /** @var Database $dbForProject */ @@ -169,7 +169,7 @@ class StatsUsageDump extends Action } } } catch (\Exception $e) { - Console::error('[' . DateTime::now() . '] project [' . $project->getInternalId() . '] database [' . $project['database'] . '] ' . ' ' . $e->getMessage()); + Console::error('[' . DateTime::now() . '] project [' . $project->getSequence() . '] database [' . $project['database'] . '] ' . ' ' . $e->getMessage()); } } } diff --git a/src/Appwrite/Platform/Workers/Webhooks.php b/src/Appwrite/Platform/Workers/Webhooks.php index ada4d6faaa..4c081aaa13 100644 --- a/src/Appwrite/Platform/Workers/Webhooks.php +++ b/src/Appwrite/Platform/Workers/Webhooks.php @@ -176,7 +176,7 @@ class Webhooks extends Action $this->errors[] = $logs; $queueForStatsUsage ->addMetric(METRIC_WEBHOOKS_FAILED, 1) - ->addMetric(str_replace('{webhookInternalId}', $webhook->getInternalId(), METRIC_WEBHOOK_ID_FAILED), 1) + ->addMetric(str_replace('{webhookInternalId}', $webhook->getSequence(), METRIC_WEBHOOK_ID_FAILED), 1) ; @@ -186,7 +186,7 @@ class Webhooks extends Action $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $queueForStatsUsage ->addMetric(METRIC_WEBHOOKS_SENT, 1) - ->addMetric(str_replace('{webhookInternalId}', $webhook->getInternalId(), METRIC_WEBHOOK_ID_SENT), 1) + ->addMetric(str_replace('{webhookInternalId}', $webhook->getSequence(), METRIC_WEBHOOK_ID_SENT), 1) ; } diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php index e8eafba5a0..20e7d5cb93 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php @@ -71,8 +71,8 @@ class Base extends Queries 'array' => false, ]); - $internalId = new Document([ - 'key' => '$internalId', + $sequence = new Document([ + 'key' => '$sequence', 'type' => Database::VAR_STRING, 'array' => false, ]); @@ -82,7 +82,7 @@ class Base extends Queries new Offset(), new Cursor(), new Filter($attributes, APP_DATABASE_QUERY_MAX_VALUES), - new Order([...$attributes, $internalId]), + new Order([...$attributes, $sequence]), ]; parent::__construct($validators); diff --git a/src/Appwrite/Utopia/Response/Model/Document.php b/src/Appwrite/Utopia/Response/Model/Document.php index 41a10cee89..c4f7eb3044 100644 --- a/src/Appwrite/Utopia/Response/Model/Document.php +++ b/src/Appwrite/Utopia/Response/Model/Document.php @@ -71,7 +71,7 @@ class Document extends Any public function filter(DatabaseDocument $document): DatabaseDocument { - $document->removeAttribute('$internalId'); + $document->removeAttribute('$sequence'); $document->removeAttribute('$collection'); $document->removeAttribute('$tenant'); diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 7c0060ecaa..8f59575f79 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -2003,9 +2003,9 @@ trait DatabasesBase $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); $this->assertEquals(2017, $documents['body']['documents'][1]['releaseYear']); $this->assertEquals(2019, $documents['body']['documents'][2]['releaseYear']); - $this->assertFalse(array_key_exists('$internalId', $documents['body']['documents'][0])); - $this->assertFalse(array_key_exists('$internalId', $documents['body']['documents'][1])); - $this->assertFalse(array_key_exists('$internalId', $documents['body']['documents'][2])); + $this->assertFalse(array_key_exists('$sequence', $documents['body']['documents'][0])); + $this->assertFalse(array_key_exists('$sequence', $documents['body']['documents'][1])); + $this->assertFalse(array_key_exists('$sequence', $documents['body']['documents'][2])); $this->assertCount(3, $documents['body']['documents']); foreach ($documents['body']['documents'] as $document) { @@ -2098,7 +2098,7 @@ trait DatabasesBase $this->assertEquals($response['body']['releaseYear'], $document['releaseYear']); $this->assertEquals($response['body']['$permissions'], $document['$permissions']); $this->assertEquals($response['body']['birthDay'], $document['birthDay']); - $this->assertFalse(array_key_exists('$internalId', $response['body'])); + $this->assertFalse(array_key_exists('$sequence', $response['body'])); $this->assertFalse(array_key_exists('$tenant', $response['body'])); } } @@ -4361,8 +4361,8 @@ trait DatabasesBase $this->assertArrayNotHasKey('$collection', $person1['body']); $this->assertArrayNotHasKey('$collection', $person1['body']['library']); - $this->assertArrayNotHasKey('$internalId', $person1['body']); - $this->assertArrayNotHasKey('$internalId', $person1['body']['library']); + $this->assertArrayNotHasKey('$sequence', $person1['body']); + $this->assertArrayNotHasKey('$sequence', $person1['body']['library']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ 'content-type' => 'application/json', From f6bf7791199364b6ae38494706ccf186e7bc09bc Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 23 May 2025 02:57:11 +1200 Subject: [PATCH 067/219] Update database --- composer.json | 2 +- composer.lock | 61 +++++++++++++++++++++++++++++---------------------- 2 files changed, 36 insertions(+), 27 deletions(-) diff --git a/composer.json b/composer.json index 7e445cd36b..9a3c9e8319 100644 --- a/composer.json +++ b/composer.json @@ -53,7 +53,7 @@ "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", "utopia-php/detector": "0.1.*", - "utopia-php/database": "0.69.*", + "utopia-php/database": "dev-feat-internal-to-sequence as 0.69.5", "utopia-php/domains": "0.8.0", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", diff --git a/composer.lock b/composer.lock index f36b815777..1d84acbb43 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9f5de64d73e2ef73d796fa64f2baf232", + "content-hash": "cb47e05e104d978efba67c3ccc7bf959", "packages": [ { "name": "adhocore/jwt", @@ -1238,16 +1238,16 @@ }, { "name": "open-telemetry/exporter-otlp", - "version": "1.3.0", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/exporter-otlp.git", - "reference": "19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c" + "reference": "8b3ca1f86d01429c73b407bf1a2075d9c187001e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c", - "reference": "19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c", + "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/8b3ca1f86d01429c73b407bf1a2075d9c187001e", + "reference": "8b3ca1f86d01429c73b407bf1a2075d9c187001e", "shasum": "" }, "require": { @@ -1298,7 +1298,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-12T00:36:35+00:00" + "time": "2025-05-21T12:02:20+00:00" }, { "name": "open-telemetry/gen-otlp-protobuf", @@ -1365,16 +1365,16 @@ }, { "name": "open-telemetry/sdk", - "version": "1.4.0", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/sdk.git", - "reference": "939d3a28395c249a763676458140dad44b3a8011" + "reference": "cd0d7367599717fc29e04eb8838ec061e6c2c657" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/939d3a28395c249a763676458140dad44b3a8011", - "reference": "939d3a28395c249a763676458140dad44b3a8011", + "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/cd0d7367599717fc29e04eb8838ec061e6c2c657", + "reference": "cd0d7367599717fc29e04eb8838ec061e6c2c657", "shasum": "" }, "require": { @@ -1451,7 +1451,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-07T12:32:21+00:00" + "time": "2025-05-22T02:33:34+00:00" }, { "name": "open-telemetry/sem-conv", @@ -3499,16 +3499,16 @@ }, { "name": "utopia-php/database", - "version": "0.69.5", + "version": "dev-feat-internal-to-sequence", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "4abe53609dfc23b2ea82884d12b149df6a8af2f5" + "reference": "0f3617e23bef7c6f260d7f8f194031c2f096a154" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/4abe53609dfc23b2ea82884d12b149df6a8af2f5", - "reference": "4abe53609dfc23b2ea82884d12b149df6a8af2f5", + "url": "https://api.github.com/repos/utopia-php/database/zipball/0f3617e23bef7c6f260d7f8f194031c2f096a154", + "reference": "0f3617e23bef7c6f260d7f8f194031c2f096a154", "shasum": "" }, "require": { @@ -3549,9 +3549,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.69.5" + "source": "https://github.com/utopia-php/database/tree/feat-internal-to-sequence" }, - "time": "2025-05-17T08:01:51+00:00" + "time": "2025-05-22T13:09:40+00:00" }, { "name": "utopia-php/detector", @@ -4816,16 +4816,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.40.17", + "version": "0.40.18", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de" + "reference": "38de4b9c58112d7e83eb75955994c8412a401093" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de", - "reference": "7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/38de4b9c58112d7e83eb75955994c8412a401093", + "reference": "38de4b9c58112d7e83eb75955994c8412a401093", "shasum": "" }, "require": { @@ -4861,9 +4861,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.40.17" + "source": "https://github.com/appwrite/sdk-generator/tree/0.40.18" }, - "time": "2025-05-16T15:10:54+00:00" + "time": "2025-05-21T14:14:47+00:00" }, { "name": "doctrine/annotations", @@ -8240,9 +8240,18 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/database", + "version": "dev-feat-internal-to-sequence", + "alias": "0.69.5", + "alias_normalized": "0.69.5.0" + } + ], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "utopia-php/database": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -8266,5 +8275,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } From b4f5af8461f447fe3b544e72b02b3eba56f92dea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Thu, 22 May 2025 17:25:47 +0200 Subject: [PATCH 068/219] Fix: unlimited deployment size --- .../Platform/Modules/Functions/Http/Deployments/Create.php | 2 +- src/Appwrite/Platform/Modules/Functions/Workers/Builds.php | 4 ++-- .../Platform/Modules/Sites/Http/Deployments/Create.php | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php index cda6dc38bf..1f3febbfef 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php @@ -182,7 +182,7 @@ class Create extends Action } } - if (!$fileSizeValidator->isValid($fileSize)) { // Check if file size is exceeding allowed limit + if (!$fileSizeValidator->isValid($fileSize) && $functionSizeLimit !== 0) { // Check if file size is exceeding allowed limit throw new Exception(Exception::STORAGE_INVALID_FILE_SIZE); } diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 6ff2161c1a..87481e91ea 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -486,7 +486,7 @@ class Builds extends Action $sizeLimit = (int) $plan['deploymentSize'] * 1000 * 1000; } - if ($directorySize > $sizeLimit) { + if ($directorySize > $sizeLimit && $sizeLimit !== 0) { throw new \Exception('Repository directory size should be less than ' . number_format($sizeLimit / (1000 * 1000), 2) . ' MBs.'); } @@ -816,7 +816,7 @@ class Builds extends Action if (isset($plan['buildSize'])) { $buildSizeLimit = $plan['buildSize'] * 1000 * 1000; } - if ($response['size'] > $buildSizeLimit) { + if ($response['size'] > $buildSizeLimit && $buildSizeLimit !== 0) { throw new \Exception('Build size should be less than ' . number_format($buildSizeLimit / (1000 * 1000), 2) . ' MBs.'); } diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php index afa1dba7d8..13b1e0c830 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php @@ -183,7 +183,7 @@ class Create extends Action } } - if (!$fileSizeValidator->isValid($fileSize)) { // Check if file size is exceeding allowed limit + if (!$fileSizeValidator->isValid($fileSize) && $siteSizeLimit !== 0) { // Check if file size is exceeding allowed limit throw new Exception(Exception::STORAGE_INVALID_FILE_SIZE); } From 04a9b0be348857dd001162d8ab0afa5060943799 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 23 May 2025 03:29:44 +1200 Subject: [PATCH 069/219] Fix replace --- CHANGES.md | 2 +- app/controllers/api/messaging.php | 2 +- app/init/database/filters.php | 2 +- composer.json | 2 +- composer.lock | 25 ++++++++++++++++--------- src/Appwrite/Deletes/Targets.php | 2 +- 6 files changed, 21 insertions(+), 14 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index fa4db4acc5..bc903e4b31 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -607,7 +607,7 @@ ### Fixes * Fix database exception wrapping by @abnegate in https://github.com/appwrite/appwrite/pull/7787 * Fix exception wrap order by @abnegate in https://github.com/appwrite/appwrite/pull/7818 -* Fix membership query to use sequence by @lohanidamodar in https://github.com/appwrite/appwrite/pull/7834 +* Fix membership query to use internalId by @lohanidamodar in https://github.com/appwrite/appwrite/pull/7834 * Fix vcs silent mode by @vermakhushboo in https://github.com/appwrite/appwrite/pull/7683 * Fix function domain permissions by @stnguyen90 in https://github.com/appwrite/appwrite/pull/7852 * Fix tests required for Cloud by @lohanidamodar in https://github.com/appwrite/appwrite/pull/7777 diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index c74314e905..0bc6f93787 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -2513,7 +2513,7 @@ App::post('/v1/messaging/topics/:topicId/subscribers') 'topicId' => $topicId, 'topicInternalId' => $topic->getSequence(), 'targetId' => $targetId, - 'targetSequence' => $target->getSequence(), + 'targetInternalId' => $target->getSequence(), 'userId' => $user->getId(), 'userInternalId' => $user->getSequence(), 'providerType' => $target->getAttribute('providerType'), diff --git a/app/init/database/filters.php b/app/init/database/filters.php index 7f2282747e..73ff7dc221 100644 --- a/app/init/database/filters.php +++ b/app/init/database/filters.php @@ -329,7 +329,7 @@ Database::addFilter( }, function (mixed $value, Document $document, Database $database) { $targetIds = Authorization::skip(fn () => \array_map( - fn ($document) => $document->getAttribute('targetSequence'), + fn ($document) => $document->getAttribute('targetInternalId'), $database->find('subscribers', [ Query::equal('topicInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBSCRIBERS_SUBQUERY) diff --git a/composer.json b/composer.json index 9a3c9e8319..7f3c4a574e 100644 --- a/composer.json +++ b/composer.json @@ -62,7 +62,7 @@ "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.6.*", "utopia-php/messaging": "0.17.*", - "utopia-php/migration": "0.9.*", + "utopia-php/migration": "dev-feat-sequence as 0.9.3", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", diff --git a/composer.lock b/composer.lock index 1d84acbb43..58b7d9d387 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "cb47e05e104d978efba67c3ccc7bf959", + "content-hash": "92b3f5ad47dd7b23394f27c18713c7e8", "packages": [ { "name": "adhocore/jwt", @@ -3999,16 +3999,16 @@ }, { "name": "utopia-php/migration", - "version": "0.9.3", + "version": "dev-feat-sequence", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "e518d39eb550fde36bc5cf06c9bd7b2faf5dbedd" + "reference": "bef2ad136a86a7747675e0e877f38a8ffe44c39f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/e518d39eb550fde36bc5cf06c9bd7b2faf5dbedd", - "reference": "e518d39eb550fde36bc5cf06c9bd7b2faf5dbedd", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/bef2ad136a86a7747675e0e877f38a8ffe44c39f", + "reference": "bef2ad136a86a7747675e0e877f38a8ffe44c39f", "shasum": "" }, "require": { @@ -4016,7 +4016,7 @@ "ext-curl": "*", "ext-openssl": "*", "php": ">=8.1", - "utopia-php/database": "0.*.*", + "utopia-php/database": "dev-feat-internal-to-sequence as 0.65.5", "utopia-php/dsn": "0.2.*", "utopia-php/framework": "0.33.*", "utopia-php/storage": "0.18.*" @@ -4049,9 +4049,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.9.3" + "source": "https://github.com/utopia-php/migration/tree/feat-sequence" }, - "time": "2025-05-01T05:41:26+00:00" + "time": "2025-05-22T15:27:01+00:00" }, { "name": "utopia-php/orchestration", @@ -8246,11 +8246,18 @@ "version": "dev-feat-internal-to-sequence", "alias": "0.69.5", "alias_normalized": "0.69.5.0" + }, + { + "package": "utopia-php/migration", + "version": "dev-feat-sequence", + "alias": "0.9.3", + "alias_normalized": "0.9.3.0" } ], "minimum-stability": "stable", "stability-flags": { - "utopia-php/database": 20 + "utopia-php/database": 20, + "utopia-php/migration": 20 }, "prefer-stable": false, "prefer-lowest": false, diff --git a/src/Appwrite/Deletes/Targets.php b/src/Appwrite/Deletes/Targets.php index 68a9d675b6..794ab0b87a 100644 --- a/src/Appwrite/Deletes/Targets.php +++ b/src/Appwrite/Deletes/Targets.php @@ -27,7 +27,7 @@ class Targets $database->deleteDocuments( 'subscribers', [ - Query::equal('targetSequence', [$target->getSequence()]), + Query::equal('targetInternalId', [$target->getSequence()]), Query::orderAsc(), ], Database::DELETE_BATCH_SIZE, From 0cccb7527351e3bc48a0fd01ac9fe437c1bea4ce Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Fri, 23 May 2025 12:05:42 +0530 Subject: [PATCH 070/219] added encrypt property in the attribute string response model --- app/controllers/api/databases.php | 6 ++++-- src/Appwrite/Utopia/Response/Model/AttributeString.php | 7 +++++++ tests/e2e/Services/Databases/DatabasesBase.php | 2 +- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index d495a1d924..786b498adf 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1372,10 +1372,12 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string 'array' => $array, 'filters' => $filters, ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - + $stringAttribute = $attribute->getArrayCopy(); + $stringAttribute['encrypt'] = $encrypt; + $stringAttribute = new Document($stringAttribute); $response ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($attribute, Response::MODEL_ATTRIBUTE_STRING); + ->dynamic($stringAttribute, Response::MODEL_ATTRIBUTE_STRING); }); App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email') diff --git a/src/Appwrite/Utopia/Response/Model/AttributeString.php b/src/Appwrite/Utopia/Response/Model/AttributeString.php index 12bb42009d..f5559f2206 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeString.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeString.php @@ -24,6 +24,13 @@ class AttributeString extends Attribute 'required' => false, 'example' => 'default', ]) + ->addRule('encrypt', [ + 'type' => self::TYPE_BOOLEAN, + 'description' => 'Encryption status for the string attribute. Encryption enhances security by not storing any plain text values in the database. However, encrypted attributes cannot be queried.', + 'default' => false, + 'required' => false, + 'example' => false, + ]) ; } diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 7c0060ecaa..9aed3684de 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -298,7 +298,7 @@ trait DatabasesBase $this->assertEquals($title['body']['type'], 'string'); $this->assertEquals($title['body']['size'], 256); $this->assertEquals($title['body']['required'], true); - + $this->assertFalse($title['body']['encrypt']); $this->assertEquals(202, $description['headers']['status-code']); $this->assertEquals($description['body']['key'], 'description'); $this->assertEquals($description['body']['type'], 'string'); From 1a4a10400b2b956a919cf2080fc43a0e7a1fdca3 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Fri, 23 May 2025 12:12:23 +0530 Subject: [PATCH 071/219] added test for the encrypted string in the server --- tests/e2e/Services/Databases/DatabasesCustomServerTest.php | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 67f7a07a9b..57dbd3d378 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -697,6 +697,7 @@ class DatabasesCustomServerTest extends Scope 'required' => true, 'encrypt' => true ]); + $this->assertTrue($lastName['body']['encrypt']); /** From 1d0577b07ded92cfca8336d48de8e6db1d2c1621 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Fri, 23 May 2025 12:51:59 +0530 Subject: [PATCH 072/219] added encrypt to the get and list atttributes --- app/controllers/api/databases.php | 18 +++++++++++++++--- .../Utopia/Response/Model/AttributeString.php | 2 +- .../Databases/DatabasesCustomServerTest.php | 13 ++++++++++++- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 786b498adf..8ed169baff 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2053,8 +2053,18 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') throw new Exception(Exception::GENERAL_QUERY_INVALID); } + $updatedAttributes = []; + + foreach ($attributes as $attribute) { + $filters = $attribute->getAttribute('filters', []); + $attributeArray = $attribute->getArrayCopy(); + $attributeArray['encrypt'] = in_array('encrypt', $filters); + $updatedAttribute = new Document($attributeArray); + $updatedAttributes[] = $updatedAttribute; + } + $response->dynamic(new Document([ - 'attributes' => $attributes, + 'attributes' => $updatedAttributes, 'total' => $total, ]), Response::MODEL_ATTRIBUTE_LIST); }); @@ -2117,7 +2127,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') $type = $attribute->getAttribute('type'); $format = $attribute->getAttribute('format'); $options = $attribute->getAttribute('options', []); - + $filters = $attribute->getAttribute('filters', []); foreach ($options as $key => $option) { $attribute->setAttribute($key, $option); } @@ -2137,7 +2147,9 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') }, default => Response::MODEL_ATTRIBUTE, }; - + $attribute = $attribute->getArrayCopy(); + $attribute['encrypt'] = in_array('encrypt', $filters); + $attribute = new Document($attribute); $response->dynamic($attribute, $model); }); diff --git a/src/Appwrite/Utopia/Response/Model/AttributeString.php b/src/Appwrite/Utopia/Response/Model/AttributeString.php index f5559f2206..fded48fddc 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeString.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeString.php @@ -26,7 +26,7 @@ class AttributeString extends Attribute ]) ->addRule('encrypt', [ 'type' => self::TYPE_BOOLEAN, - 'description' => 'Encryption status for the string attribute. Encryption enhances security by not storing any plain text values in the database. However, encrypted attributes cannot be queried.', + 'description' => 'Defines whether this attribute is encrypted or not.', 'default' => false, 'required' => false, 'example' => false, diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 57dbd3d378..d9cbc04250 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -698,8 +698,19 @@ class DatabasesCustomServerTest extends Scope 'encrypt' => true ]); $this->assertTrue($lastName['body']['encrypt']); + sleep(1); + $response = $this->client->call(Client::METHOD_GET, $attributesPath . '/lastName', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ])); + $this->assertTrue($response['body']['encrypt']); - + $response = $this->client->call(Client::METHOD_GET, $attributesPath, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ])); /** * Check status of every attribute */ From 02426df1cab7e0bf0a55f15e9097244c1e68799c Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Fri, 23 May 2025 12:53:10 +0530 Subject: [PATCH 073/219] linting --- tests/e2e/Services/Databases/DatabasesCustomServerTest.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index d9cbc04250..33e597dd87 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -706,11 +706,6 @@ class DatabasesCustomServerTest extends Scope ])); $this->assertTrue($response['body']['encrypt']); - $response = $this->client->call(Client::METHOD_GET, $attributesPath, array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], - ])); /** * Check status of every attribute */ From 14274d96aadb36a34b2318fd5b5a8b8e5bfa651c Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 23 May 2025 19:42:43 +1200 Subject: [PATCH 074/219] Update libs --- composer.json | 4 ++-- composer.lock | 48 ++++++++++++++++-------------------------------- 2 files changed, 18 insertions(+), 34 deletions(-) diff --git a/composer.json b/composer.json index 7f3c4a574e..9b61351956 100644 --- a/composer.json +++ b/composer.json @@ -53,7 +53,7 @@ "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", "utopia-php/detector": "0.1.*", - "utopia-php/database": "dev-feat-internal-to-sequence as 0.69.5", + "utopia-php/database": "0.71.*", "utopia-php/domains": "0.8.0", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", @@ -62,7 +62,7 @@ "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.6.*", "utopia-php/messaging": "0.17.*", - "utopia-php/migration": "dev-feat-sequence as 0.9.3", + "utopia-php/migration": "0.10.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", diff --git a/composer.lock b/composer.lock index 58b7d9d387..dc8661f3bb 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "92b3f5ad47dd7b23394f27c18713c7e8", + "content-hash": "5027a541e6377eb2c87357b69f11daea", "packages": [ { "name": "adhocore/jwt", @@ -3499,16 +3499,16 @@ }, { "name": "utopia-php/database", - "version": "dev-feat-internal-to-sequence", + "version": "0.71.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "0f3617e23bef7c6f260d7f8f194031c2f096a154" + "reference": "cf463c0a5c64a4168fe56266ace4ae835d61c920" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/0f3617e23bef7c6f260d7f8f194031c2f096a154", - "reference": "0f3617e23bef7c6f260d7f8f194031c2f096a154", + "url": "https://api.github.com/repos/utopia-php/database/zipball/cf463c0a5c64a4168fe56266ace4ae835d61c920", + "reference": "cf463c0a5c64a4168fe56266ace4ae835d61c920", "shasum": "" }, "require": { @@ -3549,9 +3549,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/feat-internal-to-sequence" + "source": "https://github.com/utopia-php/database/tree/0.71.0" }, - "time": "2025-05-22T13:09:40+00:00" + "time": "2025-05-23T07:32:59+00:00" }, { "name": "utopia-php/detector", @@ -3999,16 +3999,16 @@ }, { "name": "utopia-php/migration", - "version": "dev-feat-sequence", + "version": "0.10.0", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "bef2ad136a86a7747675e0e877f38a8ffe44c39f" + "reference": "0b0e94c4b5243c5566b9634b07ba2ec5f7990914" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/bef2ad136a86a7747675e0e877f38a8ffe44c39f", - "reference": "bef2ad136a86a7747675e0e877f38a8ffe44c39f", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/0b0e94c4b5243c5566b9634b07ba2ec5f7990914", + "reference": "0b0e94c4b5243c5566b9634b07ba2ec5f7990914", "shasum": "" }, "require": { @@ -4016,7 +4016,7 @@ "ext-curl": "*", "ext-openssl": "*", "php": ">=8.1", - "utopia-php/database": "dev-feat-internal-to-sequence as 0.65.5", + "utopia-php/database": "0.*.*", "utopia-php/dsn": "0.2.*", "utopia-php/framework": "0.33.*", "utopia-php/storage": "0.18.*" @@ -4049,9 +4049,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/feat-sequence" + "source": "https://github.com/utopia-php/migration/tree/0.10.0" }, - "time": "2025-05-22T15:27:01+00:00" + "time": "2025-05-23T07:40:24+00:00" }, { "name": "utopia-php/orchestration", @@ -8240,25 +8240,9 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [ - { - "package": "utopia-php/database", - "version": "dev-feat-internal-to-sequence", - "alias": "0.69.5", - "alias_normalized": "0.69.5.0" - }, - { - "package": "utopia-php/migration", - "version": "dev-feat-sequence", - "alias": "0.9.3", - "alias_normalized": "0.9.3.0" - } - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/database": 20, - "utopia-php/migration": 20 - }, + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { From 73764941b6bdcd3fc5ccd664e22977e92439a458 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Fri, 23 May 2025 13:23:33 +0530 Subject: [PATCH 075/219] updated tests and collection method --- app/controllers/api/databases.php | 31 ++++++++++--------- .../Databases/DatabasesCustomServerTest.php | 22 +++++++++++++ 2 files changed, 39 insertions(+), 14 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 8ed169baff..186ba4b08d 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1063,6 +1063,14 @@ App::get('/v1/databases/:databaseId/collections/:collectionId') throw new Exception(Exception::COLLECTION_NOT_FOUND); } + $attributes = $collection->getAttribute('attributes'); + foreach ($attributes as $attribute) { + if ($attribute->getAttribute('type') === Database::VAR_STRING) { + $filters = $attribute->getAttribute('filters', []); + $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); + } + } + $response->dynamic($collection, Response::MODEL_COLLECTION); }); @@ -1372,12 +1380,10 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string 'array' => $array, 'filters' => $filters, ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - $stringAttribute = $attribute->getArrayCopy(); - $stringAttribute['encrypt'] = $encrypt; - $stringAttribute = new Document($stringAttribute); + $attribute->setAttribute('encrypt', $encrypt); $response ->setStatusCode(Response::STATUS_CODE_ACCEPTED) - ->dynamic($stringAttribute, Response::MODEL_ATTRIBUTE_STRING); + ->dynamic($attribute, Response::MODEL_ATTRIBUTE_STRING); }); App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/email') @@ -2053,18 +2059,17 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') throw new Exception(Exception::GENERAL_QUERY_INVALID); } - $updatedAttributes = []; + foreach ($attributes as $attribute) { - $filters = $attribute->getAttribute('filters', []); - $attributeArray = $attribute->getArrayCopy(); - $attributeArray['encrypt'] = in_array('encrypt', $filters); - $updatedAttribute = new Document($attributeArray); - $updatedAttributes[] = $updatedAttribute; + if ($attribute->getAttribute('type') === Database::VAR_STRING) { + $filters = $attribute->getAttribute('filters', []); + $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); + } } $response->dynamic(new Document([ - 'attributes' => $updatedAttributes, + 'attributes' => $attributes, 'total' => $total, ]), Response::MODEL_ATTRIBUTE_LIST); }); @@ -2147,9 +2152,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') }, default => Response::MODEL_ATTRIBUTE, }; - $attribute = $attribute->getArrayCopy(); - $attribute['encrypt'] = in_array('encrypt', $filters); - $attribute = new Document($attribute); + $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); $response->dynamic($attribute, $model); }); diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 33e597dd87..3d5ba61585 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -748,6 +748,28 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $document['headers']['status-code']); $this->assertEquals('Jonah', $document['body']['firstName']); $this->assertEquals('Jameson', $document['body']['lastName']); + + + $actors = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), []); + $attributes = $actors['body']['attributes']; + $firstNameAttribute = null; + $lastNameAttribute = null; + foreach ($attributes as $attribute) { + $this->assertArrayHasKey('encrypt', $attribute); + if ($attribute['key'] === 'firstName') { + $firstNameAttribute = $attribute['encrypt']; + } + if ($attribute['key'] === 'lastName') { + $lastNameAttribute = $attribute['encrypt']; + } + } + $this->assertTrue($lastNameAttribute); + $this->assertFalse($firstNameAttribute); + } public function testDeleteAttribute(): array From 6ea35939217cca37e40fb9292ad6cfadb22974ee Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Fri, 23 May 2025 13:40:56 +0530 Subject: [PATCH 076/219] updated collection filter --- app/controllers/api/databases.php | 7 ------- app/init/database/filters.php | 7 ++++++- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 186ba4b08d..5cc1369f00 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1063,13 +1063,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attributes = $collection->getAttribute('attributes'); - foreach ($attributes as $attribute) { - if ($attribute->getAttribute('type') === Database::VAR_STRING) { - $filters = $attribute->getAttribute('filters', []); - $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); - } - } $response->dynamic($collection, Response::MODEL_COLLECTION); }); diff --git a/app/init/database/filters.php b/app/init/database/filters.php index f110fe1554..44fd748758 100644 --- a/app/init/database/filters.php +++ b/app/init/database/filters.php @@ -77,13 +77,18 @@ Database::addFilter( ]); foreach ($attributes as $attribute) { - if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { + $attributeType = $attribute->getAttribute('type'); + if ($attributeType === Database::VAR_RELATIONSHIP) { $options = $attribute->getAttribute('options'); foreach ($options as $key => $value) { $attribute->setAttribute($key, $value); } $attribute->removeAttribute('options'); } + if ($attributeType === Database::VAR_STRING) { + $filters = $attribute->getAttribute('filters', []); + $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); + } } return $attributes; From e586afceb74eca90d800323b10056b97db5a18c6 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Fri, 23 May 2025 14:11:57 +0530 Subject: [PATCH 077/219] updates --- app/controllers/api/databases.php | 1 - app/init/database/filters.php | 24 +++++++++++-------- .../Databases/DatabasesCustomServerTest.php | 8 ++----- 3 files changed, 16 insertions(+), 17 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 5cc1369f00..0d4e535b1b 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2053,7 +2053,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') } - foreach ($attributes as $attribute) { if ($attribute->getAttribute('type') === Database::VAR_STRING) { $filters = $attribute->getAttribute('filters', []); diff --git a/app/init/database/filters.php b/app/init/database/filters.php index 44fd748758..c470329706 100644 --- a/app/init/database/filters.php +++ b/app/init/database/filters.php @@ -78,16 +78,20 @@ Database::addFilter( foreach ($attributes as $attribute) { $attributeType = $attribute->getAttribute('type'); - if ($attributeType === Database::VAR_RELATIONSHIP) { - $options = $attribute->getAttribute('options'); - foreach ($options as $key => $value) { - $attribute->setAttribute($key, $value); - } - $attribute->removeAttribute('options'); - } - if ($attributeType === Database::VAR_STRING) { - $filters = $attribute->getAttribute('filters', []); - $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); + + switch ($attributeType) { + case Database::VAR_RELATIONSHIP: + $options = $attribute->getAttribute('options'); + foreach ($options as $key => $value) { + $attribute->setAttribute($key, $value); + } + $attribute->removeAttribute('options'); + break; + + case Database::VAR_STRING: + $filters = $attribute->getAttribute('filters', []); + $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); + break; } } diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 3d5ba61585..c0d8763aa7 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -756,19 +756,15 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-key' => $this->getProject()['apiKey'] ]), []); $attributes = $actors['body']['attributes']; - $firstNameAttribute = null; - $lastNameAttribute = null; foreach ($attributes as $attribute) { $this->assertArrayHasKey('encrypt', $attribute); if ($attribute['key'] === 'firstName') { - $firstNameAttribute = $attribute['encrypt']; + $this->assertFalse($attribute['encrypt']); } if ($attribute['key'] === 'lastName') { - $lastNameAttribute = $attribute['encrypt']; + $this->assertTrue($attribute['encrypt']); } } - $this->assertTrue($lastNameAttribute); - $this->assertFalse($firstNameAttribute); } From 7c760e4b07979fa94cdbbb13054928832704239c Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Fri, 23 May 2025 14:16:35 +0530 Subject: [PATCH 078/219] linting --- app/controllers/api/databases.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 0d4e535b1b..fba985fded 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1063,7 +1063,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId') throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $response->dynamic($collection, Response::MODEL_COLLECTION); }); From b8cb6f281d467bd41a5d7adde86b82134752877f Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Fri, 23 May 2025 14:19:00 +0530 Subject: [PATCH 079/219] linting --- app/controllers/api/databases.php | 1 - 1 file changed, 1 deletion(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index fba985fded..75f89d5733 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2051,7 +2051,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') throw new Exception(Exception::GENERAL_QUERY_INVALID); } - foreach ($attributes as $attribute) { if ($attribute->getAttribute('type') === Database::VAR_STRING) { $filters = $attribute->getAttribute('filters', []); From bc778f507d38f36ce239e1afa1e75ff791a98193 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 23 May 2025 22:51:20 +1200 Subject: [PATCH 080/219] Update to sequence --- .../Utopia/Response/Model/Document.php | 8 ++++---- .../e2e/Services/Databases/DatabasesBase.php | 20 +++++++++---------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/Appwrite/Utopia/Response/Model/Document.php b/src/Appwrite/Utopia/Response/Model/Document.php index 6c4e92b983..d43ab0d1e6 100644 --- a/src/Appwrite/Utopia/Response/Model/Document.php +++ b/src/Appwrite/Utopia/Response/Model/Document.php @@ -36,11 +36,11 @@ class Document extends Any 'default' => '', 'example' => '5e5ea5c16897e', ]) - ->addRule('$internalId', [ + ->addRule('$sequence', [ 'type' => self::TYPE_INTEGER, - 'description' => 'Auto increment integer.', - 'default' => '', - 'example' => '1', + 'description' => 'Document automatically incrementing ID.', + 'default' => 0, + 'example' => 1, ]) ->addRule('$collectionId', [ 'type' => self::TYPE_STRING, diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index b62ff224fb..f80f9dae0a 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -1645,7 +1645,7 @@ trait DatabasesBase $this->assertEquals($document1['body']['actors'][0], 'Chris Evans'); $this->assertEquals($document1['body']['actors'][1], 'Samuel Jackson'); $this->assertEquals($document1['body']['birthDay'], '1975-06-12T12:12:55.000+00:00'); - $this->assertTrue(array_key_exists('$internalId', $document1['body'])); + $this->assertTrue(array_key_exists('$sequence', $document1['body'])); $this->assertEquals(201, $document2['headers']['status-code']); $this->assertEquals($data['moviesId'], $document2['body']['$collectionId']); @@ -1663,7 +1663,7 @@ trait DatabasesBase $this->assertEquals($document2['body']['birthDay'], null); $this->assertEquals($document2['body']['integers'][0], 50); $this->assertEquals($document2['body']['integers'][1], 60); - $this->assertTrue(array_key_exists('$internalId', $document2['body'])); + $this->assertTrue(array_key_exists('$sequence', $document2['body'])); $this->assertEquals(201, $document3['headers']['status-code']); $this->assertEquals($data['moviesId'], $document3['body']['$collectionId']); @@ -1678,7 +1678,7 @@ trait DatabasesBase $this->assertEquals($document3['body']['actors'][0], 'Tom Holland'); $this->assertEquals($document3['body']['actors'][1], 'Zendaya Maree Stoermer'); $this->assertEquals($document3['body']['birthDay'], '1975-06-12T18:12:55.000+00:00'); // UTC for NY - $this->assertTrue(array_key_exists('$internalId', $document3['body'])); + $this->assertTrue(array_key_exists('$sequence', $document3['body'])); $this->assertEquals(400, $document4['headers']['status-code']); @@ -2128,7 +2128,7 @@ trait DatabasesBase $this->assertEquals($document['title'], $response['body']['title']); $this->assertEquals($document['releaseYear'], $response['body']['releaseYear']); $this->assertArrayNotHasKey('birthDay', $response['body']); - $this->assertFalse(array_key_exists('$internalId', $response['body'])); + $this->assertFalse(array_key_exists('$sequence', $response['body'])); // selecting internal id as well $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$collectionId'] . '/documents/' . $document['$id'], array_merge([ @@ -2136,7 +2136,7 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::select(['title', 'releaseYear', '$id','$internalId'])->toString(), + Query::select(['title', 'releaseYear', '$id','$sequence'])->toString(), ], ]); @@ -2144,23 +2144,23 @@ trait DatabasesBase $this->assertEquals($document['title'], $response['body']['title']); $this->assertEquals($document['releaseYear'], $response['body']['releaseYear']); $this->assertArrayNotHasKey('birthDay', $response['body']); - $this->assertTrue(array_key_exists('$internalId', $response['body'])); - $internalId = $response['body']['$internalId']; + $this->assertTrue(array_key_exists('$sequence', $response['body'])); + $sequence = $response['body']['$sequence']; - // Query by internalId + // Query by sequence $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$collectionId'] . '/documents/' . $document['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'queries' => [ - Query::equal('$internalId', [$internalId]) + Query::equal('$sequence', [$sequence]) ], ]); $this->assertEquals(200, $response['headers']['status-code']); $this->assertEquals($document['title'], $response['body']['title']); $this->assertEquals($document['releaseYear'], $response['body']['releaseYear']); - $this->assertTrue(array_key_exists('$internalId', $response['body'])); + $this->assertTrue(array_key_exists('$sequence', $response['body'])); } /** From a8fb467df7f5ea4211bb126b819d559f030dde99 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 23 May 2025 22:53:08 +1200 Subject: [PATCH 081/219] Update test --- tests/e2e/Services/Databases/DatabasesBase.php | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index f80f9dae0a..6038448889 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -2114,7 +2114,6 @@ trait DatabasesBase $databaseId = $data['databaseId']; $document = $data['documents'][0]; - // not selecting internal id $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$collectionId'] . '/documents/' . $document['$id'], array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], @@ -2128,23 +2127,6 @@ trait DatabasesBase $this->assertEquals($document['title'], $response['body']['title']); $this->assertEquals($document['releaseYear'], $response['body']['releaseYear']); $this->assertArrayNotHasKey('birthDay', $response['body']); - $this->assertFalse(array_key_exists('$sequence', $response['body'])); - - // selecting internal id as well - $response = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $document['$collectionId'] . '/documents/' . $document['$id'], array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'queries' => [ - Query::select(['title', 'releaseYear', '$id','$sequence'])->toString(), - ], - ]); - - $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals($document['title'], $response['body']['title']); - $this->assertEquals($document['releaseYear'], $response['body']['releaseYear']); - $this->assertArrayNotHasKey('birthDay', $response['body']); - $this->assertTrue(array_key_exists('$sequence', $response['body'])); $sequence = $response['body']['$sequence']; // Query by sequence From 1a2a725cb0eb7fe7489bb8a10f4577df9cd6e16c Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 23 May 2025 09:03:42 +0000 Subject: [PATCH 082/219] Merge pull request #9868 from ArnabChatterjee20k/dat-532 added encrypt property in the attribute string response model --- app/controllers/api/databases.php | 13 ++++++--- app/init/database/filters.php | 21 ++++++++++----- .../Utopia/Response/Model/AttributeString.php | 7 +++++ .../e2e/Services/Databases/DatabasesBase.php | 2 +- .../Databases/DatabasesCustomServerTest.php | 27 ++++++++++++++++++- 5 files changed, 59 insertions(+), 11 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 68d8891067..9c4b8e7668 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1368,7 +1368,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string 'array' => $array, 'filters' => $filters, ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - + $attribute->setAttribute('encrypt', $encrypt); $response ->setStatusCode(Response::STATUS_CODE_ACCEPTED) ->dynamic($attribute, Response::MODEL_ATTRIBUTE_STRING); @@ -2047,6 +2047,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') throw new Exception(Exception::GENERAL_QUERY_INVALID); } + foreach ($attributes as $attribute) { + if ($attribute->getAttribute('type') === Database::VAR_STRING) { + $filters = $attribute->getAttribute('filters', []); + $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); + } + } + $response->dynamic(new Document([ 'attributes' => $attributes, 'total' => $total, @@ -2111,7 +2118,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') $type = $attribute->getAttribute('type'); $format = $attribute->getAttribute('format'); $options = $attribute->getAttribute('options', []); - + $filters = $attribute->getAttribute('filters', []); foreach ($options as $key => $option) { $attribute->setAttribute($key, $option); } @@ -2131,7 +2138,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') }, default => Response::MODEL_ATTRIBUTE, }; - + $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); $response->dynamic($attribute, $model); }); diff --git a/app/init/database/filters.php b/app/init/database/filters.php index 8223b1c677..49d7845699 100644 --- a/app/init/database/filters.php +++ b/app/init/database/filters.php @@ -77,12 +77,21 @@ Database::addFilter( ]); foreach ($attributes as $attribute) { - if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { - $options = $attribute->getAttribute('options'); - foreach ($options as $key => $value) { - $attribute->setAttribute($key, $value); - } - $attribute->removeAttribute('options'); + $attributeType = $attribute->getAttribute('type'); + + switch ($attributeType) { + case Database::VAR_RELATIONSHIP: + $options = $attribute->getAttribute('options'); + foreach ($options as $key => $value) { + $attribute->setAttribute($key, $value); + } + $attribute->removeAttribute('options'); + break; + + case Database::VAR_STRING: + $filters = $attribute->getAttribute('filters', []); + $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); + break; } } diff --git a/src/Appwrite/Utopia/Response/Model/AttributeString.php b/src/Appwrite/Utopia/Response/Model/AttributeString.php index 12bb42009d..fded48fddc 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeString.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeString.php @@ -24,6 +24,13 @@ class AttributeString extends Attribute 'required' => false, 'example' => 'default', ]) + ->addRule('encrypt', [ + 'type' => self::TYPE_BOOLEAN, + 'description' => 'Defines whether this attribute is encrypted or not.', + 'default' => false, + 'required' => false, + 'example' => false, + ]) ; } diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 7c0060ecaa..9aed3684de 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -298,7 +298,7 @@ trait DatabasesBase $this->assertEquals($title['body']['type'], 'string'); $this->assertEquals($title['body']['size'], 256); $this->assertEquals($title['body']['required'], true); - + $this->assertFalse($title['body']['encrypt']); $this->assertEquals(202, $description['headers']['status-code']); $this->assertEquals($description['body']['key'], 'description'); $this->assertEquals($description['body']['type'], 'string'); diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 829960b54f..bae86066ee 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -697,7 +697,14 @@ class DatabasesCustomServerTest extends Scope 'required' => true, 'encrypt' => true, ]); - + $this->assertTrue($lastName['body']['encrypt']); + sleep(1); + $response = $this->client->call(Client::METHOD_GET, $attributesPath . '/lastName', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ])); + $this->assertTrue($response['body']['encrypt']); /** * Check status of every attribute @@ -741,6 +748,24 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $document['headers']['status-code']); $this->assertEquals('Jonah', $document['body']['firstName']); $this->assertEquals('Jameson', $document['body']['lastName']); + + + $actors = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), []); + $attributes = $actors['body']['attributes']; + foreach ($attributes as $attribute) { + $this->assertArrayHasKey('encrypt', $attribute); + if ($attribute['key'] === 'firstName') { + $this->assertFalse($attribute['encrypt']); + } + if ($attribute['key'] === 'lastName') { + $this->assertTrue($attribute['encrypt']); + } + } + } public function testDeleteAttribute(): array From d27dba05d2b3bfe309a1b7e0eeb136d1ffc0e2a0 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 21 May 2025 08:51:31 +0000 Subject: [PATCH 083/219] Merge pull request #9841 from ArnabChatterjee20k/dat-532 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit added checking for encrypt and plan allowing encryption of string att… --- app/controllers/api/databases.php | 6 +++++- tests/e2e/Services/Databases/DatabasesCustomServerTest.php | 2 +- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 9c4b8e7668..54a4c565f4 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1347,7 +1347,11 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + ->inject('plan') + ->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, array $plan) { + if ($encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string attributes are not available on your plan. Please upgrade to create encrypted string attributes.'); + } // Ensure attribute default is within required size $validator = new Text($size, 0); if (!is_null($default) && !$validator->isValid($default)) { diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index bae86066ee..c0d8763aa7 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -695,7 +695,7 @@ class DatabasesCustomServerTest extends Scope 'key' => 'lastName', 'size' => 256, 'required' => true, - 'encrypt' => true, + 'encrypt' => true ]); $this->assertTrue($lastName['body']['encrypt']); sleep(1); From 098f891f7cc5206b5fa6d367d21461cb0b090c20 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Fri, 23 May 2025 14:25:23 +0100 Subject: [PATCH 084/219] feat: add builds worker group --- src/Appwrite/Platform/Workers/Builds.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Appwrite/Platform/Workers/Builds.php b/src/Appwrite/Platform/Workers/Builds.php index 4057d4b190..59d9abacb8 100644 --- a/src/Appwrite/Platform/Workers/Builds.php +++ b/src/Appwrite/Platform/Workers/Builds.php @@ -46,6 +46,7 @@ class Builds extends Action { $this ->desc('Builds worker') + ->groups(['builds']) ->inject('message') ->inject('project') ->inject('dbForPlatform') From 18335ebf892e23f20587f0c2376cccd8dbe9e63b Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Fri, 23 May 2025 14:29:31 +0100 Subject: [PATCH 085/219] feat: add builds worker group --- src/Appwrite/Platform/Modules/Functions/Workers/Builds.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 980e49fcad..a01250c05a 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -57,6 +57,7 @@ class Builds extends Action { $this ->desc('Builds worker') + ->groups(['builds']) ->inject('message') ->inject('project') ->inject('dbForPlatform') From 65a220b70274a1405727b074fb547e648e3fc430 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Fri, 23 May 2025 20:11:27 +0530 Subject: [PATCH 086/219] Fix URL for view logs in github comment --- src/Appwrite/Vcs/Comment.php | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Appwrite/Vcs/Comment.php b/src/Appwrite/Vcs/Comment.php index 62f6ef61d0..7c550ad528 100644 --- a/src/Appwrite/Vcs/Comment.php +++ b/src/Appwrite/Vcs/Comment.php @@ -36,6 +36,7 @@ class Comment $this->builds[$id] = [ 'projectName' => $project->getAttribute('name'), 'projectId' => $project->getId(), + 'region' => $project->getAttribute('region', 'default'), 'resourceName' => $resource->getAttribute('name'), 'resourceId' => $resource->getId(), 'resourceType' => $resourceType, @@ -66,6 +67,7 @@ class Comment if ($build['resourceType'] === 'site') { $projects[$build['projectId']]['site'][$build['resourceId']] = [ 'name' => $build['resourceName'], + 'region' => $build['region'], 'status' => $build['buildStatus'], 'deploymentId' => $build['deploymentId'], 'action' => $build['action'], @@ -74,6 +76,7 @@ class Comment } elseif ($build['resourceType'] === 'function') { $projects[$build['projectId']]['function'][$build['resourceId']] = [ 'name' => $build['resourceName'], + 'region' => $build['region'], 'status' => $build['buildStatus'], 'deploymentId' => $build['deploymentId'], 'action' => $build['action'], @@ -114,7 +117,7 @@ class Comment }; if ($site['action']['type'] === 'logs') { - $action = '[View Logs](' . $protocol . '://' . $hostname . '/console/project-' . $projectId . '/sites/site-' . $siteId . '/deployments/deployment-' . $site['deploymentId'] . ')'; + $action = '[View Logs](' . $protocol . '://' . $hostname . '/console/project-' . $site['region'] . '-' . $projectId . '/sites/site-' . $siteId . '/deployments/deployment-' . $site['deploymentId'] . ')'; } else { $action = '[Authorize](' . $site['action']['url'] . ')'; } @@ -146,12 +149,12 @@ class Comment $text .= "| :- | :- | :- | :- |\n"; foreach ($project['function'] as $functionId => $function) { - $extension = $site['status'] === 'building' ? 'gif' : 'png'; + $extension = $function['status'] === 'building' ? 'gif' : 'png'; - $pathLight = '/images/vcs/status-' . $site['status'] . '-light.' . $extension; - $pathDark = '/images/vcs/status-' . $site['status'] . '-dark.' . $extension; + $pathLight = '/images/vcs/status-' . $function['status'] . '-light.' . $extension; + $pathDark = '/images/vcs/status-' . $function['status'] . '-dark.' . $extension; - $status = match ($site['status']) { + $status = match ($function['status']) { 'waiting' => $this->generatImage($pathLight, $pathDark, 'Queued', 85) . ' _Queued_', 'processing' => $this->generatImage($pathLight, $pathDark, 'Processing', 85) . ' _Processing_', 'building' => $this->generatImage($pathLight, $pathDark, 'Building', 85) . ' _Building_', @@ -160,7 +163,7 @@ class Comment }; if ($function['action']['type'] === 'logs') { - $action = '[View Logs](' . $protocol . '://' . $hostname . '/console/project-' . $projectId . '/functions/function-' . $functionId . '/deployment-' . $function['deploymentId'] . ')'; + $action = '[View Logs](' . $protocol . '://' . $hostname . '/console/project-' . $function['region'] . '-' . $projectId . '/functions/function-' . $functionId . '/deployment-' . $function['deploymentId'] . ')'; } else { $action = '[Authorize](' . $function['action']['url'] . ')'; } From 70feb72de0332c6e1a5b652116285df0294a5d77 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sat, 24 May 2025 03:04:46 +1200 Subject: [PATCH 087/219] Revert "Feat sync encrypt updates" --- app/controllers/api/databases.php | 19 +++--------- app/init/database/filters.php | 21 ++++---------- .../Utopia/Response/Model/AttributeString.php | 7 ----- .../e2e/Services/Databases/DatabasesBase.php | 2 +- .../Databases/DatabasesCustomServerTest.php | 29 ++----------------- 5 files changed, 13 insertions(+), 65 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 54a4c565f4..68d8891067 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1347,11 +1347,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('plan') - ->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, array $plan) { - if ($encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) { - throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string attributes are not available on your plan. Please upgrade to create encrypted string attributes.'); - } + ->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { // Ensure attribute default is within required size $validator = new Text($size, 0); if (!is_null($default) && !$validator->isValid($default)) { @@ -1372,7 +1368,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string 'array' => $array, 'filters' => $filters, ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - $attribute->setAttribute('encrypt', $encrypt); + $response ->setStatusCode(Response::STATUS_CODE_ACCEPTED) ->dynamic($attribute, Response::MODEL_ATTRIBUTE_STRING); @@ -2051,13 +2047,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') throw new Exception(Exception::GENERAL_QUERY_INVALID); } - foreach ($attributes as $attribute) { - if ($attribute->getAttribute('type') === Database::VAR_STRING) { - $filters = $attribute->getAttribute('filters', []); - $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); - } - } - $response->dynamic(new Document([ 'attributes' => $attributes, 'total' => $total, @@ -2122,7 +2111,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') $type = $attribute->getAttribute('type'); $format = $attribute->getAttribute('format'); $options = $attribute->getAttribute('options', []); - $filters = $attribute->getAttribute('filters', []); + foreach ($options as $key => $option) { $attribute->setAttribute($key, $option); } @@ -2142,7 +2131,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') }, default => Response::MODEL_ATTRIBUTE, }; - $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); + $response->dynamic($attribute, $model); }); diff --git a/app/init/database/filters.php b/app/init/database/filters.php index 49d7845699..8223b1c677 100644 --- a/app/init/database/filters.php +++ b/app/init/database/filters.php @@ -77,21 +77,12 @@ Database::addFilter( ]); foreach ($attributes as $attribute) { - $attributeType = $attribute->getAttribute('type'); - - switch ($attributeType) { - case Database::VAR_RELATIONSHIP: - $options = $attribute->getAttribute('options'); - foreach ($options as $key => $value) { - $attribute->setAttribute($key, $value); - } - $attribute->removeAttribute('options'); - break; - - case Database::VAR_STRING: - $filters = $attribute->getAttribute('filters', []); - $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); - break; + if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { + $options = $attribute->getAttribute('options'); + foreach ($options as $key => $value) { + $attribute->setAttribute($key, $value); + } + $attribute->removeAttribute('options'); } } diff --git a/src/Appwrite/Utopia/Response/Model/AttributeString.php b/src/Appwrite/Utopia/Response/Model/AttributeString.php index fded48fddc..12bb42009d 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeString.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeString.php @@ -24,13 +24,6 @@ class AttributeString extends Attribute 'required' => false, 'example' => 'default', ]) - ->addRule('encrypt', [ - 'type' => self::TYPE_BOOLEAN, - 'description' => 'Defines whether this attribute is encrypted or not.', - 'default' => false, - 'required' => false, - 'example' => false, - ]) ; } diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 9aed3684de..7c0060ecaa 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -298,7 +298,7 @@ trait DatabasesBase $this->assertEquals($title['body']['type'], 'string'); $this->assertEquals($title['body']['size'], 256); $this->assertEquals($title['body']['required'], true); - $this->assertFalse($title['body']['encrypt']); + $this->assertEquals(202, $description['headers']['status-code']); $this->assertEquals($description['body']['key'], 'description'); $this->assertEquals($description['body']['type'], 'string'); diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index c0d8763aa7..829960b54f 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -695,16 +695,9 @@ class DatabasesCustomServerTest extends Scope 'key' => 'lastName', 'size' => 256, 'required' => true, - 'encrypt' => true + 'encrypt' => true, ]); - $this->assertTrue($lastName['body']['encrypt']); - sleep(1); - $response = $this->client->call(Client::METHOD_GET, $attributesPath . '/lastName', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], - ])); - $this->assertTrue($response['body']['encrypt']); + /** * Check status of every attribute @@ -748,24 +741,6 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $document['headers']['status-code']); $this->assertEquals('Jonah', $document['body']['firstName']); $this->assertEquals('Jameson', $document['body']['lastName']); - - - $actors = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'], array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] - ]), []); - $attributes = $actors['body']['attributes']; - foreach ($attributes as $attribute) { - $this->assertArrayHasKey('encrypt', $attribute); - if ($attribute['key'] === 'firstName') { - $this->assertFalse($attribute['encrypt']); - } - if ($attribute['key'] === 'lastName') { - $this->assertTrue($attribute['encrypt']); - } - } - } public function testDeleteAttribute(): array From 14fe7a32939a3f5140cb847d86da477efc02dae5 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Fri, 23 May 2025 20:35:59 +0530 Subject: [PATCH 088/219] updated errro for the string encryption --- app/controllers/api/databases.php | 3 +++ .../Services/Databases/DatabasesCustomServerTest.php | 12 ++++++++++++ 2 files changed, 15 insertions(+) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 75f89d5733..c57c29d9a2 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1352,6 +1352,9 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string if ($encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string attributes are not available on your plan. Please upgrade to create encrypted string attributes.'); } + if ($encrypt && $size < 150) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Size too small. Encrypted strings require a minimum size of 150 characters.'); + } // Ensure attribute default is within required size $validator = new Text($size, 0); if (!is_null($default) && !$validator->isValid($default)) { diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index c0d8763aa7..25c7e30a4f 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -686,6 +686,18 @@ class DatabasesCustomServerTest extends Scope 'size' => 256, 'required' => true, ]); + // checking size test + $lastName = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'lastName', + 'size' => 149, + 'required' => true, + 'encrypt' => true + ]); + $this->assertEquals('Size too small. Encrypted strings require a minimum size of 150 characters.', $lastName['body']['message']); $lastName = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([ 'content-type' => 'application/json', From 6af9d1206d63b50d2970d59445b86c8b5d8b4328 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Fri, 23 May 2025 20:41:08 +0530 Subject: [PATCH 089/219] added a constant --- app/controllers/api/databases.php | 2 +- app/init/constants.php | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index c57c29d9a2..b38596239c 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1352,7 +1352,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string if ($encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string attributes are not available on your plan. Please upgrade to create encrypted string attributes.'); } - if ($encrypt && $size < 150) { + if ($encrypt && $size < APP_DATABASE_ENCRYPT_SIZE_MIN) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Size too small. Encrypted strings require a minimum size of 150 characters.'); } // Ensure attribute default is within required size diff --git a/app/init/constants.php b/app/init/constants.php index 7686759719..4699014925 100644 --- a/app/init/constants.php +++ b/app/init/constants.php @@ -51,6 +51,7 @@ const APP_DATABASE_TIMEOUT_MILLISECONDS_API = 15 * 1000; // 15 seconds const APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER = 300 * 1000; // 5 minutes const APP_DATABASE_TIMEOUT_MILLISECONDS_TASK = 300 * 1000; // 5 minutes const APP_DATABASE_QUERY_MAX_VALUES = 500; +const APP_DATABASE_ENCRYPT_SIZE_MIN = 150; const APP_STORAGE_UPLOADS = '/storage/uploads'; const APP_STORAGE_SITES = '/storage/sites'; const APP_STORAGE_FUNCTIONS = '/storage/functions'; From 49f8369fdd3ecb02337a36f8127fed4865a4090f Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k Date: Fri, 23 May 2025 20:45:36 +0530 Subject: [PATCH 090/219] updated the message --- app/controllers/api/databases.php | 5 ++++- tests/e2e/Services/Databases/DatabasesCustomServerTest.php | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index b38596239c..7eb3273c38 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1353,7 +1353,10 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string attributes are not available on your plan. Please upgrade to create encrypted string attributes.'); } if ($encrypt && $size < APP_DATABASE_ENCRYPT_SIZE_MIN) { - throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Size too small. Encrypted strings require a minimum size of 150 characters.'); + throw new Exception( + Exception::GENERAL_BAD_REQUEST, + "Size too small. Encrypted strings require a minimum size of " . APP_DATABASE_ENCRYPT_SIZE_MIN . " characters." + ); } // Ensure attribute default is within required size $validator = new Text($size, 0); diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 25c7e30a4f..e66207b215 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -697,7 +697,7 @@ class DatabasesCustomServerTest extends Scope 'required' => true, 'encrypt' => true ]); - $this->assertEquals('Size too small. Encrypted strings require a minimum size of 150 characters.', $lastName['body']['message']); + $this->assertEquals("Size too small. Encrypted strings require a minimum size of " . APP_DATABASE_ENCRYPT_SIZE_MIN . " characters.", $lastName['body']['message']); $lastName = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([ 'content-type' => 'application/json', From 28d2ed1baa69499c2377240617588b2ced2611e5 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Fri, 23 May 2025 21:39:56 +0400 Subject: [PATCH 091/219] Revert "Feat sequence" --- CONTRIBUTING.md | 10 +- app/cli.php | 12 +- app/config/console.php | 2 +- app/controllers/api/account.php | 70 ++--- app/controllers/api/avatars.php | 12 +- app/controllers/api/databases.php | 260 +++++++++--------- app/controllers/api/health.php | 9 +- app/controllers/api/messaging.php | 28 +- app/controllers/api/migrations.php | 2 +- app/controllers/api/project.php | 18 +- app/controllers/api/projects.php | 46 ++-- app/controllers/api/proxy.php | 8 +- app/controllers/api/storage.php | 80 +++--- app/controllers/api/teams.php | 24 +- app/controllers/api/users.php | 30 +- app/controllers/api/vcs.php | 32 +-- app/controllers/general.php | 20 +- app/controllers/mock.php | 4 +- app/controllers/shared/api.php | 8 +- app/http.php | 4 +- app/init/database/filters.php | 30 +- app/init/resources.php | 22 +- app/realtime.php | 10 +- app/worker.php | 16 +- composer.json | 4 +- composer.lock | 62 ++--- src/Appwrite/Deletes/Targets.php | 4 +- src/Appwrite/Event/Event.php | 2 +- src/Appwrite/Migration/Migration.php | 12 +- src/Appwrite/Migration/Version/V15.php | 30 +- src/Appwrite/Migration/Version/V16.php | 2 +- src/Appwrite/Migration/Version/V17.php | 4 +- src/Appwrite/Migration/Version/V18.php | 16 +- src/Appwrite/Migration/Version/V19.php | 24 +- src/Appwrite/Migration/Version/V20.php | 24 +- src/Appwrite/Migration/Version/V21.php | 8 +- src/Appwrite/Migration/Version/V22.php | 8 +- .../Platform/Modules/Compute/Base.php | 20 +- .../Functions/Http/Deployments/Create.php | 8 +- .../Functions/Http/Deployments/Delete.php | 4 +- .../Http/Deployments/Duplicate/Create.php | 6 +- .../Http/Deployments/Status/Update.php | 2 +- .../Http/Deployments/Template/Create.php | 4 +- .../Functions/Http/Deployments/XList.php | 2 +- .../Functions/Http/Executions/Create.php | 14 +- .../Functions/Http/Executions/Delete.php | 2 +- .../Modules/Functions/Http/Executions/Get.php | 2 +- .../Functions/Http/Executions/XList.php | 2 +- .../Functions/Http/Functions/Create.php | 26 +- .../Http/Functions/Deployment/Update.php | 6 +- .../Functions/Http/Functions/Update.php | 14 +- .../Modules/Functions/Http/Usage/Get.php | 22 +- .../Functions/Http/Variables/Create.php | 2 +- .../Functions/Http/Variables/Delete.php | 2 +- .../Modules/Functions/Http/Variables/Get.php | 2 +- .../Functions/Http/Variables/Update.php | 2 +- .../Modules/Functions/Workers/Builds.php | 74 ++--- .../Modules/Projects/Http/DevKeys/Create.php | 2 +- .../Modules/Projects/Http/DevKeys/Delete.php | 2 +- .../Modules/Projects/Http/DevKeys/Get.php | 2 +- .../Modules/Projects/Http/DevKeys/Update.php | 2 +- .../Modules/Projects/Http/DevKeys/XList.php | 2 +- .../Modules/Proxy/Http/Rules/API/Create.php | 2 +- .../Proxy/Http/Rules/Function/Create.php | 6 +- .../Proxy/Http/Rules/Redirect/Create.php | 2 +- .../Modules/Proxy/Http/Rules/Site/Create.php | 6 +- .../Modules/Sites/Http/Deployments/Create.php | 16 +- .../Modules/Sites/Http/Deployments/Delete.php | 4 +- .../Http/Deployments/Duplicate/Create.php | 12 +- .../Sites/Http/Deployments/Status/Update.php | 2 +- .../Http/Deployments/Template/Create.php | 10 +- .../Modules/Sites/Http/Deployments/XList.php | 2 +- .../Modules/Sites/Http/Logs/Delete.php | 2 +- .../Platform/Modules/Sites/Http/Logs/Get.php | 2 +- .../Modules/Sites/Http/Logs/XList.php | 2 +- .../Modules/Sites/Http/Sites/Create.php | 10 +- .../Sites/Http/Sites/Deployment/Update.php | 6 +- .../Modules/Sites/Http/Sites/Update.php | 14 +- .../Platform/Modules/Sites/Http/Usage/Get.php | 28 +- .../Modules/Sites/Http/Variables/Create.php | 2 +- .../Modules/Sites/Http/Variables/Delete.php | 2 +- .../Modules/Sites/Http/Variables/Get.php | 2 +- .../Modules/Sites/Http/Variables/Update.php | 2 +- .../Http/Tokens/Buckets/Files/Action.php | 4 +- .../Http/Tokens/Buckets/Files/Create.php | 2 +- .../Http/Tokens/Buckets/Files/XList.php | 2 +- src/Appwrite/Platform/Tasks/ScheduleBase.php | 10 +- .../Platform/Tasks/ScheduleExecutions.php | 4 +- .../Platform/Tasks/ScheduleMessages.php | 2 +- .../Platform/Tasks/StatsResources.php | 2 +- src/Appwrite/Platform/Workers/Audits.php | 14 +- .../Platform/Workers/Certificates.php | 2 +- src/Appwrite/Platform/Workers/Databases.php | 44 +-- src/Appwrite/Platform/Workers/Deletes.php | 42 +-- src/Appwrite/Platform/Workers/Functions.php | 12 +- src/Appwrite/Platform/Workers/Messaging.php | 4 +- src/Appwrite/Platform/Workers/Migrations.php | 2 +- .../Platform/Workers/StatsResources.php | 70 ++--- src/Appwrite/Platform/Workers/StatsUsage.php | 46 ++-- .../Platform/Workers/StatsUsageDump.php | 4 +- src/Appwrite/Platform/Workers/Webhooks.php | 4 +- .../Database/Validator/Queries/Base.php | 6 +- .../Utopia/Response/Model/Document.php | 2 +- .../e2e/Services/Databases/DatabasesBase.php | 12 +- 104 files changed, 802 insertions(+), 805 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 277a509447..7746ef99af 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -415,8 +415,8 @@ In addition, you will also need to add some logic to the `reduce()` method of th ```php case $document->getCollection() === 'buckets': - $files = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getSequence(), METRIC_BUCKET_ID_FILES))); - $storage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getSequence(), METRIC_BUCKET_ID_FILES_STORAGE))); + $files = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES))); + $storage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE))); if (!empty($files['value'])) { $metrics[] = [ @@ -463,9 +463,9 @@ $queueForStatsUsage ->addMetric(METRIC_BUILDS, 1) ->addMetric(METRIC_BUILDS_STORAGE, $build->getAttribute('size', 0)) ->addMetric(METRIC_BUILDS_COMPUTE, (int)$build->getAttribute('duration', 0) * 1000) - ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS), 1) - ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_STORAGE), $build->getAttribute('size', 0)) - ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int)$build->getAttribute('duration', 0) * 1000) + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS), 1) + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE), $build->getAttribute('size', 0)) + ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int)$build->getAttribute('duration', 0) * 1000) ->setProject($project) ->trigger(); ``` diff --git a/app/cli.php b/app/cli.php index 224f150a58..9517347420 100644 --- a/app/cli.php +++ b/app/cli.php @@ -125,13 +125,13 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getSequence()) + ->setTenant($project->getInternalId()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getSequence()); + ->setNamespace('_' . $project->getInternalId()); } return $database; @@ -145,13 +145,13 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getSequence()) + ->setTenant($project->getInternalId()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getSequence()); + ->setNamespace('_' . $project->getInternalId()); } $database @@ -167,7 +167,7 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) { return function (?Document $project = null) use ($pools, $cache, $database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { - $database->setTenant($project->getSequence()); + $database->setTenant($project->getInternalId()); return $database; } @@ -182,7 +182,7 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) { // set tenant if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') { - $database->setTenant($project->getSequence()); + $database->setTenant($project->getInternalId()); } return $database; diff --git a/app/config/console.php b/app/config/console.php index 1de3a99370..e37c9b7836 100644 --- a/app/config/console.php +++ b/app/config/console.php @@ -11,7 +11,7 @@ use Utopia\System\System; $console = [ '$id' => ID::custom('console'), - '$sequence' => ID::custom('console'), + '$internalId' => ID::custom('console'), 'name' => 'Appwrite', '$collection' => ID::custom('projects'), 'description' => 'Appwrite core engine', diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 0c53423325..ac01476314 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -190,7 +190,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res [ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'provider' => Auth::getSessionProviderByTokenType($verifiedToken->getAttribute('type')), 'secret' => Auth::hash($sessionSecret), // One way hash encryption to protect DB leak 'userAgent' => $request->getUserAgent('UNKNOWN'), @@ -387,7 +387,7 @@ App::post('/v1/account') 'search' => implode(' ', [$userId, $email, $name]), 'accessedAt' => DateTime::now(), ]); - $user->removeAttribute('$sequence'); + $user->removeAttribute('$internalId'); $user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); try { $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ @@ -397,7 +397,7 @@ App::post('/v1/account') Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'providerType' => MESSAGE_TYPE_EMAIL, 'identifier' => $email, ]))); @@ -907,7 +907,7 @@ App::post('/v1/account/sessions/email') [ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'provider' => Auth::SESSION_PROVIDER_EMAIL, 'providerUid' => $email, 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak @@ -1056,7 +1056,7 @@ App::post('/v1/account/sessions/anonymous') 'search' => $userId, 'accessedAt' => DateTime::now(), ]); - $user->removeAttribute('$sequence'); + $user->removeAttribute('$internalId'); Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); // Create session token @@ -1069,7 +1069,7 @@ App::post('/v1/account/sessions/anonymous') [ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'provider' => Auth::SESSION_PROVIDER_ANONYMOUS, 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'userAgent' => $request->getUserAgent('UNKNOWN'), @@ -1440,7 +1440,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), - Query::notEqual('userInternalId', $user->getSequence()), + Query::notEqual('userInternalId', $user->getInternalId()), ]); if (!$identityWithMatchingEmail->isEmpty()) { $failureRedirect(Exception::USER_ALREADY_EXISTS); @@ -1554,7 +1554,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'search' => implode(' ', [$userId, $email, $name]), 'accessedAt' => DateTime::now(), ]); - $user->removeAttribute('$sequence'); + $user->removeAttribute('$internalId'); $userDoc = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); $dbForProject->createDocument('targets', new Document([ '$permissions' => [ @@ -1563,7 +1563,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') Permission::delete(Role::user($user->getId())), ], 'userId' => $userDoc->getId(), - 'userInternalId' => $userDoc->getSequence(), + 'userInternalId' => $userDoc->getInternalId(), 'providerType' => MESSAGE_TYPE_EMAIL, 'identifier' => $email, ])); @@ -1582,7 +1582,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') } $identity = $dbForProject->findOne('identities', [ - Query::equal('userInternalId', [$user->getSequence()]), + Query::equal('userInternalId', [$user->getInternalId()]), Query::equal('provider', [$provider]), Query::equal('providerUid', [$oauth2ID]), ]); @@ -1592,7 +1592,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $identitiesWithMatchingEmail = $dbForProject->find('identities', [ Query::equal('providerEmail', [$email]), - Query::notEqual('userInternalId', $user->getSequence()), + Query::notEqual('userInternalId', $user->getInternalId()), ]); if (!empty($identitiesWithMatchingEmail)) { $failureRedirect(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */ @@ -1605,7 +1605,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') Permission::update(Role::user($userId)), Permission::delete(Role::user($userId)), ], - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'userId' => $userId, 'provider' => $provider, 'providerUid' => $oauth2ID, @@ -1648,7 +1648,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $token = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'type' => Auth::TOKEN_TYPE_OAUTH2, 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'expire' => $expire, @@ -1683,7 +1683,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $session = new Document(array_merge([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'provider' => $provider, 'providerUid' => $oauth2ID, 'providerAccessToken' => $accessToken, @@ -1736,7 +1736,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $target ->setAttribute('sessionId', $session->getId()) - ->setAttribute('sessionInternalId', $session->getSequence()); + ->setAttribute('sessionInternalId', $session->getInternalId()); $dbForProject->updateDocument('targets', $target->getId(), $target); } @@ -1931,7 +1931,7 @@ App::post('/v1/account/tokens/magic-url') 'accessedAt' => DateTime::now(), ]); - $user->removeAttribute('$sequence'); + $user->removeAttribute('$internalId'); Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); } @@ -1941,7 +1941,7 @@ App::post('/v1/account/tokens/magic-url') $token = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'type' => Auth::TOKEN_TYPE_MAGIC_URL, 'secret' => Auth::hash($tokenSecret), // One way hash encryption to protect DB leak 'expire' => $expire, @@ -2168,7 +2168,7 @@ App::post('/v1/account/tokens/email') 'accessedAt' => DateTime::now(), ]); - $user->removeAttribute('$sequence'); + $user->removeAttribute('$internalId'); Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); } @@ -2178,7 +2178,7 @@ App::post('/v1/account/tokens/email') $token = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'type' => Auth::TOKEN_TYPE_EMAIL, 'secret' => Auth::hash($tokenSecret), // One way hash encryption to protect DB leak 'expire' => $expire, @@ -2460,7 +2460,7 @@ App::post('/v1/account/tokens/phone') 'accessedAt' => DateTime::now(), ]); - $user->removeAttribute('$sequence'); + $user->removeAttribute('$internalId'); Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); try { $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ @@ -2470,7 +2470,7 @@ App::post('/v1/account/tokens/phone') Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'providerType' => MESSAGE_TYPE_SMS, 'identifier' => $phone, ]))); @@ -2501,7 +2501,7 @@ App::post('/v1/account/tokens/phone') $token = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'type' => Auth::TOKEN_TYPE_PHONE, 'secret' => Auth::hash($secret), 'expire' => $expire, @@ -2703,7 +2703,7 @@ App::get('/v1/account/logs') $audit = new EventAudit($dbForProject); - $logs = $audit->getLogsByUser($user->getSequence(), $queries); + $logs = $audit->getLogsByUser($user->getInternalId(), $queries); $output = []; @@ -2732,7 +2732,7 @@ App::get('/v1/account/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByUser($user->getSequence(), $queries), + 'total' => $audit->countLogsByUser($user->getInternalId(), $queries), 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -2900,7 +2900,7 @@ App::patch('/v1/account/email') // Makes sure this email is not already used in another identity $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), - Query::notEqual('userInternalId', $user->getSequence()), + Query::notEqual('userInternalId', $user->getInternalId()), ]); if (!$identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */ @@ -3183,7 +3183,7 @@ App::post('/v1/account/recovery') $recovery = new Document([ '$id' => ID::unique(), 'userId' => $profile->getId(), - 'userInternalId' => $profile->getSequence(), + 'userInternalId' => $profile->getInternalId(), 'type' => Auth::TOKEN_TYPE_RECOVERY, 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'expire' => $expire, @@ -3438,7 +3438,7 @@ App::post('/v1/account/verification') $verification = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'type' => Auth::TOKEN_TYPE_VERIFICATION, 'secret' => Auth::hash($verificationSecret), // One way hash encryption to protect DB leak 'expire' => $expire, @@ -3685,7 +3685,7 @@ App::post('/v1/account/verification/phone') $verification = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'type' => Auth::TOKEN_TYPE_PHONE, 'secret' => Auth::hash($secret), 'expire' => $expire, @@ -3979,7 +3979,7 @@ App::post('/v1/account/mfa/authenticators/:type') $authenticator = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'type' => Type::TOTP, 'verified' => false, 'data' => [ @@ -4292,7 +4292,7 @@ App::post('/v1/account/mfa/challenge') $code = Auth::codeGenerator(); $challenge = new Document([ 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'type' => $factor, 'token' => Auth::tokenGenerator(), 'code' => $code, @@ -4621,12 +4621,12 @@ App::post('/v1/account/targets/push') Permission::delete(Role::user($user->getId())), ], 'providerId' => !empty($providerId) ? $providerId : null, - 'providerInternalId' => !empty($providerId) ? $provider->getSequence() : null, + 'providerInternalId' => !empty($providerId) ? $provider->getInternalId() : null, 'providerType' => MESSAGE_TYPE_PUSH, 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'sessionId' => $session->getId(), - 'sessionInternalId' => $session->getSequence(), + 'sessionInternalId' => $session->getInternalId(), 'identifier' => $identifier, 'name' => "{$device['deviceBrand']} {$device['deviceModel']}" ])); @@ -4745,7 +4745,7 @@ App::delete('/v1/account/targets/:targetId/push') throw new Exception(Exception::USER_TARGET_NOT_FOUND); } - if ($user->getSequence() !== $target->getAttribute('userInternalId')) { + if ($user->getInternalId() !== $target->getAttribute('userInternalId')) { throw new Exception(Exception::USER_TARGET_NOT_FOUND); } @@ -4794,7 +4794,7 @@ App::get('/v1/account/identities') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $queries[] = Query::equal('userInternalId', [$user->getSequence()]); + $queries[] = Query::equal('userInternalId', [$user->getInternalId()]); /** * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index 3a7b4aa582..779a188089 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -669,7 +669,7 @@ App::get('/v1/cards/cloud') } } - $isPlatinum = $user->getSequence() % 100 === 0; + $isPlatinum = $user->getInternalId() % 100 === 0; } else { $name = $mock === 'normal-long' ? 'Sir First Walter O\'Brian Junior' : 'Walter O\'Brian'; $createdAt = new \DateTime('now'); @@ -859,7 +859,7 @@ App::get('/v1/cards/cloud-back') $isEmployee = \array_key_exists($email, $employees); $isGolden = $isEmployee || $isHero || $isContributor; - $isPlatinum = $user->getSequence() % 100 === 0; + $isPlatinum = $user->getInternalId() % 100 === 0; } else { $userId = '63e0bcf3c3eb803ba530'; @@ -926,9 +926,9 @@ App::get('/v1/cards/cloud-og') } if (!$mock) { - $sequence = $user->getSequence(); - $bgVariation = $sequence % 3 === 0 ? '1' : ($sequence % 3 === 1 ? '2' : '3'); - $cardVariation = $sequence % 3 === 0 ? '1' : ($sequence % 3 === 1 ? '2' : '3'); + $internalId = $user->getInternalId(); + $bgVariation = $internalId % 3 === 0 ? '1' : ($internalId % 3 === 1 ? '2' : '3'); + $cardVariation = $internalId % 3 === 0 ? '1' : ($internalId % 3 === 1 ? '2' : '3'); $name = $user->getAttribute('name', 'Anonymous'); $email = $user->getAttribute('email', ''); @@ -958,7 +958,7 @@ App::get('/v1/cards/cloud-og') } } - $isPlatinum = $user->getSequence() % 100 === 0; + $isPlatinum = $user->getInternalId() % 100 === 0; } else { $bgVariation = \str_ends_with($mock, '-bg2') ? '2' : (\str_ends_with($mock, '-bg3') ? '3' : '1'); $cardVariation = \str_ends_with($mock, '-right') ? '2' : (\str_ends_with($mock, '-middle') ? '3' : '1'); diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 4ff1c55fb3..4860f7a967 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -107,7 +107,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -130,7 +130,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att if ($type === Database::VAR_RELATIONSHIP) { $options['side'] = Database::RELATION_SIDE_PARENT; - $relatedCollection = $dbForProject->getDocument('database_' . $database->getSequence(), $options['relatedCollection'] ?? ''); + $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection'] ?? ''); if ($relatedCollection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND, 'The related collection was not found.'); } @@ -138,11 +138,11 @@ function createAttribute(string $databaseId, string $collectionId, Document $att try { $attribute = new Document([ - '$id' => ID::custom($database->getSequence() . '_' . $collection->getSequence() . '_' . $key), + '$id' => ID::custom($database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key), 'key' => $key, - 'databaseInternalId' => $database->getSequence(), + 'databaseInternalId' => $database->getInternalId(), 'databaseId' => $database->getId(), - 'collectionInternalId' => $collection->getSequence(), + 'collectionInternalId' => $collection->getInternalId(), 'collectionId' => $collectionId, 'type' => $type, 'status' => 'processing', // processing, available, failed, deleting, stuck @@ -164,13 +164,13 @@ function createAttribute(string $databaseId, string $collectionId, Document $att } catch (LimitException) { throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); } catch (\Throwable $e) { - $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); throw $e; } - $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { $twoWayKey = $options['twoWayKey']; @@ -181,11 +181,11 @@ function createAttribute(string $databaseId, string $collectionId, Document $att try { try { $twoWayAttribute = new Document([ - '$id' => ID::custom($database->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $twoWayKey), + '$id' => ID::custom($database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $twoWayKey), 'key' => $twoWayKey, - 'databaseInternalId' => $database->getSequence(), + 'databaseInternalId' => $database->getInternalId(), 'databaseId' => $database->getId(), - 'collectionInternalId' => $relatedCollection->getSequence(), + 'collectionInternalId' => $relatedCollection->getInternalId(), 'collectionId' => $relatedCollection->getId(), 'type' => $type, 'status' => 'processing', // processing, available, failed, deleting, stuck @@ -213,13 +213,13 @@ function createAttribute(string $databaseId, string $collectionId, Document $att $dbForProject->deleteDocument('attributes', $attribute->getId()); throw $e; } finally { - $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); } // If operation succeeded, purge the cache for the related collection too - $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $relatedCollection->getId()); - $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence()); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); + $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); } $queueForDatabase @@ -262,12 +262,12 @@ function updateAttribute( throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $collection->getSequence() . '_' . $key); + $attribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); if ($attribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); } @@ -292,7 +292,7 @@ function updateAttribute( throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for array attributes'); } - $collectionId = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(); + $collectionId = 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(); $attribute ->setAttribute('default', $default) @@ -378,8 +378,8 @@ function updateAttribute( } if ($primaryDocumentOptions['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $database->getSequence(), $primaryDocumentOptions['relatedCollection']); - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $primaryDocumentOptions['twoWayKey']); + $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $primaryDocumentOptions['relatedCollection']); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey']); if (!empty($newKey) && $newKey !== $key) { $options['twoWayKey'] = $newKey; @@ -389,8 +389,8 @@ function updateAttribute( $relatedAttribute->setAttribute('options', $relatedOptions); - $dbForProject->updateDocument('attributes', $database->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $primaryDocumentOptions['twoWayKey'], $relatedAttribute); - $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $relatedCollection->getId()); + $dbForProject->updateDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey'], $relatedAttribute); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); } } else { try { @@ -418,7 +418,7 @@ function updateAttribute( $originalUid = $attribute->getId(); $attribute - ->setAttribute('$id', ID::custom($database->getSequence() . '_' . $collection->getSequence() . '_' . $newKey)) + ->setAttribute('$id', ID::custom($database->getInternalId() . '_' . $collection->getInternalId() . '_' . $newKey)) ->setAttribute('key', $newKey); try { @@ -444,10 +444,10 @@ function updateAttribute( } } } else { - $attribute = $dbForProject->updateDocument('attributes', $database->getSequence() . '_' . $collection->getSequence() . '_' . $key, $attribute); + $attribute = $dbForProject->updateDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key, $attribute); } - $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collection->getId()); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collection->getId()); $queueForEvents ->setContext('collection', $collection) @@ -536,7 +536,7 @@ App::post('/v1/databases') } try { - $dbForProject->createCollection('database_' . $database->getSequence(), $attributes, $indexes); + $dbForProject->createCollection('database_' . $database->getInternalId(), $attributes, $indexes); } catch (DuplicateException) { throw new Exception(Exception::DATABASE_ALREADY_EXISTS); } catch (IndexException) { @@ -839,7 +839,7 @@ App::delete('/v1/databases/:databaseId') } $dbForProject->purgeCachedDocument('databases', $database->getId()); - $dbForProject->purgeCachedCollection('databases_' . $database->getSequence()); + $dbForProject->purgeCachedCollection('databases_' . $database->getInternalId()); $queueForDatabase ->setType(DATABASE_TYPE_DELETE_DATABASE) @@ -899,9 +899,9 @@ App::post('/v1/databases/:databaseId/collections') $permissions = Permission::aggregate($permissions) ?? []; try { - $collection = $dbForProject->createDocument('database_' . $database->getSequence(), new Document([ + $collection = $dbForProject->createDocument('database_' . $database->getInternalId(), new Document([ '$id' => $collectionId, - 'databaseInternalId' => $database->getSequence(), + 'databaseInternalId' => $database->getInternalId(), 'databaseId' => $databaseId, '$permissions' => $permissions, 'documentSecurity' => $documentSecurity, @@ -919,7 +919,7 @@ App::post('/v1/databases/:databaseId/collections') try { $dbForProject->createCollection( - id: 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + id: 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), permissions: $permissions, documentSecurity: $documentSecurity ); @@ -1000,7 +1000,7 @@ App::get('/v1/databases/:databaseId/collections') $collectionId = $cursor->getValue(); - $cursorDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $cursorDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Collection '{$collectionId}' for the 'cursor' value not found."); @@ -1009,7 +1009,7 @@ App::get('/v1/databases/:databaseId/collections') $cursor->setValue($cursorDocument); } - $collectionId = 'database_' . $database->getSequence(); + $collectionId = 'database_' . $database->getInternalId(); try { $collections = $dbForProject->find($collectionId, $queries); @@ -1057,7 +1057,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -1100,8 +1100,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collectionDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); - $collection = $dbForProject->getCollection('database_' . $database->getSequence() . '_collection_' . $collectionDocument->getSequence()); + $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); if ($collectionDocument->isEmpty() || $collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -1215,7 +1215,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -1236,12 +1236,12 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') ->setAttribute('search', \implode(' ', [$collectionId, $name])); $collection = $dbForProject->updateDocument( - 'database_' . $database->getSequence(), + 'database_' . $database->getInternalId(), $collectionId, $collection ); - $dbForProject->updateCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $permissions, $documentSecurity); + $dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $permissions, $documentSecurity); $queueForEvents ->setContext('database', $database) @@ -1287,17 +1287,17 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - if (!$dbForProject->deleteDocument('database_' . $database->getSequence(), $collectionId)) { + if (!$dbForProject->deleteDocument('database_' . $database->getInternalId(), $collectionId)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB'); } - $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); + $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); $queueForDatabase ->setType(DATABASE_TYPE_DELETE_COLLECTION) @@ -1888,15 +1888,15 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); - $collection = $dbForProject->getCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $relatedCollectionDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId); - $relatedCollection = $dbForProject->getCollection('database_' . $database->getSequence() . '_collection_' . $relatedCollectionDocument->getSequence()); + $relatedCollectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); + $relatedCollection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollectionDocument->getInternalId()); if ($relatedCollection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -1997,7 +1997,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -2010,8 +2010,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') \array_push( $queries, - Query::equal('databaseInternalId', [$database->getSequence()]), - Query::equal('collectionInternalId', [$collection->getSequence()]), + Query::equal('databaseInternalId', [$database->getInternalId()]), + Query::equal('collectionInternalId', [$collection->getInternalId()]), ); /** @@ -2033,8 +2033,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') try { $cursorDocument = $dbForProject->findOne('attributes', [ - Query::equal('databaseInternalId', [$database->getSequence()]), - Query::equal('collectionInternalId', [$collection->getSequence()]), + Query::equal('databaseInternalId', [$database->getInternalId()]), + Query::equal('collectionInternalId', [$collection->getInternalId()]), Query::equal('key', [$attributeId]), ]); } catch (QueryException $e) { @@ -2112,13 +2112,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $collection->getSequence() . '_' . $key); + $attribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); if ($attribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); @@ -2725,13 +2725,13 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $collection->getSequence() . '_' . $key); + $attribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); if ($attribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); @@ -2754,19 +2754,19 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key $attribute = $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'deleting')); } - $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { $options = $attribute->getAttribute('options'); if ($options['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $database->getSequence(), $options['relatedCollection']); + $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); if ($relatedCollection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $options['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); if ($relatedAttribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); @@ -2776,8 +2776,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'deleting')); } - $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $options['relatedCollection']); - $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence()); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $options['relatedCollection']); + $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); } } @@ -2859,7 +2859,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -2868,8 +2868,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') $limit = $dbForProject->getLimitForIndexes(); $count = $dbForProject->count('indexes', [ - Query::equal('collectionInternalId', [$collection->getSequence()]), - Query::equal('databaseInternalId', [$database->getSequence()]) + Query::equal('collectionInternalId', [$collection->getInternalId()]), + Query::equal('databaseInternalId', [$database->getInternalId()]) ], max: $limit); @@ -2939,12 +2939,12 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') } $index = new Document([ - '$id' => ID::custom($database->getSequence() . '_' . $collection->getSequence() . '_' . $key), + '$id' => ID::custom($database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key), 'key' => $key, 'status' => 'processing', // processing, available, failed, deleting, stuck - 'databaseInternalId' => $database->getSequence(), + 'databaseInternalId' => $database->getInternalId(), 'databaseId' => $databaseId, - 'collectionInternalId' => $collection->getSequence(), + 'collectionInternalId' => $collection->getInternalId(), 'collectionId' => $collectionId, 'type' => $type, 'attributes' => $attributes, @@ -2968,7 +2968,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') throw new Exception(Exception::INDEX_ALREADY_EXISTS); } - $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); $queueForDatabase ->setType(DATABASE_TYPE_CREATE_INDEX) @@ -3020,7 +3020,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -3051,8 +3051,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') $indexId = $cursor->getValue(); $cursorDocument = Authorization::skip(fn () => $dbForProject->find('indexes', [ - Query::equal('collectionInternalId', [$collection->getSequence()]), - Query::equal('databaseInternalId', [$database->getSequence()]), + Query::equal('collectionInternalId', [$collection->getInternalId()]), + Query::equal('databaseInternalId', [$database->getInternalId()]), Query::equal('key', [$indexId]), Query::limit(1) ])); @@ -3111,7 +3111,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -3164,13 +3164,13 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $index = $dbForProject->getDocument('indexes', $database->getSequence() . '_' . $collection->getSequence() . '_' . $key); + $index = $dbForProject->getDocument('indexes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); if ($index->isEmpty()) { throw new Exception(Exception::INDEX_NOT_FOUND); @@ -3181,7 +3181,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') $index = $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'deleting')); } - $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); $queueForDatabase ->setType(DATABASE_TYPE_DELETE_INDEX) @@ -3317,7 +3317,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -3426,7 +3426,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) ); foreach ($relations as &$relation) { @@ -3440,7 +3440,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') } if ($relation instanceof Document) { $current = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId()) + fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId()) ); if ($current->isEmpty()) { @@ -3495,7 +3495,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') try { $dbForProject->createDocuments( - 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documents ); } catch (DuplicateException) { @@ -3537,7 +3537,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -3554,7 +3554,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations)) - ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); // per collection + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); // per collection $response->setStatusCode(Response::STATUS_CODE_CREATED); @@ -3612,7 +3612,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -3640,7 +3640,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $documentId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Document '{$documentId}' for the 'cursor' value not found."); @@ -3649,8 +3649,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $cursor->setValue($cursorDocument); } try { - $documents = $dbForProject->find('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $queries); - $total = $dbForProject->count('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $queries, APP_LIMIT_COUNT); + $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries); + $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT); } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } catch (QueryException $e) { @@ -3694,7 +3694,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $relatedCollectionId = $relationship->getAttribute('relatedCollection'); // todo: Use local cache for this getDocument - $relatedCollection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId)); + $relatedCollection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId)); foreach ($relations as $index => $doc) { if ($doc instanceof Document) { @@ -3720,7 +3720,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_READS, \max(1, $operations)) - ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_READS), \max(1, $operations)); + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), \max(1, $operations)); $select = \array_reduce($queries, function ($result, $query) { return $result || ($query->getMethod() === Query::TYPE_SELECT); @@ -3791,7 +3791,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -3803,7 +3803,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen } try { - $document = $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId, $queries); + $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId, $queries); } catch (QueryException $e) { throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } @@ -3847,7 +3847,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -3862,7 +3862,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_READS, \max(1, $operations)) - ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_READS), \max(1, $operations)); + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), \max(1, $operations)); $response->dynamic($document, Response::MODEL_DOCUMENT); }); @@ -3901,12 +3901,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $document = $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId); + $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); @@ -4030,13 +4030,13 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } // Read permission should not be required for update - $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); + $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); } @@ -4105,7 +4105,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) ); foreach ($relations as &$relation) { @@ -4120,7 +4120,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum } if ($relation instanceof Document) { $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( - 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), + 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId() )); $relation->removeAttribute('$collectionId'); @@ -4128,7 +4128,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum // Attribute $collection is required for Utopia. $relation->setAttribute( '$collection', - 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence() + 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId() ); if ($oldDocument->isEmpty()) { @@ -4152,11 +4152,11 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations)) - ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); try { $document = $dbForProject->updateDocument( - 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $document->getId(), $newDocument ); @@ -4192,7 +4192,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -4274,7 +4274,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -4339,7 +4339,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) ); foreach ($relations as &$relation) { @@ -4354,7 +4354,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen } if ($relation instanceof Document) { $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( - 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), + 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId() )); $relation->removeAttribute('$collectionId'); @@ -4362,7 +4362,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen // Attribute $collection is required for Utopia. $relation->setAttribute( '$collection', - 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence() + 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId() ); if ($oldDocument->isEmpty()) { @@ -4386,12 +4386,12 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations)) - ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); $upserted = []; try { $modified = $dbForProject->createOrUpdateDocuments( - 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), [$newDocument], onNext: function (Document $document) use (&$upserted) { $upserted[] = $document; @@ -4430,7 +4430,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -4509,7 +4509,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -4540,7 +4540,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents') try { $modified = $dbForProject->updateDocuments( - 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), new Document($data), $queries, onNext: function (Document $document) use ($plan, &$documents) { @@ -4564,7 +4564,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $modified)) - ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); $response->dynamic(new Document([ 'total' => $modified, @@ -4609,7 +4609,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -4631,7 +4631,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents') try { $modified = $dbForProject->createOrUpdateDocuments( - 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documents, onNext: function (Document $document) use ($plan, &$upserted) { if (\count($upserted) < ($plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH)) { @@ -4656,7 +4656,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $modified)) - ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); $response->dynamic(new Document([ 'total' => $modified, @@ -4707,20 +4707,20 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } // Read permission should not be required for delete - $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); + $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); } try { $dbForProject->deleteDocument( - 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId ); } catch (ConflictException) { @@ -4755,7 +4755,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -4770,7 +4770,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations)) - ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); $relationships = \array_map( fn ($document) => $document->getAttribute('key'), @@ -4829,7 +4829,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -4853,7 +4853,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents') try { $modified = $dbForProject->deleteDocuments( - 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, onNext: function (Document $document) use ($plan, &$documents) { if (\count($documents) < ($plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH)) { @@ -4874,7 +4874,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $modified)) - ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); + ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); $response->dynamic(new Document([ 'total' => $modified, @@ -5010,11 +5010,11 @@ App::get('/v1/databases/:databaseId/usage') $stats = $usage = []; $days = $periods[$range]; $metrics = [ - str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_COLLECTIONS), - str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_DOCUMENTS), - str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_STORAGE), - str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_READS), - str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES) + str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS), + str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS), + str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_STORAGE), + str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), + str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES) ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { @@ -5103,8 +5103,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') ->inject('dbForProject') ->action(function (string $databaseId, string $range, string $collectionId, Response $response, Database $dbForProject) { $database = $dbForProject->getDocument('databases', $databaseId); - $collectionDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); - $collection = $dbForProject->getCollection('database_' . $database->getSequence() . '_collection_' . $collectionDocument->getSequence()); + $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -5114,7 +5114,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') $stats = $usage = []; $days = $periods[$range]; $metrics = [ - str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getSequence(), $collectionDocument->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), + str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collectionDocument->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index 2bdaea3c2c..b95eb432a1 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -845,18 +845,15 @@ App::get('/v1/health/storage') $checkStart = \microtime(true); foreach ($devices as $device) { - $uniqueFileName = \uniqid('health', true); - $filePath = $device->getPath($uniqueFileName); - - if (!$device->write($filePath, 'test', 'text/plain')) { + if (!$device->write($device->getPath('health.txt'), 'test', 'text/plain')) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed writing test file to ' . $device->getRoot()); } - if ($device->read($filePath) !== 'test') { + if ($device->read($device->getPath('health.txt')) !== 'test') { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed reading test file from ' . $device->getRoot()); } - if (!$device->delete($filePath)) { + if (!$device->delete($device->getPath('health.txt'))) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed deleting test file from ' . $device->getRoot()); } } diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 0bc6f93787..1d11e6c392 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -2511,11 +2511,11 @@ App::post('/v1/messaging/topics/:topicId/subscribers') Permission::delete(Role::user($user->getId())), ], 'topicId' => $topicId, - 'topicInternalId' => $topic->getSequence(), + 'topicInternalId' => $topic->getInternalId(), 'targetId' => $targetId, - 'targetInternalId' => $target->getSequence(), + 'targetInternalId' => $target->getInternalId(), 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'providerType' => $target->getAttribute('providerType'), 'search' => implode(' ', [ $subscriberId, @@ -2597,7 +2597,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') throw new Exception(Exception::TOPIC_NOT_FOUND); } - $queries[] = Query::equal('topicInternalId', [$topic->getSequence()]); + $queries[] = Query::equal('topicInternalId', [$topic->getInternalId()]); /** * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries @@ -2947,7 +2947,7 @@ App::post('/v1/messaging/messages/email') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -2989,7 +2989,7 @@ App::post('/v1/messaging/messages/email') 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), - 'resourceInternalId' => $message->getSequence(), + 'resourceInternalId' => $message->getInternalId(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -3112,7 +3112,7 @@ App::post('/v1/messaging/messages/sms') 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), - 'resourceInternalId' => $message->getSequence(), + 'resourceInternalId' => $message->getInternalId(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -3232,7 +3232,7 @@ App::post('/v1/messaging/messages/push') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -3330,7 +3330,7 @@ App::post('/v1/messaging/messages/push') 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), - 'resourceInternalId' => $message->getSequence(), + 'resourceInternalId' => $message->getInternalId(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -3731,7 +3731,7 @@ App::patch('/v1/messaging/messages/email/:messageId') 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), - 'resourceInternalId' => $message->getSequence(), + 'resourceInternalId' => $message->getInternalId(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -3796,7 +3796,7 @@ App::patch('/v1/messaging/messages/email/:messageId') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -3933,7 +3933,7 @@ App::patch('/v1/messaging/messages/sms/:messageId') 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), - 'resourceInternalId' => $message->getSequence(), + 'resourceInternalId' => $message->getInternalId(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -4107,7 +4107,7 @@ App::patch('/v1/messaging/messages/push/:messageId') 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), - 'resourceInternalId' => $message->getSequence(), + 'resourceInternalId' => $message->getInternalId(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -4210,7 +4210,7 @@ App::patch('/v1/messaging/messages/push/:messageId') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } diff --git a/app/controllers/api/migrations.php b/app/controllers/api/migrations.php index 92fca88744..494ccfcaac 100644 --- a/app/controllers/api/migrations.php +++ b/app/controllers/api/migrations.php @@ -345,7 +345,7 @@ App::post('/v1/migrations/csv') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); } diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index d09470ff39..047179b888 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -150,7 +150,7 @@ App::get('/v1/project/usage') $executionsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS); + $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -166,7 +166,7 @@ App::get('/v1/project/usage') $executionsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS); + $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -182,7 +182,7 @@ App::get('/v1/project/usage') $buildsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS); + $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -198,7 +198,7 @@ App::get('/v1/project/usage') $bucketsBreakdown = array_map(function ($bucket) use ($dbForProject) { $id = $bucket->getId(); $name = $bucket->getAttribute('name'); - $metric = str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_STORAGE); + $metric = str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -214,7 +214,7 @@ App::get('/v1/project/usage') $databasesStorageBreakdown = array_map(function ($database) use ($dbForProject) { $id = $database->getId(); $name = $database->getAttribute('name'); - $metric = str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_STORAGE); + $metric = str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_STORAGE); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), @@ -231,13 +231,13 @@ App::get('/v1/project/usage') $functionsStorageBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $deploymentMetric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE); + $deploymentMetric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE); $deploymentValue = $dbForProject->findOne('stats', [ Query::equal('metric', [$deploymentMetric]), Query::equal('period', ['inf']) ]); - $buildMetric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE); + $buildMetric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE); $buildValue = $dbForProject->findOne('stats', [ Query::equal('metric', [$buildMetric]), Query::equal('period', ['inf']) @@ -255,7 +255,7 @@ App::get('/v1/project/usage') $executionsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS); + $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -271,7 +271,7 @@ App::get('/v1/project/usage') $buildsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS); + $metric = str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index 51cbc097f5..5eda8e9a0e 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -182,7 +182,7 @@ App::post('/v1/projects') Permission::delete(Role::team(ID::custom($teamId), 'developer')), ], 'name' => $name, - 'teamInternalId' => $team->getSequence(), + 'teamInternalId' => $team->getInternalId(), 'teamId' => $team->getId(), 'region' => $region, 'description' => $description, @@ -230,13 +230,13 @@ App::post('/v1/projects') if ($sharedTables) { $dbForProject ->setSharedTables(true) - ->setTenant($sharedTablesV1 ? $project->getSequence() : null) + ->setTenant($sharedTablesV1 ? $project->getInternalId() : null) ->setNamespace($dsn->getParam('namespace')); } else { $dbForProject ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getSequence()); + ->setNamespace('_' . $project->getInternalId()); } $create = true; @@ -504,12 +504,12 @@ App::patch('/v1/projects/:projectId/team') $project ->setAttribute('teamId', $teamId) - ->setAttribute('teamInternalId', $team->getSequence()) + ->setAttribute('teamInternalId', $team->getInternalId()) ->setAttribute('$permissions', $permissions); $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project); $installations = $dbForPlatform->find('installations', [ - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), ]); foreach ($installations as $installation) { $installation->getAttribute('$permissions', $permissions); @@ -517,7 +517,7 @@ App::patch('/v1/projects/:projectId/team') } $repositories = $dbForPlatform->find('repositories', [ - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), ]); foreach ($repositories as $repository) { $repository->getAttribute('$permissions', $permissions); @@ -525,7 +525,7 @@ App::patch('/v1/projects/:projectId/team') } $vcsComments = $dbForPlatform->find('vcsComments', [ - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), ]); foreach ($vcsComments as $vcsComment) { $vcsComment->getAttribute('$permissions', $permissions); @@ -1229,7 +1229,7 @@ App::post('/v1/projects/:projectId/webhooks') Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'projectId' => $project->getId(), 'name' => $name, 'events' => $events, @@ -1279,7 +1279,7 @@ App::get('/v1/projects/:projectId/webhooks') } $webhooks = $dbForPlatform->find('webhooks', [ - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), Query::limit(5000), ]); @@ -1320,7 +1320,7 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId') $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), ]); if ($webhook->isEmpty()) { @@ -1370,7 +1370,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), ]); if ($webhook->isEmpty()) { @@ -1427,7 +1427,7 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature') $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), ]); if ($webhook->isEmpty()) { @@ -1474,7 +1474,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), ]); if ($webhook->isEmpty()) { @@ -1528,7 +1528,7 @@ App::post('/v1/projects/:projectId/keys') Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'projectId' => $project->getId(), 'name' => $name, 'scopes' => $scopes, @@ -1576,7 +1576,7 @@ App::get('/v1/projects/:projectId/keys') } $keys = $dbForPlatform->find('keys', [ - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), Query::limit(5000), ]); @@ -1617,7 +1617,7 @@ App::get('/v1/projects/:projectId/keys/:keyId') $key = $dbForPlatform->findOne('keys', [ Query::equal('$id', [$keyId]), - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), ]); if ($key->isEmpty()) { @@ -1661,7 +1661,7 @@ App::put('/v1/projects/:projectId/keys/:keyId') $key = $dbForPlatform->findOne('keys', [ Query::equal('$id', [$keyId]), - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), ]); if ($key->isEmpty()) { @@ -1712,7 +1712,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId') $key = $dbForPlatform->findOne('keys', [ Query::equal('$id', [$keyId]), - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), ]); if ($key->isEmpty()) { @@ -1811,7 +1811,7 @@ App::post('/v1/projects/:projectId/platforms') Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'projectId' => $project->getId(), 'type' => $type, 'name' => $name, @@ -1858,7 +1858,7 @@ App::get('/v1/projects/:projectId/platforms') } $platforms = $dbForPlatform->find('platforms', [ - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), Query::limit(5000), ]); @@ -1899,7 +1899,7 @@ App::get('/v1/projects/:projectId/platforms/:platformId') $platform = $dbForPlatform->findOne('platforms', [ Query::equal('$id', [$platformId]), - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), ]); if ($platform->isEmpty()) { @@ -1943,7 +1943,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId') $platform = $dbForPlatform->findOne('platforms', [ Query::equal('$id', [$platformId]), - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), ]); if ($platform->isEmpty()) { @@ -1997,7 +1997,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') $platform = $dbForPlatform->findOne('platforms', [ Query::equal('$id', [$platformId]), - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), ]); if ($platform->isEmpty()) { diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index 417ea602ba..c1c8d8e4a0 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -58,7 +58,7 @@ App::get('/v1/proxy/rules') $queries[] = Query::search('search', $search); } - $queries[] = Query::equal('projectInternalId', [$project->getSequence()]); + $queries[] = Query::equal('projectInternalId', [$project->getInternalId()]); /** * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries @@ -124,7 +124,7 @@ App::get('/v1/proxy/rules/:ruleId') ->action(function (string $ruleId, Response $response, Document $project, Database $dbForPlatform) { $rule = $dbForPlatform->getDocument('rules', $ruleId); - if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getSequence()) { + if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getInternalId()) { throw new Exception(Exception::RULE_NOT_FOUND); } @@ -165,7 +165,7 @@ App::delete('/v1/proxy/rules/:ruleId') ->action(function (string $ruleId, Response $response, Document $project, Database $dbForPlatform, Delete $queueForDeletes, Event $queueForEvents) { $rule = $dbForPlatform->getDocument('rules', $ruleId); - if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getSequence()) { + if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getInternalId()) { throw new Exception(Exception::RULE_NOT_FOUND); } @@ -210,7 +210,7 @@ App::patch('/v1/proxy/rules/:ruleId/verification') ->action(function (string $ruleId, Response $response, Certificate $queueForCertificates, Event $queueForEvents, Document $project, Database $dbForPlatform, Log $log) { $rule = $dbForPlatform->getDocument('rules', $ruleId); - if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getSequence()) { + if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getInternalId()) { throw new Exception(Exception::RULE_NOT_FOUND); } diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index a25241ec4b..b3b8fb906a 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -145,7 +145,7 @@ App::post('/v1/storage/buckets') $bucket = $dbForProject->getDocument('buckets', $bucketId); - $dbForProject->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes, permissions: $permissions ?? [], documentSecurity: $fileSecurity); + $dbForProject->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes, permissions: $permissions ?? [], documentSecurity: $fileSecurity); } catch (DuplicateException) { throw new Exception(Exception::STORAGE_BUCKET_ALREADY_EXISTS); } @@ -326,7 +326,7 @@ App::put('/v1/storage/buckets/:bucketId') ->setAttribute('compression', $compression) ->setAttribute('antivirus', $antivirus)); - $dbForProject->updateCollection('bucket_' . $bucket->getSequence(), $permissions, $fileSecurity); + $dbForProject->updateCollection('bucket_' . $bucket->getInternalId(), $permissions, $fileSecurity); $queueForEvents ->setParam('bucketId', $bucket->getId()); @@ -558,7 +558,7 @@ App::post('/v1/storage/buckets/:bucketId/files') $path = $deviceForFiles->getPath($fileId . '.' . \pathinfo($fileName, PATHINFO_EXTENSION)); $path = str_ireplace($deviceForFiles->getRoot(), $deviceForFiles->getRoot() . DIRECTORY_SEPARATOR . $bucket->getId(), $path); // Add bucket id to path after root - $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); $metadata = ['content_type' => $deviceForLocal->getFileMimeType($fileTmpName)]; if (!$file->isEmpty()) { @@ -652,7 +652,7 @@ App::post('/v1/storage/buckets/:bucketId/files') '$id' => $fileId, '$permissions' => $permissions, 'bucketId' => $bucket->getId(), - 'bucketInternalId' => $bucket->getSequence(), + 'bucketInternalId' => $bucket->getInternalId(), 'name' => $fileName, 'path' => $path, 'signature' => $fileHash, @@ -671,7 +671,7 @@ App::post('/v1/storage/buckets/:bucketId/files') 'metadata' => $metadata, ]); - $file = $dbForProject->createDocument('bucket_' . $bucket->getSequence(), $doc); + $file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc); } else { $file = $file ->setAttribute('$permissions', $permissions) @@ -696,7 +696,7 @@ App::post('/v1/storage/buckets/:bucketId/files') if (!$validator->isValid($bucket->getCreate())) { throw new Exception(Exception::USER_UNAUTHORIZED); } - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file)); } } else { if ($file->isEmpty()) { @@ -704,7 +704,7 @@ App::post('/v1/storage/buckets/:bucketId/files') '$id' => ID::custom($fileId), '$permissions' => $permissions, 'bucketId' => $bucket->getId(), - 'bucketInternalId' => $bucket->getSequence(), + 'bucketInternalId' => $bucket->getInternalId(), 'name' => $fileName, 'path' => $path, 'signature' => '', @@ -720,7 +720,7 @@ App::post('/v1/storage/buckets/:bucketId/files') ]); try { - $file = $dbForProject->createDocument('bucket_' . $bucket->getSequence(), $doc); + $file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc); } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -741,7 +741,7 @@ App::post('/v1/storage/buckets/:bucketId/files') } try { - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file)); } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -826,9 +826,9 @@ App::get('/v1/storage/buckets/:bucketId/files') $fileId = $cursor->getValue(); if ($fileSecurity && !$valid) { - $cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); + $cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } if ($cursorDocument->isEmpty()) { @@ -842,11 +842,11 @@ App::get('/v1/storage/buckets/:bucketId/files') try { if ($fileSecurity && !$valid) { - $files = $dbForProject->find('bucket_' . $bucket->getSequence(), $queries); - $total = $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT); + $files = $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries); + $total = $dbForProject->count('bucket_' . $bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT); } else { - $files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries)); - $total = Authorization::skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)); + $files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries)); + $total = Authorization::skip(fn () => $dbForProject->count('bucket_' . $bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -902,9 +902,9 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId') } if ($fileSecurity && !$valid) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } if ($file->isEmpty()) { @@ -973,7 +973,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); + $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getInternalId(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); @@ -982,12 +982,12 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') } if ($fileSecurity && !$valid && !$isToken) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } - if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { + if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getInternalId()) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -1150,7 +1150,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); + $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getInternalId(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); @@ -1159,12 +1159,12 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') } if ($fileSecurity && !$valid) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } - if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { + if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getInternalId()) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -1309,7 +1309,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); + $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getInternalId(); $fileSecurity = $bucket->getAttribute('fileSecurity', false); $validator = new Authorization(Database::PERMISSION_READ); $valid = $validator->isValid($bucket->getRead()); @@ -1318,12 +1318,12 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') } if ($fileSecurity && !$valid) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } - if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { + if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getInternalId()) { throw new Exception(Exception::USER_UNAUTHORIZED); } @@ -1478,7 +1478,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -1643,7 +1643,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') } // Read permission should not be required for update - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -1689,9 +1689,9 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') try { if ($fileSecurity && !$valid) { - $file = $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file); + $file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file); } else { - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); + $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -1757,7 +1757,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') } // Read permission should not be required for delete - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -1787,9 +1787,9 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') try { if ($fileSecurity && !$valid) { - $deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId); + $deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { - $deleted = Authorization::skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId)); + $deleted = Authorization::skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -1937,14 +1937,14 @@ App::get('/v1/storage/:bucketId/usage') $stats = $usage = []; $days = $periods[$range]; $metrics = [ - str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES), - str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_STORAGE), - str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED), + str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES), + str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE), + str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED), ]; Authorization::skip(function () use ($dbForProject, $dbForLogs, $bucket, $days, $metrics, &$stats) { foreach ($metrics as $metric) { - $db = ($metric === str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED)) + $db = ($metric === str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED)) ? $dbForLogs : $dbForProject; diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index c83cad7eb1..49d9005c54 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -123,9 +123,9 @@ App::post('/v1/teams') Permission::delete(Role::team($team->getId(), 'owner')), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'teamId' => $team->getId(), - 'teamInternalId' => $team->getSequence(), + 'teamInternalId' => $team->getInternalId(), 'roles' => $roles, 'invited' => DateTime::now(), 'joined' => DateTime::now(), @@ -595,8 +595,8 @@ App::post('/v1/teams/:teamId/memberships') } $membership = $dbForProject->findOne('memberships', [ - Query::equal('userInternalId', [$invitee->getSequence()]), - Query::equal('teamInternalId', [$team->getSequence()]), + Query::equal('userInternalId', [$invitee->getInternalId()]), + Query::equal('teamInternalId', [$team->getInternalId()]), ]); $secret = Auth::tokenGenerator(); @@ -612,9 +612,9 @@ App::post('/v1/teams/:teamId/memberships') Permission::delete(Role::team($team->getId(), 'owner')), ], 'userId' => $invitee->getId(), - 'userInternalId' => $invitee->getSequence(), + 'userInternalId' => $invitee->getInternalId(), 'teamId' => $team->getId(), - 'teamInternalId' => $team->getSequence(), + 'teamInternalId' => $team->getInternalId(), 'roles' => $roles, 'invited' => DateTime::now(), 'joined' => ($isPrivilegedUser || $isAppUser) ? DateTime::now() : null, @@ -842,7 +842,7 @@ App::get('/v1/teams/:teamId/memberships') } // Set internal queries - $queries[] = Query::equal('teamInternalId', [$team->getSequence()]); + $queries[] = Query::equal('teamInternalId', [$team->getInternalId()]); /** * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries @@ -1092,7 +1092,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') collection: 'memberships', queries: [ Query::contains('roles', ['owner']), - Query::equal('teamInternalId', [$team->getSequence()]) + Query::equal('teamInternalId', [$team->getInternalId()]) ], max: 2 ); @@ -1180,7 +1180,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') throw new Exception(Exception::TEAM_NOT_FOUND); } - if ($membership->getAttribute('teamInternalId') !== $team->getSequence()) { + if ($membership->getAttribute('teamInternalId') !== $team->getInternalId()) { throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH); } @@ -1197,7 +1197,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $user->setAttributes($dbForProject->getDocument('users', $userId)->getArrayCopy()); // Get user } - if ($membership->getAttribute('userInternalId') !== $user->getSequence()) { + if ($membership->getAttribute('userInternalId') !== $user->getInternalId()) { throw new Exception(Exception::TEAM_INVITE_MISMATCH, 'Invite does not belong to current user (' . $user->getAttribute('email') . ')'); } @@ -1229,7 +1229,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'provider' => Auth::SESSION_PROVIDER_EMAIL, 'providerUid' => $user->getAttribute('email'), 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak @@ -1338,7 +1338,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') throw new Exception(Exception::TEAM_NOT_FOUND); } - if ($membership->getAttribute('teamInternalId') !== $team->getSequence()) { + if ($membership->getAttribute('teamInternalId') !== $team->getInternalId()) { throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH); } diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 4b6e5abe6b..bc9de0fd42 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -140,7 +140,7 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'providerType' => 'email', 'identifier' => $email, ])); @@ -164,7 +164,7 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'providerType' => 'sms', 'identifier' => $phone, ])); @@ -564,10 +564,10 @@ App::post('/v1/users/:userId/targets') Permission::delete(Role::user($user->getId())), ], 'providerId' => empty($provider->getId()) ? null : $provider->getId(), - 'providerInternalId' => $provider->isEmpty() ? null : $provider->getSequence(), + 'providerInternalId' => $provider->isEmpty() ? null : $provider->getInternalId(), 'providerType' => $providerType, 'userId' => $userId, - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'identifier' => $identifier, 'name' => ($name !== '') ? $name : null, ])); @@ -846,7 +846,7 @@ App::get('/v1/users/:userId/memberships') } // Set internal queries - $queries[] = Query::equal('userInternalId', [$user->getSequence()]); + $queries[] = Query::equal('userInternalId', [$user->getInternalId()]); $memberships = array_map(function ($membership) use ($dbForProject, $user) { $team = $dbForProject->getDocument('teams', $membership->getAttribute('teamId')); @@ -910,7 +910,7 @@ App::get('/v1/users/:userId/logs') $audit = new Audit($dbForProject); - $logs = $audit->getLogsByUser($user->getSequence(), $queries); + $logs = $audit->getLogsByUser($user->getInternalId(), $queries); $output = []; @@ -957,7 +957,7 @@ App::get('/v1/users/:userId/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByUser($user->getSequence(), $queries), + 'total' => $audit->countLogsByUser($user->getInternalId(), $queries), 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -1396,7 +1396,7 @@ App::patch('/v1/users/:userId/email') // Makes sure this email is not already used in another identity $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), - Query::notEqual('userInternalId', $user->getSequence()), + Query::notEqual('userInternalId', $user->getInternalId()), ]); if (!$identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); @@ -1440,7 +1440,7 @@ App::patch('/v1/users/:userId/email') Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'providerType' => 'email', 'identifier' => $email, ])); @@ -1529,7 +1529,7 @@ App::patch('/v1/users/:userId/phone') Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'providerType' => 'sms', 'identifier' => $number, ])); @@ -1711,7 +1711,7 @@ App::patch('/v1/users/:userId/targets/:targetId') $target ->setAttribute('providerId', $provider->getId()) - ->setAttribute('providerInternalId', $provider->getSequence()); + ->setAttribute('providerInternalId', $provider->getInternalId()); } if ($name) { @@ -2051,7 +2051,7 @@ App::post('/v1/users/:userId/sessions') [ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'provider' => Auth::SESSION_PROVIDER_SERVER, 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'userAgent' => $request->getUserAgent('UNKNOWN'), @@ -2131,7 +2131,7 @@ App::post('/v1/users/:userId/tokens') $token = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getSequence(), + 'userInternalId' => $user->getInternalId(), 'type' => Auth::TOKEN_TYPE_GENERIC, 'secret' => Auth::hash($secret), 'expire' => $expire, @@ -2293,8 +2293,8 @@ App::delete('/v1/users/:userId') $clone = clone $user; $dbForProject->deleteDocument('users', $userId); - DeleteIdentities::delete($dbForProject, Query::equal('userInternalId', [$user->getSequence()])); - DeleteTargets::delete($dbForProject, Query::equal('userInternalId', [$user->getSequence()])); + DeleteIdentities::delete($dbForProject, Query::equal('userInternalId', [$user->getInternalId()])); + DeleteTargets::delete($dbForProject, Query::equal('userInternalId', [$user->getInternalId()])); $queueForDeletes ->setType(DELETE_TYPE_DOCUMENT) diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 746f61c59c..571c7ddca7 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -78,11 +78,11 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $resourceCollection = $resourceType === "function" ? 'functions' : 'sites'; $resourceId = $repository->getAttribute('resourceId'); $resource = Authorization::skip(fn () => $dbForProject->getDocument($resourceCollection, $resourceId)); - $resourceInternalId = $resource->getSequence(); + $resourceInternalId = $resource->getInternalId(); $deploymentId = ID::unique(); $repositoryId = $repository->getId(); - $repositoryInternalId = $repository->getSequence(); + $repositoryInternalId = $repository->getInternalId(); $providerRepositoryId = $repository->getAttribute('providerRepositoryId'); $installationId = $repository->getAttribute('installationId'); $installationInternalId = $repository->getAttribute('installationInternalId'); @@ -157,7 +157,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId ], 'installationInternalId' => $installationInternalId, 'installationId' => $installationId, - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'projectId' => $project->getId(), 'providerRepositoryId' => $providerRepositoryId, 'providerBranch' => $providerBranch, @@ -257,7 +257,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $resource = $resource ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); Authorization::skip(fn () => $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource)); @@ -273,12 +273,12 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'domain' => $domain, 'type' => 'deployment', 'trigger' => 'deployment', 'deploymentId' => $deployment->getId(), - 'deploymentInternalId' => $deployment->getSequence(), + 'deploymentInternalId' => $deployment->getInternalId(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $resourceId, 'deploymentResourceInternalId' => $resourceInternalId, @@ -300,12 +300,12 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'domain' => $domain, 'type' => 'deployment', 'trigger' => 'deployment', 'deploymentId' => $deployment->getId(), - 'deploymentInternalId' => $deployment->getSequence(), + 'deploymentInternalId' => $deployment->getInternalId(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $resourceId, 'deploymentResourceInternalId' => $resourceInternalId, @@ -331,12 +331,12 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'domain' => $domain, 'type' => 'deployment', 'trigger' => 'deployment', 'deploymentId' => $deployment->getId(), - 'deploymentInternalId' => $deployment->getSequence(), + 'deploymentInternalId' => $deployment->getInternalId(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $resourceId, 'deploymentResourceInternalId' => $resourceInternalId, @@ -503,7 +503,7 @@ App::get('/v1/vcs/github/callback') $github->initializeVariables($providerInstallationId, $privateKey, $githubAppId); $owner = $github->getOwnerName($providerInstallationId) ?? ''; - $projectInternalId = $project->getSequence(); + $projectInternalId = $project->getInternalId(); $installation = $dbForPlatform->findOne('installations', [ Query::equal('providerInstallationId', [$providerInstallationId]), @@ -999,7 +999,7 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories') if (empty($accessToken) || empty($refreshToken) || empty($accessTokenExpiry)) { $identity = $dbForPlatform->findOne('identities', [ Query::equal('provider', ['github']), - Query::equal('userInternalId', [$user->getSequence()]), + Query::equal('userInternalId', [$user->getInternalId()]), ]); if ($identity->isEmpty()) { throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); @@ -1246,7 +1246,7 @@ App::post('/v1/vcs/github/events') foreach ($installations as $installation) { $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ - Query::equal('installationInternalId', [$installation->getSequence()]), + Query::equal('installationInternalId', [$installation->getInternalId()]), Query::limit(1000) ])); @@ -1349,7 +1349,7 @@ App::get('/v1/vcs/installations') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $queries[] = Query::equal('projectInternalId', [$project->getSequence()]); + $queries[] = Query::equal('projectInternalId', [$project->getInternalId()]); if (!empty($search)) { $queries[] = Query::search('search', $search); @@ -1422,7 +1422,7 @@ App::get('/v1/vcs/installations/:installationId') throw new Exception(Exception::INSTALLATION_NOT_FOUND); } - if ($installation->getAttribute('projectInternalId') !== $project->getSequence()) { + if ($installation->getAttribute('projectInternalId') !== $project->getInternalId()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); } @@ -1505,7 +1505,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor } $repository = Authorization::skip(fn () => $dbForPlatform->getDocument('repositories', $repositoryId, [ - Query::equal('projectInternalId', [$project->getSequence()]) + Query::equal('projectInternalId', [$project->getInternalId()]) ])); if ($repository->isEmpty()) { diff --git a/app/controllers/general.php b/app/controllers/general.php index 90a108c7c6..bff701792e 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -391,9 +391,9 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $execution = new Document([ '$id' => $executionId, '$permissions' => [], - 'resourceInternalId' => $resource->getSequence(), + 'resourceInternalId' => $resource->getInternalId(), 'resourceId' => $resource->getId(), - 'deploymentInternalId' => $deployment->getSequence(), + 'deploymentInternalId' => $deployment->getInternalId(), 'deploymentId' => $deployment->getId(), 'responseStatusCode' => 0, 'responseHeaders' => [], @@ -692,11 +692,11 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw } $metricTypeExecutions = str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_EXECUTIONS); - $metricTypeIdExecutions = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS); + $metricTypeIdExecutions = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS); $metricTypeExecutionsCompute = str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE); - $metricTypeIdExecutionsCompute = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE); + $metricTypeIdExecutionsCompute = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE); $metricTypeExecutionsMbSeconds = str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS); - $metricTypeIdExecutionsMBSeconds = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS); + $metricTypeIdExecutionsMBSeconds = str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS); if ($deployment->getAttribute('resourceType') === 'sites') { $queueForStatsUsage ->disableMetric(METRIC_NETWORK_REQUESTS) @@ -719,9 +719,9 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw ->addMetric(METRIC_SITES_REQUESTS, 1) ->addMetric(METRIC_SITES_INBOUND, $request->getSize() + $fileSize) ->addMetric(METRIC_SITES_OUTBOUND, $response->getSize()) - ->addMetric(str_replace('{siteInternalId}', $resource->getSequence(), METRIC_SITES_ID_REQUESTS), 1) - ->addMetric(str_replace('{siteInternalId}', $resource->getSequence(), METRIC_SITES_ID_INBOUND), $request->getSize() + $fileSize) - ->addMetric(str_replace('{siteInternalId}', $resource->getSequence(), METRIC_SITES_ID_OUTBOUND), $response->getSize()) + ->addMetric(str_replace('{siteInternalId}', $resource->getInternalId(), METRIC_SITES_ID_REQUESTS), 1) + ->addMetric(str_replace('{siteInternalId}', $resource->getInternalId(), METRIC_SITES_ID_INBOUND), $request->getSize() + $fileSize) + ->addMetric(str_replace('{siteInternalId}', $resource->getInternalId(), METRIC_SITES_ID_OUTBOUND), $response->getSize()) ; } @@ -914,7 +914,7 @@ App::init() 'type' => 'api', 'status' => 'verifying', 'projectId' => $console->getId(), - 'projectInternalId' => $console->getSequence(), + 'projectInternalId' => $console->getInternalId(), 'search' => implode(' ', [$ruleId, $domain->get()]), 'owner' => $owner, 'region' => $console->getAttribute('region') @@ -964,7 +964,7 @@ App::init() )[0] ?? new Document(); } - if (!$rule->isEmpty() && $rule->getAttribute('projectInternalId') === $project->getSequence()) { + if (!$rule->isEmpty() && $rule->getAttribute('projectInternalId') === $project->getInternalId()) { $refDomainOrigin = $origin; } } diff --git a/app/controllers/mock.php b/app/controllers/mock.php index fd7b9ab495..16d8e03841 100644 --- a/app/controllers/mock.php +++ b/app/controllers/mock.php @@ -185,7 +185,7 @@ App::post('/v1/mock/api-key-unprefixed') Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'projectId' => $project->getId(), 'name' => 'Outdated key', 'scopes' => $scopes, @@ -235,7 +235,7 @@ App::get('/v1/mock/github/callback') $github->initializeVariables($providerInstallationId, $privateKey, $githubAppId); $owner = $github->getOwnerName($providerInstallationId) ?? ''; - $projectInternalId = $project->getSequence(); + $projectInternalId = $project->getInternalId(); $teamId = $project->getAttribute('teamId', ''); diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index f99ebbce07..937f245099 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -574,7 +574,7 @@ App::init() $bucketId = $parts[1] ?? null; $bucket = Authorization::skip(fn () => $dbForProject->getDocument('buckets', $bucketId)); - $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getSequence(); + $isToken = !$resourceToken->isEmpty() && $resourceToken->getAttribute('bucketInternalId') === $bucket->getInternalId(); $isAPIKey = Auth::isAppUser(Authorization::getRoles()); $isPrivilegedUser = Auth::isPrivilegedUser(Authorization::getRoles()); @@ -593,12 +593,12 @@ App::init() $fileId = $parts[1] ?? null; if ($fileSecurity && !$valid && !$isToken) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } - if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getSequence()) { + if (!$resourceToken->isEmpty() && $resourceToken->getAttribute('fileInternalId') !== $file->getInternalId()) { throw new Exception(Exception::USER_UNAUTHORIZED); } diff --git a/app/http.php b/app/http.php index 30f4013821..6064dfdd4c 100644 --- a/app/http.php +++ b/app/http.php @@ -309,7 +309,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg 'orders' => $index['orders'], ]), $files['indexes']); - $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes); + $dbForPlatform->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes); } if (Authorization::skip(fn () => $dbForPlatform->getDocument('buckets', 'screenshots')->isEmpty())) { @@ -357,7 +357,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg 'orders' => $index['orders'], ]), $files['indexes']); - Authorization::skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes)); + Authorization::skip(fn () => $dbForPlatform->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes)); } }); diff --git a/app/init/database/filters.php b/app/init/database/filters.php index 98a37ec4ad..c470329706 100644 --- a/app/init/database/filters.php +++ b/app/init/database/filters.php @@ -71,7 +71,7 @@ Database::addFilter( }, function (mixed $value, Document $document, Database $database) { $attributes = $database->find('attributes', [ - Query::equal('collectionInternalId', [$document->getSequence()]), + Query::equal('collectionInternalId', [$document->getInternalId()]), Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), Query::limit($database->getLimitForAttributes()), ]); @@ -107,7 +107,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return $database ->find('indexes', [ - Query::equal('collectionInternalId', [$document->getSequence()]), + Query::equal('collectionInternalId', [$document->getInternalId()]), Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), Query::limit($database->getLimitForIndexes()), ]); @@ -122,7 +122,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return $database ->find('platforms', [ - Query::equal('projectInternalId', [$document->getSequence()]), + Query::equal('projectInternalId', [$document->getInternalId()]), Query::limit(APP_LIMIT_SUBQUERY), ]); } @@ -136,7 +136,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return $database ->find('keys', [ - Query::equal('projectInternalId', [$document->getSequence()]), + Query::equal('projectInternalId', [$document->getInternalId()]), Query::limit(APP_LIMIT_SUBQUERY), ]); } @@ -150,7 +150,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return $database ->find('devKeys', [ - Query::equal('projectInternalId', [$document->getSequence()]), + Query::equal('projectInternalId', [$document->getInternalId()]), Query::limit(APP_LIMIT_SUBQUERY), ]); } @@ -164,7 +164,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return $database ->find('webhooks', [ - Query::equal('projectInternalId', [$document->getSequence()]), + Query::equal('projectInternalId', [$document->getInternalId()]), Query::limit(APP_LIMIT_SUBQUERY), ]); } @@ -177,7 +177,7 @@ Database::addFilter( }, function (mixed $value, Document $document, Database $database) { return Authorization::skip(fn () => $database->find('sessions', [ - Query::equal('userInternalId', [$document->getSequence()]), + Query::equal('userInternalId', [$document->getInternalId()]), Query::limit(APP_LIMIT_SUBQUERY), ])); } @@ -191,7 +191,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return Authorization::skip(fn () => $database ->find('tokens', [ - Query::equal('userInternalId', [$document->getSequence()]), + Query::equal('userInternalId', [$document->getInternalId()]), Query::limit(APP_LIMIT_SUBQUERY), ])); } @@ -205,7 +205,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return Authorization::skip(fn () => $database ->find('challenges', [ - Query::equal('userInternalId', [$document->getSequence()]), + Query::equal('userInternalId', [$document->getInternalId()]), Query::limit(APP_LIMIT_SUBQUERY), ])); } @@ -219,7 +219,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return Authorization::skip(fn () => $database ->find('authenticators', [ - Query::equal('userInternalId', [$document->getSequence()]), + Query::equal('userInternalId', [$document->getInternalId()]), Query::limit(APP_LIMIT_SUBQUERY), ])); } @@ -233,7 +233,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return Authorization::skip(fn () => $database ->find('memberships', [ - Query::equal('userInternalId', [$document->getSequence()]), + Query::equal('userInternalId', [$document->getInternalId()]), Query::limit(APP_LIMIT_SUBQUERY), ])); } @@ -247,7 +247,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return $database ->find('variables', [ - Query::equal('resourceInternalId', [$document->getSequence()]), + Query::equal('resourceInternalId', [$document->getInternalId()]), Query::equal('resourceType', ['function', 'site']), Query::limit(APP_LIMIT_SUBQUERY), ]); @@ -325,7 +325,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return Authorization::skip(fn () => $database ->find('targets', [ - Query::equal('userInternalId', [$document->getSequence()]), + Query::equal('userInternalId', [$document->getInternalId()]), Query::limit(APP_LIMIT_SUBQUERY) ])); } @@ -340,13 +340,13 @@ Database::addFilter( $targetIds = Authorization::skip(fn () => \array_map( fn ($document) => $document->getAttribute('targetInternalId'), $database->find('subscribers', [ - Query::equal('topicInternalId', [$document->getSequence()]), + Query::equal('topicInternalId', [$document->getInternalId()]), Query::limit(APP_LIMIT_SUBSCRIBERS_SUBQUERY) ]) )); if (\count($targetIds) > 0) { return $database->skipValidation(fn () => $database->find('targets', [ - Query::equal('$sequence', $targetIds) + Query::equal('$internalId', $targetIds) ])); } return []; diff --git a/app/init/resources.php b/app/init/resources.php index 7c3df681b1..c75df2a362 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -347,13 +347,13 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getSequence()) + ->setTenant($project->getInternalId()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getSequence()); + ->setNamespace('_' . $project->getInternalId()); } return $database; @@ -400,13 +400,13 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getSequence()) + ->setTenant($project->getInternalId()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getSequence()); + ->setNamespace('_' . $project->getInternalId()); } }); @@ -430,7 +430,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) { return function (?Document $project = null) use ($pools, $cache, &$database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { - $database->setTenant($project->getSequence()); + $database->setTenant($project->getInternalId()); return $database; } @@ -445,7 +445,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) { // set tenant if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') { - $database->setTenant($project->getSequence()); + $database->setTenant($project->getInternalId()); } return $database; @@ -836,7 +836,7 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A $team = Authorization::skip(function () use ($dbForPlatform, $teamInternalId) { return $dbForPlatform->findOne('teams', [ - Query::equal('$sequence', [$teamInternalId]), + Query::equal('$internalId', [$teamInternalId]), ]); }); @@ -915,10 +915,10 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { return match ($token->getAttribute('resourceType')) { TOKENS_RESOURCE_TYPE_FILES => (function () use ($token, $dbForProject) { - $sequences = explode(':', $token->getAttribute('resourceInternalId')); + $internalIds = explode(':', $token->getAttribute('resourceInternalId')); $ids = explode(':', $token->getAttribute('resourceId')); - if (count($sequences) !== 2 || count($ids) !== 2) { + if (count($internalIds) !== 2 || count($ids) !== 2) { return new Document([]); } @@ -931,8 +931,8 @@ App::setResource('resourceToken', function ($project, $dbForProject, $request) { return new Document([ 'bucketId' => $ids[0], 'fileId' => $ids[1], - 'bucketInternalId' => $sequences[0], - 'fileInternalId' => $sequences[1], + 'bucketInternalId' => $internalIds[0], + 'fileInternalId' => $internalIds[1], ]); })(), diff --git a/app/realtime.php b/app/realtime.php index 96484c8a35..7e6fc0e311 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -79,8 +79,8 @@ if (!function_exists('getProjectDB')) { static $databases = []; - if (isset($databases[$project->getSequence()])) { - return $databases[$project->getSequence()]; + if (isset($databases[$project->getInternalId()])) { + return $databases[$project->getInternalId()]; } /** @var Group $pools */ @@ -105,20 +105,20 @@ if (!function_exists('getProjectDB')) { if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getSequence()) + ->setTenant($project->getInternalId()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getSequence()); + ->setNamespace('_' . $project->getInternalId()); } $database ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()); - return $databases[$project->getSequence()] = $database; + return $databases[$project->getInternalId()] = $database; } } diff --git a/app/worker.php b/app/worker.php index 2b6726c855..597e8a9943 100644 --- a/app/worker.php +++ b/app/worker.php @@ -90,13 +90,13 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getSequence()) + ->setTenant($project->getInternalId()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getSequence()); + ->setNamespace('_' . $project->getInternalId()); } $database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); @@ -127,13 +127,13 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getSequence()) + ->setTenant($project->getInternalId()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getSequence()); + ->setNamespace('_' . $project->getInternalId()); } return $database; @@ -149,13 +149,13 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getSequence()) + ->setTenant($project->getInternalId()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getSequence()); + ->setNamespace('_' . $project->getInternalId()); } $database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); @@ -168,7 +168,7 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = null; return function (?Document $project = null) use ($pools, $cache, $database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { - $database->setTenant($project->getSequence()); + $database->setTenant($project->getInternalId()); return $database; } @@ -183,7 +183,7 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) { // set tenant if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') { - $database->setTenant($project->getSequence()); + $database->setTenant($project->getInternalId()); } return $database; diff --git a/composer.json b/composer.json index 9b61351956..7e445cd36b 100644 --- a/composer.json +++ b/composer.json @@ -53,7 +53,7 @@ "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", "utopia-php/detector": "0.1.*", - "utopia-php/database": "0.71.*", + "utopia-php/database": "0.69.*", "utopia-php/domains": "0.8.0", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", @@ -62,7 +62,7 @@ "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.6.*", "utopia-php/messaging": "0.17.*", - "utopia-php/migration": "0.10.*", + "utopia-php/migration": "0.9.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", diff --git a/composer.lock b/composer.lock index dc8661f3bb..f36b815777 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "5027a541e6377eb2c87357b69f11daea", + "content-hash": "9f5de64d73e2ef73d796fa64f2baf232", "packages": [ { "name": "adhocore/jwt", @@ -1238,16 +1238,16 @@ }, { "name": "open-telemetry/exporter-otlp", - "version": "1.3.1", + "version": "1.3.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/exporter-otlp.git", - "reference": "8b3ca1f86d01429c73b407bf1a2075d9c187001e" + "reference": "19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/8b3ca1f86d01429c73b407bf1a2075d9c187001e", - "reference": "8b3ca1f86d01429c73b407bf1a2075d9c187001e", + "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c", + "reference": "19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c", "shasum": "" }, "require": { @@ -1298,7 +1298,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-21T12:02:20+00:00" + "time": "2025-05-12T00:36:35+00:00" }, { "name": "open-telemetry/gen-otlp-protobuf", @@ -1365,16 +1365,16 @@ }, { "name": "open-telemetry/sdk", - "version": "1.5.0", + "version": "1.4.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/sdk.git", - "reference": "cd0d7367599717fc29e04eb8838ec061e6c2c657" + "reference": "939d3a28395c249a763676458140dad44b3a8011" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/cd0d7367599717fc29e04eb8838ec061e6c2c657", - "reference": "cd0d7367599717fc29e04eb8838ec061e6c2c657", + "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/939d3a28395c249a763676458140dad44b3a8011", + "reference": "939d3a28395c249a763676458140dad44b3a8011", "shasum": "" }, "require": { @@ -1451,7 +1451,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-22T02:33:34+00:00" + "time": "2025-05-07T12:32:21+00:00" }, { "name": "open-telemetry/sem-conv", @@ -3499,16 +3499,16 @@ }, { "name": "utopia-php/database", - "version": "0.71.0", + "version": "0.69.5", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "cf463c0a5c64a4168fe56266ace4ae835d61c920" + "reference": "4abe53609dfc23b2ea82884d12b149df6a8af2f5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/cf463c0a5c64a4168fe56266ace4ae835d61c920", - "reference": "cf463c0a5c64a4168fe56266ace4ae835d61c920", + "url": "https://api.github.com/repos/utopia-php/database/zipball/4abe53609dfc23b2ea82884d12b149df6a8af2f5", + "reference": "4abe53609dfc23b2ea82884d12b149df6a8af2f5", "shasum": "" }, "require": { @@ -3549,9 +3549,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.71.0" + "source": "https://github.com/utopia-php/database/tree/0.69.5" }, - "time": "2025-05-23T07:32:59+00:00" + "time": "2025-05-17T08:01:51+00:00" }, { "name": "utopia-php/detector", @@ -3999,16 +3999,16 @@ }, { "name": "utopia-php/migration", - "version": "0.10.0", + "version": "0.9.3", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "0b0e94c4b5243c5566b9634b07ba2ec5f7990914" + "reference": "e518d39eb550fde36bc5cf06c9bd7b2faf5dbedd" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/0b0e94c4b5243c5566b9634b07ba2ec5f7990914", - "reference": "0b0e94c4b5243c5566b9634b07ba2ec5f7990914", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/e518d39eb550fde36bc5cf06c9bd7b2faf5dbedd", + "reference": "e518d39eb550fde36bc5cf06c9bd7b2faf5dbedd", "shasum": "" }, "require": { @@ -4049,9 +4049,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.10.0" + "source": "https://github.com/utopia-php/migration/tree/0.9.3" }, - "time": "2025-05-23T07:40:24+00:00" + "time": "2025-05-01T05:41:26+00:00" }, { "name": "utopia-php/orchestration", @@ -4816,16 +4816,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.40.18", + "version": "0.40.17", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "38de4b9c58112d7e83eb75955994c8412a401093" + "reference": "7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/38de4b9c58112d7e83eb75955994c8412a401093", - "reference": "38de4b9c58112d7e83eb75955994c8412a401093", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de", + "reference": "7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de", "shasum": "" }, "require": { @@ -4861,9 +4861,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.40.18" + "source": "https://github.com/appwrite/sdk-generator/tree/0.40.17" }, - "time": "2025-05-21T14:14:47+00:00" + "time": "2025-05-16T15:10:54+00:00" }, { "name": "doctrine/annotations", @@ -8242,7 +8242,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -8266,5 +8266,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.6.0" + "plugin-api-version": "2.3.0" } diff --git a/src/Appwrite/Deletes/Targets.php b/src/Appwrite/Deletes/Targets.php index 794ab0b87a..95e744ddf1 100644 --- a/src/Appwrite/Deletes/Targets.php +++ b/src/Appwrite/Deletes/Targets.php @@ -27,7 +27,7 @@ class Targets $database->deleteDocuments( 'subscribers', [ - Query::equal('targetInternalId', [$target->getSequence()]), + Query::equal('targetInternalId', [$target->getInternalId()]), Query::orderAsc(), ], Database::DELETE_BATCH_SIZE, @@ -35,7 +35,7 @@ class Targets $topicId = $subscriber->getAttribute('topicId'); $topicInternalId = $subscriber->getAttribute('topicInternalId'); $topic = $database->getDocument('topics', $topicId); - if (!$topic->isEmpty() && $topic->getSequence() === $topicInternalId) { + if (!$topic->isEmpty() && $topic->getInternalId() === $topicInternalId) { $totalAttribute = match ($target->getAttribute('providerType')) { MESSAGE_TYPE_EMAIL => 'emailTotal', MESSAGE_TYPE_SMS => 'smsTotal', diff --git a/src/Appwrite/Event/Event.php b/src/Appwrite/Event/Event.php index 934647f7c3..2c735ef2d4 100644 --- a/src/Appwrite/Event/Event.php +++ b/src/Appwrite/Event/Event.php @@ -320,7 +320,7 @@ class Event if ($this->project) { $trimmed['project'] = new Document([ '$id' => $this->project->getId(), - '$sequence' => $this->project->getSequence(), + '$internalId' => $this->project->getInternalId(), 'database' => $this->project->getAttribute('database') ]); } diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 73d16394c0..81ea1ef263 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -155,7 +155,7 @@ abstract class Migration */ public function forEachDocument(callable $callback): void { - $projectInternalId = $this->project->getSequence(); + $projectInternalId = $this->project->getInternalId(); $collections = match ($projectInternalId) { 'console' => $this->collections['console'], @@ -208,7 +208,7 @@ abstract class Migration { $name ??= $id; - $collectionType = match ($this->project->getSequence()) { + $collectionType = match ($this->project->getInternalId()) { 'console' => 'console', default => 'projects', }; @@ -259,7 +259,7 @@ abstract class Migration ): void { $from ??= $collectionId; - $collectionType = match ($this->project->getSequence()) { + $collectionType = match ($this->project->getInternalId()) { 'console' => 'console', default => 'projects', }; @@ -324,7 +324,7 @@ abstract class Migration ): void { $from ??= $collectionId; - $collectionType = match ($this->project->getSequence()) { + $collectionType = match ($this->project->getInternalId()) { 'console' => 'console', default => 'projects', }; @@ -382,7 +382,7 @@ abstract class Migration { $from ??= $collectionId; - $collectionType = match ($this->project->getSequence()) { + $collectionType = match ($this->project->getInternalId()) { 'console' => 'console', default => 'projects', }; @@ -428,7 +428,7 @@ abstract class Migration */ protected function changeAttributeInternalType(string $collection, string $attribute, string $type): void { - $stmt = $this->pdo->prepare("ALTER TABLE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}_{$collection}` MODIFY `$attribute` $type;"); + $stmt = $this->pdo->prepare("ALTER TABLE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$collection}` MODIFY `$attribute` $type;"); try { $stmt->execute(); diff --git a/src/Appwrite/Migration/Version/V15.php b/src/Appwrite/Migration/Version/V15.php index 15331e9a37..8eab916f19 100644 --- a/src/Appwrite/Migration/Version/V15.php +++ b/src/Appwrite/Migration/Version/V15.php @@ -95,7 +95,7 @@ class V15 extends Migration $this->migrateStatsMetric('storage.files.delete', 'files.$all.requests.delete'); foreach ($this->documentsIterator('buckets') as $bucket) { - $bucketTable = "bucket_{$bucket->getSequence()}"; + $bucketTable = "bucket_{$bucket->getInternalId()}"; $this->createPermissionsColumn($bucketTable); $this->migrateDateTimeAttribute($bucketTable, '_createdAt'); @@ -178,7 +178,7 @@ class V15 extends Migration * Migrate every Database. */ foreach ($this->documentsIterator('databases') as $database) { - $databaseTable = "database_{$database->getSequence()}"; + $databaseTable = "database_{$database->getInternalId()}"; $this->createPermissionsColumn($databaseTable); $this->migrateDateTimeAttribute($databaseTable, '_createdAt'); $this->migrateDateTimeAttribute($databaseTable, '_updatedAt'); @@ -216,7 +216,7 @@ class V15 extends Migration */ Console::info("Migrating Collections of {$database->getId()} ({$database->getAttribute('name')})"); foreach ($this->documentsIterator($databaseTable) as $collection) { - $collectionTable = "{$databaseTable}_collection_{$collection->getSequence()}"; + $collectionTable = "{$databaseTable}_collection_{$collection->getInternalId()}"; $this->createPermissionsColumn($collectionTable); $this->migrateDateTimeAttribute($collectionTable, '_createdAt'); $this->migrateDateTimeAttribute($collectionTable, '_updatedAt'); @@ -277,7 +277,7 @@ class V15 extends Migration $this->removeWritePermissions($databaseTable); try { - $this->dbForProject->deleteAttribute("database_{$database->getSequence()}", 'permission'); + $this->dbForProject->deleteAttribute("database_{$database->getInternalId()}", 'permission'); } catch (\Throwable $th) { Console::warning("'permission' from {$databaseTable}: {$th->getMessage()}"); } @@ -293,7 +293,7 @@ class V15 extends Migration protected function removeWritePermissions(string $table): void { try { - $this->pdo->prepare("DELETE FROM `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}_{$table}_perms` WHERE _type = 'write'")->execute(); + $this->pdo->prepare("DELETE FROM `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}_perms` WHERE _type = 'write'")->execute(); } catch (\Throwable $th) { Console::warning("Remove 'write' permissions from {$table}: {$th->getMessage()}"); } @@ -309,7 +309,7 @@ class V15 extends Migration */ protected function getSQLColumnTypes(string $table): array { - $query = $this->pdo->prepare("SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '_{$this->project->getSequence()}_{$table}' AND table_schema = '{$this->dbForProject->getDatabase()}'"); + $query = $this->pdo->prepare("SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '_{$this->project->getInternalId()}_{$table}' AND table_schema = '{$this->dbForProject->getDatabase()}'"); $query->execute(); return array_reduce($query->fetchAll(), function (array $carry, array $item) { @@ -331,8 +331,8 @@ class V15 extends Migration if ($columns[$attribute] === 'int') { try { - $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}_{$table}` MODIFY {$attribute} VARCHAR(64)")->execute(); - $this->pdo->prepare("UPDATE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}_{$table}` SET {$attribute} = IF({$attribute} = 0, NULL, FROM_UNIXTIME({$attribute}))")->execute(); + $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` MODIFY {$attribute} VARCHAR(64)")->execute(); + $this->pdo->prepare("UPDATE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` SET {$attribute} = IF({$attribute} = 0, NULL, FROM_UNIXTIME({$attribute}))")->execute(); $columns[$attribute] = 'varchar'; } catch (\Throwable $th) { Console::warning($th->getMessage()); @@ -341,7 +341,7 @@ class V15 extends Migration if ($columns[$attribute] === 'varchar') { try { - $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}_{$table}` MODIFY {$attribute} DATETIME(3)")->execute(); + $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` MODIFY {$attribute} DATETIME(3)")->execute(); } catch (\Throwable $th) { Console::warning($th->getMessage()); } @@ -387,7 +387,7 @@ class V15 extends Migration if (!array_key_exists('_permissions', $columns)) { try { - $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}_{$table}` ADD `_permissions` MEDIUMTEXT DEFAULT NULL")->execute(); + $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` ADD `_permissions` MEDIUMTEXT DEFAULT NULL")->execute(); } catch (\Throwable $th) { Console::warning("Add '_permissions' column to '{$table}': {$th->getMessage()}"); } @@ -408,7 +408,7 @@ class V15 extends Migration { $table ??= $document->getCollection(); - $query = $this->pdo->prepare("SELECT * FROM `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}_{$table}_perms` WHERE _document = '{$document->getId()}'"); + $query = $this->pdo->prepare("SELECT * FROM `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}_perms` WHERE _document = '{$document->getId()}'"); $query->execute(); $results = $query->fetchAll(); $permissions = []; @@ -466,7 +466,7 @@ class V15 extends Migration Console::log("Migrating Collection \"{$id}\""); - $this->dbForProject->setNamespace("_{$this->project->getSequence()}"); + $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); switch ($id) { case '_metadata': @@ -746,7 +746,7 @@ class V15 extends Migration Permission::delete(Role::any()), ], 'functionId' => $function->getId(), - 'functionInternalId' => $function->getSequence(), + 'functionInternalId' => $function->getInternalId(), 'key' => (string) $key, 'value' => (string) $value, 'search' => implode(' ', [$variableId, $key, $function->getId()]) @@ -1470,9 +1470,9 @@ class V15 extends Migration $from = $this->pdo->quote($from); $to = $this->pdo->quote($to); - $this->pdo->prepare("UPDATE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}_stats` SET metric = {$to} WHERE metric = {$from}")->execute(); + $this->pdo->prepare("UPDATE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_stats` SET metric = {$to} WHERE metric = {$from}")->execute(); } catch (\Throwable $th) { - Console::warning("Migrating steps from {$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}_stats:" . $th->getMessage()); + Console::warning("Migrating steps from {$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}_stats:" . $th->getMessage()); } } diff --git a/src/Appwrite/Migration/Version/V16.php b/src/Appwrite/Migration/Version/V16.php index 9d72af9563..34407a0471 100644 --- a/src/Appwrite/Migration/Version/V16.php +++ b/src/Appwrite/Migration/Version/V16.php @@ -45,7 +45,7 @@ class V16 extends Migration Console::log("Migrating Collection \"{$id}\""); - $this->dbForProject->setNamespace("_{$this->project->getSequence()}"); + $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); switch ($id) { case 'sessions': diff --git a/src/Appwrite/Migration/Version/V17.php b/src/Appwrite/Migration/Version/V17.php index fbbd4bfde0..f7cb08d6f4 100644 --- a/src/Appwrite/Migration/Version/V17.php +++ b/src/Appwrite/Migration/Version/V17.php @@ -44,7 +44,7 @@ class V17 extends Migration protected function migrateBuckets(): void { foreach ($this->documentsIterator('buckets') as $bucket) { - $id = "bucket_{$bucket->getSequence()}"; + $id = "bucket_{$bucket->getInternalId()}"; try { $this->dbForProject->updateAttribute($id, 'mimeType', Database::VAR_STRING, 255, true, false); @@ -67,7 +67,7 @@ class V17 extends Migration Console::log("Migrating Collection \"{$id}\""); - $this->dbForProject->setNamespace("_{$this->project->getSequence()}"); + $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); switch ($id) { case 'builds': diff --git a/src/Appwrite/Migration/Version/V18.php b/src/Appwrite/Migration/Version/V18.php index aa2ad35cca..a5fae3789b 100644 --- a/src/Appwrite/Migration/Version/V18.php +++ b/src/Appwrite/Migration/Version/V18.php @@ -26,7 +26,7 @@ class V18 extends Migration } Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); - $this->dbForProject->setNamespace("_{$this->project->getSequence()}"); + $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); $this->addDocumentSecurityToProject(); Console::info('Migrating Databases'); @@ -48,12 +48,12 @@ class V18 extends Migration private function migrateDatabases(): void { foreach ($this->documentsIterator('databases') as $database) { - $databaseTable = "database_{$database->getSequence()}"; + $databaseTable = "database_{$database->getInternalId()}"; Console::info("Migrating Collections of {$database->getId()} ({$database->getAttribute('name')})"); foreach ($this->documentsIterator($databaseTable) as $collection) { - $collectionTable = "{$databaseTable}_collection_{$collection->getSequence()}"; + $collectionTable = "{$databaseTable}_collection_{$collection->getInternalId()}"; foreach ($collection['attributes'] ?? [] as $attribute) { if ($attribute['type'] !== Database::VAR_FLOAT) { @@ -197,7 +197,7 @@ class V18 extends Migration * Set the bucket permission in the metadata table */ try { - $internalBucketId = "bucket_{$this->project->getSequence()}"; + $internalBucketId = "bucket_{$this->project->getInternalId()}"; $permissions = $document->getPermissions(); $fileSecurity = $document->getAttribute('fileSecurity', false); $this->dbForProject->updateCollection($internalBucketId, $permissions, $fileSecurity); @@ -224,8 +224,8 @@ class V18 extends Migration // Nonetheless, there's nothing else we can do here. break; } - $sequence = $user->getSequence(); - $document->setAttribute('userId', $sequence); + $internalId = $user->getInternalId(); + $document->setAttribute('userId', $internalId); $data = $document->getAttribute('data', []); $data['userId'] = $user->getId(); $document->setAttribute('data', $data); @@ -244,7 +244,7 @@ class V18 extends Migration /** * Create 'documentSecurity' column */ - $this->pdo->prepare("ALTER TABLE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}__metadata` ADD COLUMN IF NOT EXISTS documentSecurity TINYINT(1);")->execute(); + $this->pdo->prepare("ALTER TABLE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}__metadata` ADD COLUMN IF NOT EXISTS documentSecurity TINYINT(1);")->execute(); } catch (\Throwable $th) { Console::warning($th->getMessage()); } @@ -253,7 +253,7 @@ class V18 extends Migration /** * Set 'documentSecurity' column to 1 if NULL */ - $this->pdo->prepare("UPDATE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getSequence()}__metadata` SET documentSecurity = 1 WHERE documentSecurity IS NULL")->execute(); + $this->pdo->prepare("UPDATE `{$this->dbForProject->getDatabase()}`.`_{$this->project->getInternalId()}__metadata` SET documentSecurity = 1 WHERE documentSecurity IS NULL")->execute(); } catch (\Throwable $th) { Console::warning($th->getMessage()); } diff --git a/src/Appwrite/Migration/Version/V19.php b/src/Appwrite/Migration/Version/V19.php index d4dda02d75..cae27cc6ed 100644 --- a/src/Appwrite/Migration/Version/V19.php +++ b/src/Appwrite/Migration/Version/V19.php @@ -28,7 +28,7 @@ class V19 extends Migration } Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); - $this->dbForProject->setNamespace("_{$this->project->getSequence()}"); + $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); Console::info('Migrating Collections'); $this->migrateCollections(); @@ -100,7 +100,7 @@ class V19 extends Migration protected function migrateBuckets(): void { foreach ($this->documentsIterator('buckets') as $bucket) { - $id = "bucket_{$bucket->getSequence()}"; + $id = "bucket_{$bucket->getInternalId()}"; Console::log("Migrating Bucket {$id} {$bucket->getId()} ({$bucket->getAttribute('name')})"); try { @@ -121,7 +121,7 @@ class V19 extends Migration */ private function migrateCollections(): void { - $internalProjectId = $this->project->getSequence(); + $internalProjectId = $this->project->getInternalId(); $collectionType = match ($internalProjectId) { 'console' => 'console', default => 'projects', @@ -680,7 +680,7 @@ class V19 extends Migration case 'builds': $deploymentId = $document->getAttribute('deploymentId'); $deployment = $this->dbForProject->getDocument('deployments', $deploymentId); - $document->setAttribute('deploymentInternalId', $deployment->getSequence()); + $document->setAttribute('deploymentInternalId', $deployment->getInternalId()); $stdout = $document->getAttribute('stdout', ''); $stderr = $document->getAttribute('stderr', ''); @@ -692,12 +692,12 @@ class V19 extends Migration case 'deployments': $resourceId = $document->getAttribute('resourceId'); $function = $this->dbForProject->getDocument('functions', $resourceId); - $document->setAttribute('resourceInternalId', $function->getSequence()); + $document->setAttribute('resourceInternalId', $function->getInternalId()); $buildId = $document->getAttribute('buildId'); if (!empty($buildId)) { $build = $this->dbForProject->getDocument('builds', $buildId); - $document->setAttribute('buildInternalId', $build->getSequence()); + $document->setAttribute('buildInternalId', $build->getInternalId()); } $commands = $this->getFunctionCommands($function); @@ -707,11 +707,11 @@ class V19 extends Migration case 'executions': $functionId = $document->getAttribute('functionId'); $function = $this->dbForProject->getDocument('functions', $functionId); - $document->setAttribute('functionInternalId', $function->getSequence()); + $document->setAttribute('functionInternalId', $function->getInternalId()); $deploymentId = $document->getAttribute('deploymentId'); $deployment = $this->dbForProject->getDocument('deployments', $deploymentId); - $document->setAttribute('deploymentInternalId', $deployment->getSequence()); + $document->setAttribute('deploymentInternalId', $deployment->getInternalId()); break; case 'functions': $document->setAttribute('live', $document->getAttribute('live', true)); @@ -721,7 +721,7 @@ class V19 extends Migration if (!empty($deploymentId)) { $deployment = $this->dbForProject->getDocument('deployments', $deploymentId); - $document->setAttribute('deploymentInternalId', $deployment->getSequence()); + $document->setAttribute('deploymentInternalId', $deployment->getInternalId()); $document->setAttribute('entrypoint', $deployment->getAttribute('entrypoint')); } @@ -733,7 +733,7 @@ class V19 extends Migration 'region' => $project->getAttribute('region'), 'resourceType' => 'function', 'resourceId' => $document->getId(), - 'resourceInternalId' => $document->getSequence(), + 'resourceInternalId' => $document->getInternalId(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $this->project->getId(), 'schedule' => $document->getAttribute('schedule'), @@ -741,7 +741,7 @@ class V19 extends Migration ])); $document->setAttribute('scheduleId', $schedule->getId()); - $document->setAttribute('scheduleInternalId', $schedule->getSequence()); + $document->setAttribute('scheduleInternalId', $schedule->getInternalId()); } break; @@ -799,7 +799,7 @@ class V19 extends Migration */ public function forEachDocument(callable $callback): void { - $internalProjectId = $this->project->getSequence(); + $internalProjectId = $this->project->getInternalId(); $collections = match ($internalProjectId) { 'console' => $this->collections['console'], diff --git a/src/Appwrite/Migration/Version/V20.php b/src/Appwrite/Migration/Version/V20.php index 9ff041eb33..3a9bba6772 100644 --- a/src/Appwrite/Migration/Version/V20.php +++ b/src/Appwrite/Migration/Version/V20.php @@ -36,13 +36,13 @@ class V20 extends Migration } Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); - $this->dbForProject->setNamespace("_{$this->project->getSequence()}"); + $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); Console::info('Migrating Collections'); $this->migrateCollections(); // No need to migrate stats for console - if ($this->project->getSequence() !== 'console') { + if ($this->project->getInternalId() !== 'console') { $this->migrateUsageMetrics('project.$all.network.requests', 'network.requests'); $this->migrateUsageMetrics('project.$all.network.outbound', 'network.outbound'); $this->migrateUsageMetrics('project.$all.network.inbound', 'network.inbound'); @@ -71,7 +71,7 @@ class V20 extends Migration */ private function migrateCollections(): void { - $internalProjectId = $this->project->getSequence(); + $internalProjectId = $this->project->getInternalId(); $collectionType = match ($internalProjectId) { 'console' => 'console', default => 'projects', @@ -510,7 +510,7 @@ class V20 extends Migration Console::log("Migrating Functions usage stats of {$function->getId()} ({$function->getAttribute('name')})"); $functionId = $function->getId(); - $functionInternalId = $function->getSequence(); + $functionInternalId = $function->getInternalId(); $this->migrateUsageMetrics("deployment.$functionId.storage.size", "function.$functionInternalId.deployments.storage"); $this->migrateUsageMetrics("builds.$functionId.compute.total", "$functionInternalId.builds"); @@ -536,22 +536,22 @@ class V20 extends Migration foreach ($this->documentsIterator('databases') as $database) { Console::log("Migrating Collections of {$database->getId()} ({$database->getAttribute('name')})"); - $databaseTable = "database_{$database->getSequence()}"; + $databaseTable = "database_{$database->getInternalId()}"; // Database level $databaseId = $database->getId(); - $databaseInternalId = $database->getSequence(); + $databaseInternalId = $database->getInternalId(); $this->migrateUsageMetrics("collections.$databaseId.count.total", "$databaseInternalId.collections"); $this->migrateUsageMetrics("documents.$databaseId.count.total", "$databaseInternalId.documents"); foreach ($this->documentsIterator($databaseTable) as $collection) { - $collectionTable = "{$databaseTable}_collection_{$collection->getSequence()}"; + $collectionTable = "{$databaseTable}_collection_{$collection->getInternalId()}"; Console::log("Migrating Collections of {$collectionTable} {$collection->getId()} ({$collection->getAttribute('name')})"); // Collection level $collectionId = $collection->getId(); - $collectionInternalId = $collection->getSequence(); + $collectionInternalId = $collection->getInternalId(); $this->migrateUsageMetrics("documents.$databaseId/$collectionId.count.total", "$databaseInternalId.$collectionInternalId.documents"); } @@ -573,12 +573,12 @@ class V20 extends Migration $this->migrateUsageMetrics('files.$all.storage.size', 'files.storage'); foreach ($this->documentsIterator('buckets') as $bucket) { - $id = "bucket_{$bucket->getSequence()}"; + $id = "bucket_{$bucket->getInternalId()}"; Console::log("Migrating Bucket {$id} {$bucket->getId()} ({$bucket->getAttribute('name')})"); // Bucket level $bucketId = $bucket->getId(); - $bucketInternalId = $bucket->getSequence(); + $bucketInternalId = $bucket->getInternalId(); $this->migrateUsageMetrics("files.$bucketId.count.total", "$bucketInternalId.files"); $this->migrateUsageMetrics("files.$bucketId.storage.size", "$bucketInternalId.files.storage"); @@ -605,7 +605,7 @@ class V20 extends Migration $target = new Document([ '$id' => ID::unique(), 'userId' => $document->getId(), - 'userInternalId' => $document->getSequence(), + 'userInternalId' => $document->getInternalId(), 'providerType' => MESSAGE_TYPE_EMAIL, 'identifier' => $document->getAttribute('email'), ]); @@ -620,7 +620,7 @@ class V20 extends Migration $target = new Document([ '$id' => ID::unique(), 'userId' => $document->getId(), - 'userInternalId' => $document->getSequence(), + 'userInternalId' => $document->getInternalId(), 'providerType' => MESSAGE_TYPE_SMS, 'identifier' => $document->getAttribute('phone'), ]); diff --git a/src/Appwrite/Migration/Version/V21.php b/src/Appwrite/Migration/Version/V21.php index 891d2a92fe..38e8a8d513 100644 --- a/src/Appwrite/Migration/Version/V21.php +++ b/src/Appwrite/Migration/Version/V21.php @@ -29,12 +29,12 @@ class V21 extends Migration } Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); - $this->dbForProject->setNamespace("_{$this->project->getSequence()}"); + $this->dbForProject->setNamespace("_{$this->project->getInternalId()}"); Console::info('Migrating Collections'); $this->migrateCollections(); - if ($this->project->getSequence() !== 'console') { + if ($this->project->getInternalId() !== 'console') { Console::info('Migrating Buckets'); $this->migrateBuckets(); } @@ -51,7 +51,7 @@ class V21 extends Migration */ private function migrateCollections(): void { - $internalProjectId = $this->project->getSequence(); + $internalProjectId = $this->project->getInternalId(); $collectionType = match ($internalProjectId) { 'console' => 'console', default => 'projects', @@ -251,7 +251,7 @@ class V21 extends Migration private function migrateBuckets(): void { $this->dbForProject->forEach('buckets', function (Document $bucket) { - $bucketId = 'bucket_' . $bucket['$sequence']; + $bucketId = 'bucket_' . $bucket['$internalId']; Console::log("Migrating Bucket {$bucketId} {$bucket->getId()} ({$bucket->getAttribute('name')})"); diff --git a/src/Appwrite/Migration/Version/V22.php b/src/Appwrite/Migration/Version/V22.php index a99e07de59..50d5bdbb85 100644 --- a/src/Appwrite/Migration/Version/V22.php +++ b/src/Appwrite/Migration/Version/V22.php @@ -49,7 +49,7 @@ class V22 extends Migration */ private function migrateCollections(): void { - $projectInternalId = $this->project->getSequence(); + $projectInternalId = $this->project->getInternalId(); if (empty($projectInternalId)) { throw new Exception('Project ID is null'); @@ -394,7 +394,7 @@ class V22 extends Migration 2. Fill "deploymentCreatedAt" with deployment's "$createdAt" --- Fetch latestDeployment using find() 3. Fill latestDeploymentId with latestDeployment's "$id" - 4. Fill latestDeploymentInternalId with latestDeployment's "$sequence" + 4. Fill latestDeploymentInternalId with latestDeployment's "$internalId" 5. Fill latestDeploymentCreatedAt with latestDeployment's "$createdAt" 6. Fill latestDeploymentStatus with latestDeployment's build's "status" */ @@ -433,7 +433,7 @@ class V22 extends Migration $document ->setAttribute('latestDeploymentId', $latestDeployment->getId()) - ->setAttribute('latestDeploymentInternalId', $latestDeployment->getSequence()) + ->setAttribute('latestDeploymentInternalId', $latestDeployment->getInternalId()) ->setAttribute('latestDeploymentCreatedAt', $latestDeployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $latestBuild->getAttribute('status', $document->getAttribute('latestDeploymentStatus', ''))); break; @@ -497,7 +497,7 @@ class V22 extends Migration private function cleanCollections(): void { - $projectInternalId = $this->project->getSequence(); + $projectInternalId = $this->project->getInternalId(); $collectionType = match ($projectInternalId) { 'console' => 'console', diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php index 71c436b0a0..47529a142b 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -69,13 +69,13 @@ class Base extends Action Permission::delete(Role::any()), ], 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getSequence(), + 'resourceInternalId' => $function->getInternalId(), 'resourceType' => 'functions', 'entrypoint' => $entrypoint, 'buildCommands' => $function->getAttribute('commands', ''), 'type' => 'vcs', 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getSequence(), + 'installationInternalId' => $installation->getInternalId(), 'providerRepositoryId' => $providerRepositoryId, 'repositoryId' => $function->getAttribute('repositoryId', ''), 'repositoryInternalId' => $function->getAttribute('repositoryInternalId', ''), @@ -95,7 +95,7 @@ class Base extends Action $function = $function ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); @@ -166,7 +166,7 @@ class Base extends Action Permission::delete(Role::any()), ], 'resourceId' => $site->getId(), - 'resourceInternalId' => $site->getSequence(), + 'resourceInternalId' => $site->getInternalId(), 'resourceType' => 'sites', 'buildCommands' => implode(' && ', $commands), 'buildOutput' => $site->getAttribute('outputDirectory', ''), @@ -174,7 +174,7 @@ class Base extends Action 'fallbackFile' => $site->getAttribute('fallbackFile', ''), 'type' => 'vcs', 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getSequence(), + 'installationInternalId' => $installation->getInternalId(), 'providerRepositoryId' => $providerRepositoryId, 'repositoryId' => $site->getAttribute('repositoryId', ''), 'repositoryInternalId' => $site->getAttribute('repositoryInternalId', ''), @@ -194,7 +194,7 @@ class Base extends Action $site = $site ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('sites', $site->getId(), $site); @@ -209,15 +209,15 @@ class Base extends Action fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'domain' => $domain, 'trigger' => 'deployment', 'type' => 'deployment', 'deploymentId' => $deployment->getId(), - 'deploymentInternalId' => $deployment->getSequence(), + 'deploymentInternalId' => $deployment->getInternalId(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $site->getId(), - 'deploymentResourceInternalId' => $site->getSequence(), + 'deploymentResourceInternalId' => $site->getInternalId(), 'deploymentVcsProviderBranch' => $providerBranch, 'status' => 'verified', 'certificateId' => '', @@ -244,7 +244,7 @@ class Base extends Action do { $queries = \array_merge([ Query::limit($limit), - Query::equal("projectInternalId", [$project->getSequence()]) + Query::equal("projectInternalId", [$project->getInternalId()]) ], $queries); if ($cursor !== null) { diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php index 007cea0252..1f3febbfef 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Create.php @@ -237,7 +237,7 @@ class Create extends Action Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'resourceInternalId' => $function->getSequence(), + 'resourceInternalId' => $function->getInternalId(), 'resourceId' => $function->getId(), 'resourceType' => 'functions', 'entrypoint' => $entrypoint, @@ -252,7 +252,7 @@ class Create extends Action $function = $function ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); @@ -274,7 +274,7 @@ class Create extends Action Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'resourceInternalId' => $function->getSequence(), + 'resourceInternalId' => $function->getInternalId(), 'resourceId' => $function->getId(), 'resourceType' => 'functions', 'entrypoint' => $entrypoint, @@ -291,7 +291,7 @@ class Create extends Action $function = $function ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php index 912e12bdc1..84878055d8 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Delete.php @@ -101,7 +101,7 @@ class Delete extends Action if ($function->getAttribute('latestDeploymentId') === $deployment->getId()) { $latestDeployment = $dbForProject->findOne('deployments', [ Query::equal('resourceType', ['functions']), - Query::equal('resourceInternalId', [$function->getSequence()]), + Query::equal('resourceInternalId', [$function->getInternalId()]), Query::orderDesc('$createdAt'), ]); $function = $dbForProject->updateDocument( @@ -109,7 +109,7 @@ class Delete extends Action $function->getId(), $function ->setAttribute('latestDeploymentCreatedAt', $latestDeployment->isEmpty() ? '' : $latestDeployment->getCreatedAt()) - ->setAttribute('latestDeploymentInternalId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getSequence()) + ->setAttribute('latestDeploymentInternalId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getInternalId()) ->setAttribute('latestDeploymentId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getId()) ->setAttribute('latestDeploymentStatus', $latestDeployment->isEmpty() ? '' : $latestDeployment->getAttribute('status', '')) ); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php index 0a07440dff..8f739dd37f 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Duplicate/Create.php @@ -96,9 +96,9 @@ class Create extends Action $destination = $deviceForFunctions->getPath($deploymentId . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION)); $deviceForFunctions->transfer($path, $destination, $deviceForFunctions); - $deployment->removeAttribute('$sequence'); + $deployment->removeAttribute('$internalId'); $deployment = $dbForProject->createDocument('deployments', $deployment->setAttributes([ - '$sequence' => '', + '$internalId' => '', '$id' => $deploymentId, 'sourcePath' => $destination, 'totalSize' => $deployment->getAttribute('sourceSize', 0), @@ -115,7 +115,7 @@ class Create extends Action $function = $function ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php index 4c924a64d1..c5436d1d05 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Status/Update.php @@ -97,7 +97,7 @@ class Update extends Action 'status' => 'canceled' ])); - if ($deployment->getSequence() === $function->getAttribute('latestDeploymentInternalId', '')) { + if ($deployment->getInternalId() === $function->getAttribute('latestDeploymentInternalId', '')) { $function = $function->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php index f1bd4b71e4..55230bd4a5 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Template/Create.php @@ -142,7 +142,7 @@ class Create extends Base Permission::delete(Role::any()), ], 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getSequence(), + 'resourceInternalId' => $function->getInternalId(), 'resourceType' => 'functions', 'entrypoint' => $function->getAttribute('entrypoint', ''), 'buildCommands' => $function->getAttribute('commands', ''), @@ -152,7 +152,7 @@ class Create extends Base $function = $function ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php index 2ffcfc5d11..38f1f38e89 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/XList.php @@ -84,7 +84,7 @@ class XList extends Action } // Set resource queries - $queries[] = Query::equal('resourceInternalId', [$function->getSequence()]); + $queries[] = Query::equal('resourceInternalId', [$function->getInternalId()]); $queries[] = Query::equal('resourceType', ['functions']); /** diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php index 0aec31e5fd..fd1b2076a8 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Create.php @@ -253,10 +253,10 @@ class Create extends Base $execution = new Document([ '$id' => $executionId, '$permissions' => !$user->isEmpty() ? [Permission::read(Role::user($user->getId()))] : [], - 'resourceInternalId' => $function->getSequence(), + 'resourceInternalId' => $function->getInternalId(), 'resourceId' => $function->getId(), 'resourceType' => 'functions', - 'deploymentInternalId' => $deployment->getSequence(), + 'deploymentInternalId' => $deployment->getInternalId(), 'deploymentId' => $deployment->getId(), 'trigger' => (!is_null($scheduledAt)) ? 'schedule' : 'http', 'status' => $status, // waiting / processing / completed / failed / scheduled @@ -305,7 +305,7 @@ class Create extends Base 'region' => $project->getAttribute('region'), 'resourceType' => ScheduleExecutions::getSupportedResource(), 'resourceId' => $execution->getId(), - 'resourceInternalId' => $execution->getSequence(), + 'resourceInternalId' => $execution->getInternalId(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -315,7 +315,7 @@ class Create extends Base $execution = $execution ->setAttribute('scheduleId', $schedule->getId()) - ->setAttribute('scheduleInternalId', $schedule->getSequence()) + ->setAttribute('scheduleInternalId', $schedule->getInternalId()) ->setAttribute('scheduledAt', $scheduledAt); $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); @@ -439,13 +439,13 @@ class Create extends Base $queueForStatsUsage ->addMetric(METRIC_EXECUTIONS, 1) ->addMetric(str_replace(['{resourceType}'], [RESOURCE_TYPE_FUNCTIONS], METRIC_RESOURCE_TYPE_EXECUTIONS), 1) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), 1) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), 1) ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000)) // per project ->addMetric(str_replace(['{resourceType}'], [RESOURCE_TYPE_FUNCTIONS], METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function ->addMetric(METRIC_EXECUTIONS_MB_SECONDS, (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ->addMetric(str_replace(['{resourceType}'], [RESOURCE_TYPE_FUNCTIONS], METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ; $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php index 8a3d5f2a49..cd85b5e534 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Delete.php @@ -84,7 +84,7 @@ class Delete extends Base throw new Exception(Exception::EXECUTION_NOT_FOUND); } - if ($execution->getAttribute('resourceType') !== 'functions' && $execution->getAttribute('resourceInternalId') !== $function->getSequence()) { + if ($execution->getAttribute('resourceType') !== 'functions' && $execution->getAttribute('resourceInternalId') !== $function->getInternalId()) { throw new Exception(Exception::EXECUTION_NOT_FOUND); } $status = $execution->getAttribute('status'); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php index 659682ab55..892ce30f47 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/Get.php @@ -72,7 +72,7 @@ class Get extends Base $execution = $dbForProject->getDocument('executions', $executionId); - if ($execution->getAttribute('resourceType') !== 'functions' || $execution->getAttribute('resourceInternalId') !== $function->getSequence()) { + if ($execution->getAttribute('resourceType') !== 'functions' || $execution->getAttribute('resourceInternalId') !== $function->getInternalId()) { throw new Exception(Exception::EXECUTION_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php index 91683c915b..a31e95b1c8 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Executions/XList.php @@ -83,7 +83,7 @@ class XList extends Base } // Set internal queries - $queries[] = Query::equal('resourceInternalId', [$function->getSequence()]); + $queries[] = Query::equal('resourceInternalId', [$function->getInternalId()]); $queries[] = Query::equal('resourceType', ['functions']); /** diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php index c644c681d8..fd8da657eb 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Create.php @@ -222,7 +222,7 @@ class Create extends Base 'search' => implode(' ', [$functionId, $name, $runtime]), 'version' => 'v5', 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getSequence(), + 'installationInternalId' => $installation->getInternalId(), 'providerRepositoryId' => $providerRepositoryId, 'repositoryId' => '', 'repositoryInternalId' => '', @@ -237,7 +237,7 @@ class Create extends Base 'region' => $project->getAttribute('region'), 'resourceType' => 'function', 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getSequence(), + 'resourceInternalId' => $function->getInternalId(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $function->getAttribute('schedule'), @@ -246,7 +246,7 @@ class Create extends Base ); $function->setAttribute('scheduleId', $schedule->getId()); - $function->setAttribute('scheduleInternalId', $schedule->getSequence()); + $function->setAttribute('scheduleInternalId', $schedule->getInternalId()); // Git connect logic if (!empty($providerRepositoryId)) { @@ -262,18 +262,18 @@ class Create extends Base Permission::delete(Role::team(ID::custom($teamId), 'developer')), ], 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getSequence(), + 'installationInternalId' => $installation->getInternalId(), 'projectId' => $project->getId(), - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'providerRepositoryId' => $providerRepositoryId, 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getSequence(), + 'resourceInternalId' => $function->getInternalId(), 'resourceType' => 'function', 'providerPullRequestIds' => [] ])); $function->setAttribute('repositoryId', $repository->getId()); - $function->setAttribute('repositoryInternalId', $repository->getSequence()); + $function->setAttribute('repositoryInternalId', $repository->getInternalId()); } $function = $dbForProject->updateDocument('functions', $function->getId(), $function); @@ -316,7 +316,7 @@ class Create extends Base $function = $function ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); @@ -331,7 +331,7 @@ class Create extends Base Permission::delete(Role::any()), ], 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getSequence(), + 'resourceInternalId' => $function->getInternalId(), 'resourceType' => 'functions', 'entrypoint' => $function->getAttribute('entrypoint', ''), 'buildCommands' => $function->getAttribute('commands', ''), @@ -341,7 +341,7 @@ class Create extends Base $function = $function ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('functions', $function->getId(), $function); @@ -364,16 +364,16 @@ class Create extends Base fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'domain' => $domain, 'status' => 'verified', 'type' => 'deployment', 'trigger' => 'manual', 'deploymentId' => !isset($deployment) || $deployment->isEmpty() ? '' : $deployment->getId(), - 'deploymentInternalId' => !isset($deployment) || $deployment->isEmpty() ? '' : $deployment->getSequence(), + 'deploymentInternalId' => !isset($deployment) || $deployment->isEmpty() ? '' : $deployment->getInternalId(), 'deploymentResourceType' => 'function', 'deploymentResourceId' => $function->getId(), - 'deploymentResourceInternalId' => $function->getSequence(), + 'deploymentResourceInternalId' => $function->getInternalId(), 'deploymentVcsProviderBranch' => '', 'certificateId' => '', 'search' => implode(' ', [$ruleId, $domain]), diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php index 1f3e39dee1..6de71cfae6 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -92,7 +92,7 @@ class Update extends Base $oldDeploymentInternalId = $function->getAttribute('deploymentInternalId', ''); $function = $dbForProject->updateDocument('functions', $function->getId(), new Document(array_merge($function->getArrayCopy(), [ - 'deploymentInternalId' => $deployment->getSequence(), + 'deploymentInternalId' => $deployment->getInternalId(), 'deploymentId' => $deployment->getId(), 'deploymentCreatedAt' => $deployment->getCreatedAt(), ]))); @@ -109,7 +109,7 @@ class Update extends Base Query::equal('trigger', 'manual'), Query::equal("type", ["deployment"]), Query::equal("deploymentResourceType", ["function"]), - Query::equal("deploymentResourceInternalId", [$function->getSequence()]), + Query::equal("deploymentResourceInternalId", [$function->getInternalId()]), ]; if (empty($oldDeploymentInternalId)) { @@ -121,7 +121,7 @@ class Update extends Base $this->listRules($project, $queries, $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) - ->setAttribute('deploymentInternalId', $deployment->getSequence()); + ->setAttribute('deploymentInternalId', $deployment->getInternalId()); $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); }); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php index 2bfe8b1344..a19ec1e278 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Update.php @@ -175,8 +175,8 @@ class Update extends Base // Git disconnect logic. Disconnecting only when providerRepositoryId is empty, allowing for continue updates without disconnecting git if ($isConnected && ($providerRepositoryId !== null && empty($providerRepositoryId))) { $repositories = $dbForPlatform->find('repositories', [ - Query::equal('projectInternalId', [$project->getSequence()]), - Query::equal('resourceInternalId', [$function->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('resourceInternalId', [$function->getInternalId()]), Query::equal('resourceType', ['function']), Query::limit(100), ]); @@ -208,18 +208,18 @@ class Update extends Base Permission::delete(Role::team(ID::custom($teamId), 'developer')), ], 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getSequence(), + 'installationInternalId' => $installation->getInternalId(), 'projectId' => $project->getId(), - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'providerRepositoryId' => $providerRepositoryId, 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getSequence(), + 'resourceInternalId' => $function->getInternalId(), 'resourceType' => 'function', 'providerPullRequestIds' => [] ])); $repositoryId = $repository->getId(); - $repositoryInternalId = $repository->getSequence(); + $repositoryInternalId = $repository->getInternalId(); } $live = true; @@ -260,7 +260,7 @@ class Update extends Base 'commands' => $commands, 'scopes' => $scopes, 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getSequence(), + 'installationInternalId' => $installation->getInternalId(), 'providerRepositoryId' => $providerRepositoryId, 'repositoryId' => $repositoryId, 'repositoryInternalId' => $repositoryInternalId, diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php index 947da4cd37..e0d659c9ba 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Usage/Get.php @@ -70,17 +70,17 @@ class Get extends Base $stats = $usage = []; $days = $periods[$range]; $metrics = [ - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php index ee892fe1ed..9300524c64 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Create.php @@ -96,7 +96,7 @@ class Create extends Base Permission::delete(Role::team(ID::custom($teamId), 'owner')), Permission::delete(Role::team(ID::custom($teamId), 'developer')), ], - 'resourceInternalId' => $function->getSequence(), + 'resourceInternalId' => $function->getInternalId(), 'resourceId' => $function->getId(), 'resourceType' => 'function', 'key' => $key, diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php index dda1f97f6b..3d6bfebcb9 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Delete.php @@ -74,7 +74,7 @@ class Delete extends Base } $variable = $dbForProject->getDocument('variables', $variableId); - if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $function->getSequence() || $variable->getAttribute('resourceType') !== 'function') { + if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $function->getInternalId() || $variable->getAttribute('resourceType') !== 'function') { throw new Exception(Exception::VARIABLE_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Get.php index 98119c4a66..70cc66219a 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Get.php @@ -68,7 +68,7 @@ class Get extends Base if ( $variable === false || $variable->isEmpty() || - $variable->getAttribute('resourceInternalId') !== $function->getSequence() || + $variable->getAttribute('resourceInternalId') !== $function->getInternalId() || $variable->getAttribute('resourceType') !== 'function' ) { throw new Exception(Exception::VARIABLE_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php index 7a6acf88e3..4102022267 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Variables/Update.php @@ -81,7 +81,7 @@ class Update extends Base } $variable = $dbForProject->getDocument('variables', $variableId); - if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $function->getSequence() || $variable->getAttribute('resourceType') !== 'function') { + if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $function->getInternalId() || $variable->getAttribute('resourceType') !== 'function') { throw new Exception(Exception::VARIABLE_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index a01250c05a..0ecf1d3f73 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -274,7 +274,7 @@ class Builds extends Action $deployment->setAttribute('status', 'processing'); $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); - if ($deployment->getSequence() === $resource->getAttribute('latestDeploymentInternalId', '')) { + if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) { $resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource); } @@ -524,7 +524,7 @@ class Builds extends Action $deployment->setAttribute('status', 'building'); $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); - if ($deployment->getSequence() === $resource->getAttribute('latestDeploymentInternalId', '')) { + if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) { $resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource); } @@ -887,9 +887,9 @@ class Builds extends Action if ($resource->getCollection() === 'sites') { try { $rule = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ - Query::equal("projectInternalId", [$project->getSequence()]), + Query::equal("projectInternalId", [$project->getInternalId()]), Query::equal("type", ["deployment"]), - Query::equal('deploymentInternalId', [$deployment->getSequence()]), + Query::equal('deploymentInternalId', [$deployment->getInternalId()]), ])); if ($rule->isEmpty()) { @@ -928,9 +928,9 @@ class Builds extends Action str_replace(["{resourceType}"], [RESOURCE_TYPE_SITES], METRIC_RESOURCE_TYPE_EXECUTIONS), str_replace(["{resourceType}"], [RESOURCE_TYPE_SITES], METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE), str_replace(["{resourceType}"], [RESOURCE_TYPE_SITES], METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS), - str_replace(["{resourceType}", "{resourceInternalId}"], [RESOURCE_TYPE_SITES, $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), - str_replace(["{resourceType}", "{resourceInternalId}"], [RESOURCE_TYPE_SITES, $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), - str_replace(["{resourceType}", "{resourceInternalId}"], [RESOURCE_TYPE_SITES, $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), + str_replace(["{resourceType}", "{resourceInternalId}"], [RESOURCE_TYPE_SITES, $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), + str_replace(["{resourceType}", "{resourceInternalId}"], [RESOURCE_TYPE_SITES, $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), + str_replace(["{resourceType}", "{resourceInternalId}"], [RESOURCE_TYPE_SITES, $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), ], 'bannerDisabled' => true, 'projectCheckDisabled' => true, @@ -1000,7 +1000,7 @@ class Builds extends Action Permission::read(Role::team(ID::custom($teamId))), ], 'bucketId' => $bucket->getId(), - 'bucketInternalId' => $bucket->getSequence(), + 'bucketInternalId' => $bucket->getInternalId(), 'name' => $fileName, 'path' => $path, 'signature' => $deviceForFiles->getFileHash($path), @@ -1019,7 +1019,7 @@ class Builds extends Action 'metadata' => ['content_type' => $deviceForFiles->getFileMimeType($path)], ]); - Authorization::skip(fn () => $dbForPlatform->createDocument('bucket_' . $bucket->getSequence(), $file)); + Authorization::skip(fn () => $dbForPlatform->createDocument('bucket_' . $bucket->getInternalId(), $file)); $deployment->setAttribute($key, $fileId); } @@ -1055,7 +1055,7 @@ class Builds extends Action $deployment->setAttribute('status', 'ready'); $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment); - if ($deployment->getSequence() === $resource->getAttribute('latestDeploymentInternalId', '')) { + if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) { $resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource); } @@ -1078,14 +1078,14 @@ class Builds extends Action $oldDeploymentInternalId = $resource->getAttribute('deploymentInternalId', ''); $resource->setAttribute('deploymentId', $deployment->getId()); - $resource->setAttribute('deploymentInternalId', $deployment->getSequence()); + $resource->setAttribute('deploymentInternalId', $deployment->getInternalId()); $resource->setAttribute('deploymentCreatedAt', $deployment->getCreatedAt()); $resource = $dbForProject->updateDocument('functions', $resource->getId(), $resource); $queries = [ - Query::equal("projectInternalId", [$project->getSequence()]), + Query::equal("projectInternalId", [$project->getInternalId()]), Query::equal("type", ["deployment"]), - Query::equal("deploymentResourceInternalId", [$resource->getSequence()]), + Query::equal("deploymentResourceInternalId", [$resource->getInternalId()]), Query::equal('deploymentResourceType', ['function']), Query::equal('trigger', ['manual']), ]; @@ -1101,7 +1101,7 @@ class Builds extends Action $rulesUpdated = true; $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) - ->setAttribute('deploymentInternalId', $deployment->getSequence()); + ->setAttribute('deploymentInternalId', $deployment->getInternalId()); $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); }); break; @@ -1109,15 +1109,15 @@ class Builds extends Action $oldDeploymentInternalId = $resource->getAttribute('deploymentInternalId', ''); $resource->setAttribute('deploymentId', $deployment->getId()); - $resource->setAttribute('deploymentInternalId', $deployment->getSequence()); + $resource->setAttribute('deploymentInternalId', $deployment->getInternalId()); $resource->setAttribute('deploymentScreenshotDark', $deployment->getAttribute('screenshotDark', '')); $resource->setAttribute('deploymentScreenshotLight', $deployment->getAttribute('screenshotLight', '')); $resource->setAttribute('deploymentCreatedAt', $deployment->getCreatedAt()); $resource = $dbForProject->updateDocument('sites', $resource->getId(), $resource); $queries = [ - Query::equal("projectInternalId", [$project->getSequence()]), + Query::equal("projectInternalId", [$project->getInternalId()]), Query::equal("type", ["deployment"]), - Query::equal("deploymentResourceInternalId", [$resource->getSequence()]), + Query::equal("deploymentResourceInternalId", [$resource->getInternalId()]), Query::equal('deploymentResourceType', ['site']), Query::equal('trigger', ['manual']), ]; @@ -1131,7 +1131,7 @@ class Builds extends Action $this->listRules($project, $queries, $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) - ->setAttribute('deploymentInternalId', $deployment->getSequence()); + ->setAttribute('deploymentInternalId', $deployment->getInternalId()); $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); }); @@ -1151,15 +1151,15 @@ class Builds extends Action $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'domain' => $domain, 'type' => 'deployment', 'trigger' => 'deployment', 'deploymentId' => $deployment->getId(), - 'deploymentInternalId' => $deployment->getSequence(), + 'deploymentInternalId' => $deployment->getInternalId(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $deployment->getId(), - 'deploymentResourceInternalId' => $deployment->getSequence(), + 'deploymentResourceInternalId' => $deployment->getInternalId(), 'deploymentVcsProviderBranch' => $branchName, 'status' => 'verified', 'certificateId' => '', @@ -1171,21 +1171,21 @@ class Builds extends Action $rule = $dbForPlatform->getDocument('rules', $ruleId); $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) - ->setAttribute('deploymentInternalId', $deployment->getSequence()); + ->setAttribute('deploymentInternalId', $deployment->getInternalId()); $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); } $this->listRules($project, [ - Query::equal("projectInternalId", [$project->getSequence()]), + Query::equal("projectInternalId", [$project->getInternalId()]), Query::equal("type", ["deployment"]), - Query::equal("deploymentResourceInternalId", [$resource->getSequence()]), + Query::equal("deploymentResourceInternalId", [$resource->getInternalId()]), Query::equal('deploymentResourceType', ['site']), Query::equal("deploymentVcsProviderBranch", [$branchName]), Query::equal("trigger", ['manual']), ], $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) - ->setAttribute('deploymentInternalId', $deployment->getSequence()); + ->setAttribute('deploymentInternalId', $deployment->getInternalId()); $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); }); } @@ -1250,7 +1250,7 @@ class Builds extends Action $deployment->setAttribute('buildLogs', $message); $deployment = $dbForProject->updateDocument('deployments', $deploymentId, $deployment); - if ($deployment->getSequence() === $resource->getAttribute('latestDeploymentInternalId', '')) { + if ($deployment->getInternalId() === $resource->getAttribute('latestDeploymentInternalId', '')) { $resource = $resource->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument($resource->getCollection(), $resource->getId(), $resource); } @@ -1285,8 +1285,8 @@ class Builds extends Action ->addMetric(METRIC_BUILDS_COMPUTE_SUCCESS, (int)$deployment->getAttribute('buildDuration', 0) * 1000) ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_SUCCESS), 1) // per function ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_COMPUTE_SUCCESS), (int)$deployment->getAttribute('buildDuration', 0) * 1000) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS), 1) // per function - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_SUCCESS), (int)$deployment->getAttribute('buildDuration', 0) * 1000); + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS), 1) // per function + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_SUCCESS), (int)$deployment->getAttribute('buildDuration', 0) * 1000); break; case 'failed': $queue @@ -1294,8 +1294,8 @@ class Builds extends Action ->addMetric(METRIC_BUILDS_COMPUTE_FAILED, (int)$deployment->getAttribute('buildDuration', 0) * 1000) ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_FAILED), 1) // per function ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_COMPUTE_FAILED), (int)$deployment->getAttribute('buildDuration', 0) * 1000) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), 1) // per function - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_FAILED), (int)$deployment->getAttribute('buildDuration', 0) * 1000); + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), 1) // per function + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE_FAILED), (int)$deployment->getAttribute('buildDuration', 0) * 1000); break; } @@ -1308,10 +1308,10 @@ class Builds extends Action ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_STORAGE), $deployment->getAttribute('buildSize', 0)) ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_COMPUTE), (int)$deployment->getAttribute('buildDuration', 0) * 1000) ->addMetric(str_replace(['{resourceType}'], [$deployment->getAttribute('resourceType')], METRIC_RESOURCE_TYPE_BUILDS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $deployment->getAttribute('buildDuration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS), 1) // per function - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $deployment->getAttribute('buildSize', 0)) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE), (int)$deployment->getAttribute('buildDuration', 0) * 1000) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $deployment->getAttribute('buildDuration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS), 1) // per function + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $deployment->getAttribute('buildSize', 0)) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE), (int)$deployment->getAttribute('buildDuration', 0) * 1000) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [$deployment->getAttribute('resourceType'), $resource->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $deployment->getAttribute('buildDuration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ->setProject($project) ->trigger(); } @@ -1469,9 +1469,9 @@ class Builds extends Action }; $rule = Authorization::skip(fn () => $dbForPlatform->findOne('rules', [ - Query::equal("projectInternalId", [$project->getSequence()]), + Query::equal("projectInternalId", [$project->getInternalId()]), Query::equal("type", ["deployment"]), - Query::equal("deploymentInternalId", [$deployment->getSequence()]), + Query::equal("deploymentInternalId", [$deployment->getInternalId()]), ])); $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; @@ -1499,7 +1499,7 @@ class Builds extends Action do { $queries = \array_merge([ Query::limit($limit), - Query::equal("projectInternalId", [$project->getSequence()]) + Query::equal("projectInternalId", [$project->getInternalId()]) ], $queries); if ($cursor !== null) { diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Create.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Create.php index 54ff189c20..43f7d4ac02 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Create.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Create.php @@ -76,7 +76,7 @@ class Create extends Action Permission::update(Role::user($user->getId())), Permission::delete(Role::user($user->getId())), ], - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'projectId' => $project->getId(), 'name' => $name, 'expire' => $expire, diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Delete.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Delete.php index eac42be5f0..f6cb966f50 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Delete.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Delete.php @@ -63,7 +63,7 @@ class Delete extends Action $key = $dbForPlatform->getDocument('devKeys', $keyId); - if ($key === false || $key->isEmpty() || $key->getAttribute('projectInternalId') !== $project->getSequence()) { + if ($key === false || $key->isEmpty() || $key->getAttribute('projectInternalId') !== $project->getInternalId()) { throw new Exception(Exception::KEY_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Get.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Get.php index 6255976de4..bd472b26e7 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Get.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Get.php @@ -63,7 +63,7 @@ class Get extends Action $key = $dbForPlatform->getDocument('devKeys', $keyId); - if ($key === false || $key->isEmpty() || $key->getAttribute('projectInternalId') !== $project->getSequence()) { + if ($key === false || $key->isEmpty() || $key->getAttribute('projectInternalId') !== $project->getInternalId()) { throw new Exception(Exception::KEY_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Update.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Update.php index 33b91eb0b6..d5e6839174 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Update.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/Update.php @@ -65,7 +65,7 @@ class Update extends Action $key = $dbForPlatform->getDocument('devKeys', $keyId); - if ($key === false || $key->isEmpty() || $key->getAttribute('projectInternalId') !== $project->getSequence()) { + if ($key === false || $key->isEmpty() || $key->getAttribute('projectInternalId') !== $project->getInternalId()) { throw new Exception(Exception::KEY_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/XList.php b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/XList.php index 73e79a783a..864531d32d 100644 --- a/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/XList.php +++ b/src/Appwrite/Platform/Modules/Projects/Http/DevKeys/XList.php @@ -71,7 +71,7 @@ class XList extends Action throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $queries[] = Query::equal('projectInternalId', [$project->getSequence()]); + $queries[] = Query::equal('projectInternalId', [$project->getInternalId()]); $keys = $dbForPlatform->find('devKeys', $queries); diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php index 33eb5313a0..e4d0d2899f 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/API/Create.php @@ -153,7 +153,7 @@ class Create extends Action $rule = new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'domain' => $domain->get(), 'status' => $status, 'type' => 'api', diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php index 0b68b80aa3..6c5a87a68d 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Function/Create.php @@ -165,16 +165,16 @@ class Create extends Action $rule = new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'domain' => $domain->get(), 'status' => $status, 'type' => 'deployment', 'trigger' => 'manual', 'deploymentId' => $deployment->isEmpty() ? '' : $deployment->getId(), - 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getSequence(), + 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getInternalId(), 'deploymentResourceType' => 'function', 'deploymentResourceId' => $function->getId(), - 'deploymentResourceInternalId' => $function->getSequence(), + 'deploymentResourceInternalId' => $function->getInternalId(), 'deploymentVcsProviderBranch' => $branch, 'certificateId' => '', 'search' => implode(' ', [$ruleId, $domain->get(), $branch]), diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php index ed84b8498b..d0c9dbbbe3 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php @@ -157,7 +157,7 @@ class Create extends Action $rule = new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'domain' => $domain->get(), 'status' => $status, 'type' => 'redirect', diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php index 7c2a640cdf..894c954a32 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Site/Create.php @@ -165,16 +165,16 @@ class Create extends Action $rule = new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'domain' => $domain->get(), 'status' => $status, 'type' => 'deployment', 'trigger' => 'manual', 'deploymentId' => $deployment->isEmpty() ? '' : $deployment->getId(), - 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getSequence(), + 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getInternalId(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $site->getId(), - 'deploymentResourceInternalId' => $site->getSequence(), + 'deploymentResourceInternalId' => $site->getInternalId(), 'deploymentVcsProviderBranch' => $branch, 'certificateId' => '', 'search' => implode(' ', [$ruleId, $domain->get(), $branch]), diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php index 77d7a80f70..13b1e0c830 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php @@ -246,7 +246,7 @@ class Create extends Action Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'resourceInternalId' => $site->getSequence(), + 'resourceInternalId' => $site->getInternalId(), 'resourceId' => $site->getId(), 'resourceType' => 'sites', 'buildCommands' => \implode(' && ', $commands), @@ -263,7 +263,7 @@ class Create extends Action $site = $site ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('sites', $site->getId(), $site); @@ -278,15 +278,15 @@ class Create extends Action fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'domain' => $domain, 'type' => 'deployment', 'trigger' => 'deployment', 'deploymentId' => $deployment->isEmpty() ? '' : $deployment->getId(), - 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getSequence(), + 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getInternalId(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $site->getId(), - 'deploymentResourceInternalId' => $site->getSequence(), + 'deploymentResourceInternalId' => $site->getInternalId(), 'status' => 'verified', 'certificateId' => '', 'search' => implode(' ', [$ruleId, $domain]), @@ -312,7 +312,7 @@ class Create extends Action Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'resourceInternalId' => $site->getSequence(), + 'resourceInternalId' => $site->getInternalId(), 'resourceId' => $site->getId(), 'resourceType' => 'sites', 'buildCommands' => \implode(' && ', $commands), @@ -331,7 +331,7 @@ class Create extends Action $site = $site ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('sites', $site->getId(), $site); @@ -343,7 +343,7 @@ class Create extends Action fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'domain' => $domain, 'type' => 'deployment', 'trigger' => 'deployment', diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php index 8717d04fc2..27db10c484 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Delete.php @@ -101,7 +101,7 @@ class Delete extends Action if ($site->getAttribute('latestDeploymentId') === $deployment->getId()) { $latestDeployment = $dbForProject->findOne('deployments', [ Query::equal('resourceType', ['sites']), - Query::equal('resourceInternalId', [$site->getSequence()]), + Query::equal('resourceInternalId', [$site->getInternalId()]), Query::orderDesc('$createdAt'), ]); $site = $dbForProject->updateDocument( @@ -109,7 +109,7 @@ class Delete extends Action $site->getId(), $site ->setAttribute('latestDeploymentCreatedAt', $latestDeployment->isEmpty() ? '' : $latestDeployment->getCreatedAt()) - ->setAttribute('latestDeploymentInternalId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getSequence()) + ->setAttribute('latestDeploymentInternalId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getInternalId()) ->setAttribute('latestDeploymentId', $latestDeployment->isEmpty() ? '' : $latestDeployment->getId()) ->setAttribute('latestDeploymentStatus', $latestDeployment->isEmpty() ? '' : $latestDeployment->getAttribute('status', '')) ); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php index 739c701a2e..bff0735328 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Duplicate/Create.php @@ -110,9 +110,9 @@ class Create extends Action $commands[] = $site->getAttribute('buildCommand', ''); } - $deployment->removeAttribute('$sequence'); + $deployment->removeAttribute('$internalId'); $deployment = $dbForProject->createDocument('deployments', $deployment->setAttributes([ - '$sequence' => '', + '$internalId' => '', '$id' => $deploymentId, 'sourcePath' => $destination, 'totalSize' => $deployment->getAttribute('sourceSize', 0), @@ -134,7 +134,7 @@ class Create extends Action $site = $site ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('sites', $site->getId(), $site); @@ -150,15 +150,15 @@ class Create extends Action fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'domain' => $domain, 'type' => 'deployment', 'trigger' => 'deployment', 'deploymentId' => $deployment->isEmpty() ? '' : $deployment->getId(), - 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getSequence(), + 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getInternalId(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $site->getId(), - 'deploymentResourceInternalId' => $site->getSequence(), + 'deploymentResourceInternalId' => $site->getInternalId(), 'status' => 'verified', 'certificateId' => '', 'owner' => 'Appwrite', diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php index 046ddd1ac8..2c6da43893 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Status/Update.php @@ -95,7 +95,7 @@ class Update extends Action 'status' => 'canceled' ])); - if ($deployment->getSequence() === $site->getAttribute('latestDeploymentInternalId', '')) { + if ($deployment->getInternalId() === $site->getAttribute('latestDeploymentInternalId', '')) { $site = $site->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('sites', $site->getId(), $site); } diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php index 5de688fbf8..5b29521ce5 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Template/Create.php @@ -153,7 +153,7 @@ class Create extends Base Permission::delete(Role::any()), ], 'resourceId' => $site->getId(), - 'resourceInternalId' => $site->getSequence(), + 'resourceInternalId' => $site->getInternalId(), 'resourceType' => 'sites', 'buildCommands' => \implode(' && ', $commands), 'buildOutput' => $site->getAttribute('outputDirectory', ''), @@ -165,7 +165,7 @@ class Create extends Base $site = $site ->setAttribute('latestDeploymentId', $deployment->getId()) - ->setAttribute('latestDeploymentInternalId', $deployment->getSequence()) + ->setAttribute('latestDeploymentInternalId', $deployment->getInternalId()) ->setAttribute('latestDeploymentCreatedAt', $deployment->getCreatedAt()) ->setAttribute('latestDeploymentStatus', $deployment->getAttribute('status', '')); $dbForProject->updateDocument('sites', $site->getId(), $site); @@ -180,15 +180,15 @@ class Create extends Base fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'domain' => $domain, 'type' => 'deployment', 'trigger' => 'deployment', 'deploymentId' => $deployment->isEmpty() ? '' : $deployment->getId(), - 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getSequence(), + 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getInternalId(), 'deploymentResourceType' => 'site', 'deploymentResourceId' => $site->getId(), - 'deploymentResourceInternalId' => $site->getSequence(), + 'deploymentResourceInternalId' => $site->getInternalId(), 'status' => 'verified', 'certificateId' => '', 'owner' => 'Appwrite', diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php index 306f756d87..d7cfc1d3ad 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/XList.php @@ -79,7 +79,7 @@ class XList extends Action } // Set resource queries - $queries[] = Query::equal('resourceInternalId', [$site->getSequence()]); + $queries[] = Query::equal('resourceInternalId', [$site->getInternalId()]); $queries[] = Query::equal('resourceType', ['sites']); /** diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Logs/Delete.php b/src/Appwrite/Platform/Modules/Sites/Http/Logs/Delete.php index 2d87321086..a411cee91f 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Logs/Delete.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Logs/Delete.php @@ -71,7 +71,7 @@ class Delete extends Base throw new Exception(Exception::LOG_NOT_FOUND); } - if ($log->getAttribute('resourceType') !== 'sites' && $log->getAttribute('resourceInternalId') !== $site->getSequence()) { + if ($log->getAttribute('resourceType') !== 'sites' && $log->getAttribute('resourceInternalId') !== $site->getInternalId()) { throw new Exception(Exception::LOG_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Logs/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Logs/Get.php index 2ef7d75539..3d1ace2d20 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Logs/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Logs/Get.php @@ -63,7 +63,7 @@ class Get extends Base $log = $dbForProject->getDocument('executions', $logId); - if ($log->getAttribute('resourceType') !== 'sites' && $log->getAttribute('resourceInternalId') !== $site->getSequence()) { + if ($log->getAttribute('resourceType') !== 'sites' && $log->getAttribute('resourceInternalId') !== $site->getInternalId()) { throw new Exception(Exception::LOG_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php b/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php index 7e2c587797..a873d32603 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Logs/XList.php @@ -75,7 +75,7 @@ class XList extends Base } // Set internal queries - $queries[] = Query::equal('resourceInternalId', [$site->getSequence()]); + $queries[] = Query::equal('resourceInternalId', [$site->getInternalId()]); $queries[] = Query::equal('resourceType', ['sites']); /** diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php index 6dd1865047..c509799024 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Create.php @@ -154,7 +154,7 @@ class Create extends Base 'search' => implode(' ', [$siteId, $name, $framework]), 'fallbackFile' => $fallbackFile, 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getSequence(), + 'installationInternalId' => $installation->getInternalId(), 'providerRepositoryId' => $providerRepositoryId, 'repositoryId' => '', 'repositoryInternalId' => '', @@ -180,18 +180,18 @@ class Create extends Base Permission::delete(Role::team(ID::custom($teamId), 'developer')), ], 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getSequence(), + 'installationInternalId' => $installation->getInternalId(), 'projectId' => $project->getId(), - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'providerRepositoryId' => $providerRepositoryId, 'resourceId' => $site->getId(), - 'resourceInternalId' => $site->getSequence(), + 'resourceInternalId' => $site->getInternalId(), 'resourceType' => 'site', 'providerPullRequestIds' => [] ])); $site->setAttribute('repositoryId', $repository->getId()); - $site->setAttribute('repositoryInternalId', $repository->getSequence()); + $site->setAttribute('repositoryInternalId', $repository->getInternalId()); } $site = $dbForProject->updateDocument('sites', $site->getId(), $site); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php index 835068be88..7f1681c0f1 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -89,7 +89,7 @@ class Update extends Base $oldDeploymentInternalId = $site->getAttribute('deploymentInternalId', ''); $site = $dbForProject->updateDocument('sites', $site->getId(), new Document(array_merge($site->getArrayCopy(), [ - 'deploymentInternalId' => $deployment->getSequence(), + 'deploymentInternalId' => $deployment->getInternalId(), 'deploymentId' => $deployment->getId(), 'deploymentScreenshotDark' => $deployment->getAttribute('screenshotDark', ''), 'deploymentScreenshotLight' => $deployment->getAttribute('screenshotLight', ''), @@ -100,7 +100,7 @@ class Update extends Base Query::equal('trigger', 'manual'), Query::equal("type", ["deployment"]), Query::equal("deploymentResourceType", ["site"]), - Query::equal("deploymentResourceInternalId", [$site->getSequence()]), + Query::equal("deploymentResourceInternalId", [$site->getInternalId()]), ]; if (empty($oldDeploymentInternalId)) { @@ -112,7 +112,7 @@ class Update extends Base $this->listRules($project, $queries, $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) - ->setAttribute('deploymentInternalId', $deployment->getSequence()); + ->setAttribute('deploymentInternalId', $deployment->getInternalId()); $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); }); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php index 85f1ee8845..212b410178 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Update.php @@ -173,8 +173,8 @@ class Update extends Base // Git disconnect logic. Disconnecting only when providerRepositoryId is empty, allowing for continue updates without disconnecting git if ($isConnected && ($providerRepositoryId !== null && empty($providerRepositoryId))) { $repositories = $dbForPlatform->find('repositories', [ - Query::equal('projectInternalId', [$project->getSequence()]), - Query::equal('resourceInternalId', [$site->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('resourceInternalId', [$site->getInternalId()]), Query::equal('resourceType', ['site']), Query::limit(100), ]); @@ -206,18 +206,18 @@ class Update extends Base Permission::delete(Role::team(ID::custom($teamId), 'developer')), ], 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getSequence(), + 'installationInternalId' => $installation->getInternalId(), 'projectId' => $project->getId(), - 'projectInternalId' => $project->getSequence(), + 'projectInternalId' => $project->getInternalId(), 'providerRepositoryId' => $providerRepositoryId, 'resourceId' => $site->getId(), - 'resourceInternalId' => $site->getSequence(), + 'resourceInternalId' => $site->getInternalId(), 'resourceType' => 'site', 'providerPullRequestIds' => [] ])); $repositoryId = $repository->getId(); - $repositoryInternalId = $repository->getSequence(); + $repositoryInternalId = $repository->getInternalId(); } $live = true; @@ -256,7 +256,7 @@ class Update extends Base 'buildCommand' => $buildCommand, 'outputDirectory' => $outputDirectory, 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getSequence(), + 'installationInternalId' => $installation->getInternalId(), 'providerRepositoryId' => $providerRepositoryId, 'repositoryId' => $repositoryId, 'repositoryInternalId' => $repositoryInternalId, diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php index f8df836085..8bf19a9c28 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Usage/Get.php @@ -74,20 +74,20 @@ class Get extends Base $stats = $usage = []; $days = $periods[$range]; $metrics = [ - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS), - str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), - str_replace(['{siteInternalId}'], [$site->getSequence()], METRIC_SITES_ID_REQUESTS), - str_replace(['{siteInternalId}'], [$site->getSequence()], METRIC_SITES_ID_INBOUND), - str_replace(['{siteInternalId}'], [$site->getSequence()], METRIC_SITES_ID_OUTBOUND), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_MB_SECONDS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_SUCCESS), + str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_SITES, $site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_FAILED), + str_replace(['{siteInternalId}'], [$site->getInternalId()], METRIC_SITES_ID_REQUESTS), + str_replace(['{siteInternalId}'], [$site->getInternalId()], METRIC_SITES_ID_INBOUND), + str_replace(['{siteInternalId}'], [$site->getInternalId()], METRIC_SITES_ID_OUTBOUND), ]; diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Create.php index 88da635fe4..ff1a5c50ec 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Create.php @@ -85,7 +85,7 @@ class Create extends Base Permission::delete(Role::team(ID::custom($teamId), 'owner')), Permission::delete(Role::team(ID::custom($teamId), 'developer')), ], - 'resourceInternalId' => $site->getSequence(), + 'resourceInternalId' => $site->getInternalId(), 'resourceId' => $site->getId(), 'resourceType' => 'site', 'key' => $key, diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Delete.php b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Delete.php index ea927be367..e4594a7c3d 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Delete.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Delete.php @@ -66,7 +66,7 @@ class Delete extends Base } $variable = $dbForProject->getDocument('variables', $variableId); - if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $site->getSequence() || $variable->getAttribute('resourceType') !== 'site') { + if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $site->getInternalId() || $variable->getAttribute('resourceType') !== 'site') { throw new Exception(Exception::VARIABLE_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Get.php index 1c25f9e701..a14129d432 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Get.php @@ -68,7 +68,7 @@ class Get extends Base if ( $variable === false || $variable->isEmpty() || - $variable->getAttribute('resourceInternalId') !== $site->getSequence() || + $variable->getAttribute('resourceInternalId') !== $site->getInternalId() || $variable->getAttribute('resourceType') !== 'site' ) { throw new Exception(Exception::VARIABLE_NOT_FOUND); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Update.php index 698992f79f..cd438a0ebb 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Variables/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Variables/Update.php @@ -77,7 +77,7 @@ class Update extends Base } $variable = $dbForProject->getDocument('variables', $variableId); - if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $site->getSequence() || $variable->getAttribute('resourceType') !== 'site') { + if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $site->getInternalId() || $variable->getAttribute('resourceType') !== 'site') { throw new Exception(Exception::VARIABLE_NOT_FOUND); } diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php index bcefaf353f..565ab7bab7 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Action.php @@ -29,9 +29,9 @@ class Action extends UtopiaAction $fileSecurity = $bucket->getAttribute('fileSecurity', false); if ($fileSecurity) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); } if ($file->isEmpty()) { diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php index dc1e5232b6..fb96849ed2 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/Create.php @@ -94,7 +94,7 @@ class Create extends Action '$id' => ID::unique(), 'secret' => Auth::tokenGenerator(128), 'resourceId' => $bucketId . ':' . $fileId, - 'resourceInternalId' => $bucket->getSequence() . ':' . $file->getSequence(), + 'resourceInternalId' => $bucket->getInternalId() . ':' . $file->getInternalId(), 'resourceType' => TOKENS_RESOURCE_TYPE_FILES, 'expire' => $expire, ])); diff --git a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php index 628d9b768f..38fe10e2d9 100644 --- a/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php +++ b/src/Appwrite/Platform/Modules/Tokens/Http/Tokens/Buckets/Files/XList.php @@ -64,7 +64,7 @@ class XList extends Action $queries = Query::parseQueries($queries); $queries[] = Query::equal('resourceType', [TOKENS_RESOURCE_TYPE_FILES]); - $queries[] = Query::equal('resourceInternalId', [$bucket->getSequence() . ':' . $file->getSequence()]); + $queries[] = Query::equal('resourceInternalId', [$bucket->getInternalId() . ':' . $file->getInternalId()]); // Get cursor document if there was a cursor query $cursor = \array_filter($queries, function ($query) { return \in_array($query->getMethod(), [Query::TYPE_CURSOR_AFTER, Query::TYPE_CURSOR_BEFORE]); diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index 6d0968a804..286ffe45cb 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -124,7 +124,7 @@ abstract class ScheduleBase extends Action ); return [ - '$sequence' => $schedule->getSequence(), + '$internalId' => $schedule->getInternalId(), '$id' => $schedule->getId(), 'resourceId' => $schedule->getAttribute('resourceId'), 'schedule' => $schedule->getAttribute('schedule'), @@ -175,19 +175,19 @@ abstract class ScheduleBase extends Action $total = $total + $sum; foreach ($results as $document) { - $localDocument = $this->schedules[$document->getSequence()] ?? null; + $localDocument = $this->schedules[$document->getInternalId()] ?? null; if ($localDocument !== null) { if (!$document['active']) { Console::info("Removing: {$document['resourceType']}::{$document['resourceId']}"); - unset($this->schedules[$document->getSequence()]); + unset($this->schedules[$document->getInternalId()]); } elseif (strtotime($localDocument['resourceUpdatedAt']) !== strtotime($document['resourceUpdatedAt'])) { Console::info("Updating: {$document['resourceType']}::{$document['resourceId']}"); - $this->schedules[$document->getSequence()] = $getSchedule($document); + $this->schedules[$document->getInternalId()] = $getSchedule($document); } } else { try { - $this->schedules[$document->getSequence()] = $getSchedule($document); + $this->schedules[$document->getInternalId()] = $getSchedule($document); } catch (\Throwable $th) { $collectionId = static::getCollectionId(); Console::error("Failed to load schedule for project {$document['projectId']} {$collectionId} {$document['resourceId']}"); diff --git a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php index 27a7c1dbf1..6bf2f93afe 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php @@ -39,7 +39,7 @@ class ScheduleExecutions extends ScheduleBase $schedule['$id'], ); - unset($this->schedules[$schedule['$sequence']]); + unset($this->schedules[$schedule['$internalId']]); continue; } @@ -81,7 +81,7 @@ class ScheduleExecutions extends ScheduleBase $schedule['$id'], ); - unset($this->schedules[$schedule['$sequence']]); + unset($this->schedules[$schedule['$internalId']]); } } } diff --git a/src/Appwrite/Platform/Tasks/ScheduleMessages.php b/src/Appwrite/Platform/Tasks/ScheduleMessages.php index 4d971e1b36..5e65f7a8a6 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleMessages.php +++ b/src/Appwrite/Platform/Tasks/ScheduleMessages.php @@ -57,7 +57,7 @@ class ScheduleMessages extends ScheduleBase ); $this->recordEnqueueDelay($scheduledAt); - unset($this->schedules[$schedule['$sequence']]); + unset($this->schedules[$schedule['$internalId']]); }); } } diff --git a/src/Appwrite/Platform/Tasks/StatsResources.php b/src/Appwrite/Platform/Tasks/StatsResources.php index a0b5056b0f..ca2a6860ff 100644 --- a/src/Appwrite/Platform/Tasks/StatsResources.php +++ b/src/Appwrite/Platform/Tasks/StatsResources.php @@ -73,7 +73,7 @@ class StatsResources extends Action $queue ->setProject($project) ->trigger(); - Console::success('project: ' . $project->getId() . '(' . $project->getSequence() . ')' . ' queued'); + Console::success('project: ' . $project->getId() . '(' . $project->getInternalId() . ')' . ' queued'); }); }, $interval); diff --git a/src/Appwrite/Platform/Workers/Audits.php b/src/Appwrite/Platform/Workers/Audits.php index 19ca5181ce..76309145b8 100644 --- a/src/Appwrite/Platform/Workers/Audits.php +++ b/src/Appwrite/Platform/Workers/Audits.php @@ -91,7 +91,7 @@ class Audits extends Action // Create event data $eventData = [ - 'userId' => $user->getSequence(), + 'userId' => $user->getInternalId(), 'event' => $event, 'resource' => $resource, 'userAgent' => $userAgent, @@ -108,13 +108,13 @@ class Audits extends Action 'timestamp' => date("Y-m-d H:i:s", $message->getTimestamp()), ]; - if (isset($this->logs[$project->getSequence()])) { - $this->logs[$project->getSequence()]['logs'][] = $eventData; + if (isset($this->logs[$project->getInternalId()])) { + $this->logs[$project->getInternalId()]['logs'][] = $eventData; } else { - $this->logs[$project->getSequence()] = [ + $this->logs[$project->getInternalId()] = [ 'project' => new Document([ '$id' => $project->getId(), - '$sequence' => $project->getSequence(), + '$internalId' => $project->getInternalId(), 'database' => $project->getAttribute('database'), ]), 'logs' => [$eventData] @@ -130,7 +130,7 @@ class Audits extends Action if ($shouldProcessBatch) { try { - foreach ($this->logs as $sequence => $projectLogs) { + foreach ($this->logs as $internalId => $projectLogs) { $dbForProject = $getProjectDB($projectLogs['project']); Console::log('Processing batch with ' . count($projectLogs['logs']) . ' events'); @@ -139,7 +139,7 @@ class Audits extends Action $audit->logBatch($projectLogs['logs']); Console::success('Audit logs processed successfully'); - unset($this->logs[$sequence]); + unset($this->logs[$internalId]); } } catch (Throwable $e) { Console::error('Error processing audit logs: ' . $e->getMessage()); diff --git a/src/Appwrite/Platform/Workers/Certificates.php b/src/Appwrite/Platform/Workers/Certificates.php index a9104e0017..0dce51cb52 100644 --- a/src/Appwrite/Platform/Workers/Certificates.php +++ b/src/Appwrite/Platform/Workers/Certificates.php @@ -255,7 +255,7 @@ class Certificates extends Action $certificate = new Document(\array_merge($certificateDocument->getArrayCopy(), $certificate->getArrayCopy())); $certificate = $dbForPlatform->updateDocument('certificates', $certificate->getId(), $certificate); } else { - $certificate->removeAttribute('$sequence'); + $certificate->removeAttribute('$internalId'); $certificate = $dbForPlatform->createDocument('certificates', $certificate); } diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index 8c6f6f0252..b2691b420e 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -147,15 +147,15 @@ class Databases extends Action try { switch ($type) { case Database::VAR_RELATIONSHIP: - $relatedCollection = $dbForProject->getDocument('database_' . $database->getSequence(), $options['relatedCollection']); + $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); if ($relatedCollection->isEmpty()) { throw new DatabaseException('Collection not found'); } if ( !$dbForProject->createRelationship( - collection: 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), - relatedCollection: 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), + collection: 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + relatedCollection: 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), type: $options['relationType'], twoWay: $options['twoWay'], id: $key, @@ -167,12 +167,12 @@ class Databases extends Action } if ($options['twoWay']) { - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $options['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'available')); } break; default: - if (!$dbForProject->createAttribute('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) { + if (!$dbForProject->createAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) { throw new Exception('Failed to create Attribute'); } } @@ -207,10 +207,10 @@ class Databases extends Action $this->trigger($database, $collection, $project, $event, $queueForRealtime, $attribute); if (! $relatedCollection->isEmpty()) { - $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $relatedCollection->getId()); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); } - $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); } } @@ -257,18 +257,18 @@ class Databases extends Action try { if ($type === Database::VAR_RELATIONSHIP) { if ($options['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $database->getSequence(), $options['relatedCollection']); + $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); if ($relatedCollection->isEmpty()) { throw new DatabaseException('Collection not found'); } - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $options['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); } - if (!$dbForProject->deleteRelationship('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $key)) { + if (!$dbForProject->deleteRelationship('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'stuck')); throw new DatabaseException('Failed to delete Relationship'); } - } elseif (!$dbForProject->deleteAttribute('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $key)) { + } elseif (!$dbForProject->deleteAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { throw new DatabaseException('Failed to delete Attribute'); } @@ -365,10 +365,10 @@ class Databases extends Action } } } finally { - $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); if (! $relatedCollection->isEmpty()) { - $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $relatedCollection->getId()); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); } } } @@ -408,7 +408,7 @@ class Databases extends Action $project = $dbForPlatform->getDocument('projects', $projectId); try { - if (!$dbForProject->createIndex('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $key, $type, $attributes, $lengths, $orders)) { + if (!$dbForProject->createIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $attributes, $lengths, $orders)) { throw new DatabaseException('Failed to create Index'); } $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'available')); @@ -426,7 +426,7 @@ class Databases extends Action throw $e; } finally { $this->trigger($database, $collection, $project, $event, $queueForRealtime, null, $index); - $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); } } @@ -461,7 +461,7 @@ class Databases extends Action $project = $dbForPlatform->getDocument('projects', $projectId); try { - if ($status !== 'failed' && !$dbForProject->deleteIndex('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $key)) { + if ($status !== 'failed' && !$dbForProject->deleteIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { throw new DatabaseException('Failed to delete index'); } $dbForProject->deleteDocument('indexes', $index->getId()); @@ -482,7 +482,7 @@ class Databases extends Action } finally { $this->trigger($database, $collection, $project, $event, $queueForRealtime, null, $index); - $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collection->getId()); + $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collection->getId()); } } @@ -495,11 +495,11 @@ class Databases extends Action */ protected function deleteDatabase(Document $database, Document $project, $dbForProject): void { - $this->deleteByGroup('database_' . $database->getSequence(), [], $dbForProject, function ($collection) use ($database, $project, $dbForProject) { + $this->deleteByGroup('database_' . $database->getInternalId(), [], $dbForProject, function ($collection) use ($database, $project, $dbForProject) { $this->deleteCollection($database, $collection, $project, $dbForProject); }); - $dbForProject->deleteCollection('database_' . $database->getSequence()); + $dbForProject->deleteCollection('database_' . $database->getInternalId()); } /** @@ -522,10 +522,10 @@ class Databases extends Action } $collectionId = $collection->getId(); - $collectionInternalId = $collection->getSequence(); - $databaseInternalId = $database->getSequence(); + $collectionInternalId = $collection->getInternalId(); + $databaseInternalId = $database->getInternalId(); - $dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $collection->getSequence()); + $dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $collection->getInternalId()); /** * Related collections relating to current collection diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 8ed96c76a2..43bc55583d 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -34,7 +34,7 @@ use Utopia\System\System; class Deletes extends Action { - protected array $selects = ['$sequence', '$id', '$collection', '$permissions', '$updatedAt']; + protected array $selects = ['$internalId', '$id', '$collection', '$permissions', '$updatedAt']; public static function getName(): string { @@ -277,7 +277,7 @@ class Deletes extends Action $this->deleteByGroup( 'subscribers', [ - Query::equal('topicInternalId', [$topic->getSequence()]), + Query::equal('topicInternalId', [$topic->getInternalId()]), Query::orderAsc(), ], $getProjectDB($project) @@ -298,7 +298,7 @@ class Deletes extends Action private function deleteSessionTargets(Document $project, callable $getProjectDB, Document $session): void { - Targets::delete($getProjectDB($project), Query::equal('sessionInternalId', [$session->getSequence()])); + Targets::delete($getProjectDB($project), Query::equal('sessionInternalId', [$session->getInternalId()])); } /** @@ -434,7 +434,7 @@ class Deletes extends Action public function deleteMemberships(callable $getProjectDB, Document $document, Document $project): void { $dbForProject = $getProjectDB($project); - $teamInternalId = $document->getSequence(); + $teamInternalId = $document->getInternalId(); // Delete Memberships $this->deleteByGroup( @@ -466,7 +466,7 @@ class Deletes extends Action { $projects = $dbForPlatform->find('projects', [ - Query::equal('teamInternalId', [$document->getSequence()]), + Query::equal('teamInternalId', [$document->getInternalId()]), Query::equal('region', [System::getEnv('_APP_REGION', 'default')]) ]); @@ -497,7 +497,7 @@ class Deletes extends Action */ private function deleteProject(Database $dbForPlatform, callable $getProjectDB, Device $deviceForFiles, Device $deviceForSites, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, Document $document): void { - $projectInternalId = $document->getSequence(); + $projectInternalId = $document->getInternalId(); $projectId = $document->getId(); try { @@ -637,7 +637,7 @@ class Deletes extends Action private function deleteUser(callable $getProjectDB, Document $document, Document $project): void { $userId = $document->getId(); - $userInternalId = $document->getSequence(); + $userInternalId = $document->getInternalId(); $dbForProject = $getProjectDB($project); // Delete all sessions of this user from the sessions table and update the sessions field of the user record @@ -769,7 +769,7 @@ class Deletes extends Action { $dbForProject = $getProjectDB($project); $siteId = $document->getId(); - $siteInternalId = $document->getSequence(); + $siteInternalId = $document->getInternalId(); /** * Delete rules for site @@ -779,7 +779,7 @@ class Deletes extends Action Query::equal('type', ['deployment']), Query::equal('deploymentResourceType', ['site']), Query::equal('deploymentResourceInternalId', [$siteInternalId]), - Query::equal('projectInternalId', [$project->getSequence()]) + Query::equal('projectInternalId', [$project->getInternalId()]) ], $dbForPlatform, function (Document $document) use ($dbForPlatform, $certificates) { $this->deleteRule($dbForPlatform, $document, $certificates); }); @@ -804,7 +804,7 @@ class Deletes extends Action Query::equal('resourceType', ['site']), Query::orderAsc() ], $dbForProject, function (Document $document) use ($project, $certificates, $deviceForSites, $deviceForBuilds, $deviceForFiles, $dbForPlatform, &$deploymentInternalIds) { - $deploymentInternalIds[] = $document->getSequence(); + $deploymentInternalIds[] = $document->getInternalId(); $deploymentIds[] = $document->getId(); $this->deleteBuildFiles($deviceForBuilds, $document); $this->deleteDeploymentFiles($deviceForSites, $document); @@ -827,7 +827,7 @@ class Deletes extends Action */ Console::info("Deleting VCS repositories and comments linked to site " . $siteId); $this->deleteByGroup('repositories', [ - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), Query::equal('resourceInternalId', [$siteInternalId]), Query::equal('resourceType', ['site']), ], $dbForPlatform, function (Document $document) use ($dbForPlatform) { @@ -855,7 +855,7 @@ class Deletes extends Action $projectId = $project->getId(); $dbForProject = $getProjectDB($project); $functionId = $document->getId(); - $functionInternalId = $document->getSequence(); + $functionInternalId = $document->getInternalId(); /** * Delete rules @@ -865,7 +865,7 @@ class Deletes extends Action Query::equal('type', ['deployment']), Query::equal('deploymentResourceType', ['function']), Query::equal('deploymentResourceInternalId', [$functionInternalId]), - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), Query::orderAsc() ], $dbForPlatform, function (Document $document) use ($project, $dbForPlatform, $certificates) { $this->deleteRule($dbForPlatform, $document, $certificates); @@ -892,7 +892,7 @@ class Deletes extends Action Query::equal('resourceType', ['function']), Query::orderAsc() ], $dbForProject, function (Document $document) use ($dbForPlatform, $project, $certificates, $deviceForFunctions, $deviceForBuilds, &$deploymentInternalIds) { - $deploymentInternalIds[] = $document->getSequence(); + $deploymentInternalIds[] = $document->getInternalId(); $this->deleteDeploymentFiles($deviceForFunctions, $document); $this->deleteBuildFiles($deviceForBuilds, $document); }); @@ -913,7 +913,7 @@ class Deletes extends Action */ Console::info("Deleting VCS repositories and comments linked to function " . $functionId); $this->deleteByGroup('repositories', [ - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), Query::equal('resourceInternalId', [$functionInternalId]), Query::equal('resourceType', ['function']), Query::orderAsc() @@ -957,7 +957,7 @@ class Deletes extends Action } foreach ($screenshotIds as $id) { - $file = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('bucket_' . $bucket->getSequence(), $id)); + $file = ValidatorAuthorization::skip(fn () => $dbForPlatform->getDocument('bucket_' . $bucket->getInternalId(), $id)); if ($file->isEmpty()) { Console::error('Failed to get deployment screenshot: ' . $id); @@ -1060,7 +1060,7 @@ class Deletes extends Action $projectId = $project->getId(); $dbForProject = $getProjectDB($project); $deploymentId = $document->getId(); - $deploymentInternalId = $document->getSequence(); + $deploymentInternalId = $document->getInternalId(); /** * Delete deployment files @@ -1089,7 +1089,7 @@ class Deletes extends Action Query::equal('trigger', ['deployment']), Query::equal('type', ['deployment']), Query::equal('deploymentInternalId', [$deploymentInternalId]), - Query::equal('projectInternalId', [$project->getSequence()]) + Query::equal('projectInternalId', [$project->getInternalId()]) ], $dbForPlatform, function (Document $document) use ($dbForPlatform, $certificates) { $this->deleteRule($dbForPlatform, $document, $certificates); }); @@ -1211,7 +1211,7 @@ class Deletes extends Action { $dbForProject = $getProjectDB($project); - $dbForProject->deleteCollection('bucket_' . $document->getSequence()); + $dbForProject->deleteCollection('bucket_' . $document->getInternalId()); $deviceForFiles->deletePath($document->getId()); } @@ -1229,7 +1229,7 @@ class Deletes extends Action $dbForProject = $getProjectDB($project); $this->listByGroup('functions', [ - Query::equal('installationInternalId', [$document->getSequence()]) + Query::equal('installationInternalId', [$document->getInternalId()]) ], $dbForProject, function ($function) use ($dbForProject, $dbForPlatform) { $dbForPlatform->deleteDocument('repositories', $function->getAttribute('repositoryId')); @@ -1260,7 +1260,7 @@ class Deletes extends Action $this->listByGroup( 'deployments', [ - Query::equal('resourceInternalId', [$function->getSequence()]), + Query::equal('resourceInternalId', [$function->getInternalId()]), Query::equal('resourceType', ['functions']), ], $getProjectDB($project), diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index a9126583ce..c8c68a58ba 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -280,7 +280,7 @@ class Functions extends Action $execution = new Document([ '$id' => $executionId, '$permissions' => $user->isEmpty() ? [] : [Permission::read(Role::user($user->getId()))], - 'resourceInternalId' => $function->getSequence(), + 'resourceInternalId' => $function->getInternalId(), 'resourceId' => $function->getId(), 'resourceType' => 'functions', 'deploymentInternalId' => '', @@ -420,10 +420,10 @@ class Functions extends Action $execution = new Document([ '$id' => $executionId, '$permissions' => $user->isEmpty() ? [] : [Permission::read(Role::user($user->getId()))], - 'resourceInternalId' => $function->getSequence(), + 'resourceInternalId' => $function->getInternalId(), 'resourceId' => $function->getId(), 'resourceType' => 'functions', - 'deploymentInternalId' => $deployment->getSequence(), + 'deploymentInternalId' => $deployment->getInternalId(), 'deploymentId' => $deployment->getId(), 'trigger' => $trigger, 'status' => 'processing', @@ -572,13 +572,13 @@ class Functions extends Action ->setProject($project) ->addMetric(METRIC_EXECUTIONS, 1) ->addMetric(str_replace(['{resourceType}'], [RESOURCE_TYPE_FUNCTIONS], METRIC_RESOURCE_TYPE_EXECUTIONS), 1) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), 1) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS), 1) ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000))// per project ->addMetric(str_replace(['{resourceType}'], [RESOURCE_TYPE_FUNCTIONS], METRIC_RESOURCE_TYPE_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) ->addMetric(METRIC_EXECUTIONS_MB_SECONDS, (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ->addMetric(str_replace(['{resourceType}'], [RESOURCE_TYPE_FUNCTIONS], METRIC_RESOURCE_TYPE_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) - ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) + ->addMetric(str_replace(['{resourceType}', '{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS, $function->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_COMPUTE_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_COMPUTE_CPUS_DEFAULT))) ->trigger() ; } diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index 2ee107a319..8491e91a6c 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -373,7 +373,7 @@ class Messaging extends Action throw new \Exception('Storage bucket with the requested ID could not be found'); } - $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); if ($file->isEmpty()) { throw new \Exception('Storage file with the requested ID could not be found'); } @@ -558,7 +558,7 @@ class Messaging extends Action throw new \Exception('Storage bucket with the requested ID could not be found'); } - $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); if ($file->isEmpty()) { throw new \Exception('Storage file with the requested ID could not be found'); } diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 395ec1351e..b746365f20 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -368,7 +368,7 @@ class Migrations extends Action $this->updateMigrationDocument($migration, $projectDocument, $queueForRealtime); if ($migration->getAttribute('status', '') === 'failed') { - Console::error('Migration('.$migration->getSequence().':'.$migration->getId().') failed, Project('.$this->project->getSequence().':'.$this->project->getId().')'); + Console::error('Migration('.$migration->getInternalId().':'.$migration->getId().') failed, Project('.$this->project->getInternalId().':'.$this->project->getId().')'); if ($destination) { $destination->error(); diff --git a/src/Appwrite/Platform/Workers/StatsResources.php b/src/Appwrite/Platform/Workers/StatsResources.php index c68465f8df..19d1223d95 100644 --- a/src/Appwrite/Platform/Workers/StatsResources.php +++ b/src/Appwrite/Platform/Workers/StatsResources.php @@ -80,7 +80,7 @@ class StatsResources extends Action $this->countForProject($dbForPlatform, $getLogsDB, $getProjectDB, $project); $endTime = microtime(true); $executionTime = $endTime - $startTime; - Console::info('Project: ' . $project->getId() . '(' . $project->getSequence() . ') aggregated in ' . $executionTime .' seconds'); + Console::info('Project: ' . $project->getId() . '(' . $project->getInternalId() . ') aggregated in ' . $executionTime .' seconds'); } protected function countForProject(Database $dbForPlatform, callable $getLogsDB, callable $getProjectDB, Document $project): void @@ -105,17 +105,17 @@ class StatsResources extends Action $region = $project->getAttribute('region'); $platforms = $dbForPlatform->count('platforms', [ - Query::equal('projectInternalId', [$project->getSequence()]) + Query::equal('projectInternalId', [$project->getInternalId()]) ]); $webhooks = $dbForPlatform->count('webhooks', [ - Query::equal('projectInternalId', [$project->getSequence()]) + Query::equal('projectInternalId', [$project->getInternalId()]) ]); $keys = $dbForPlatform->count('keys', [ - Query::equal('projectInternalId', [$project->getSequence()]) + Query::equal('projectInternalId', [$project->getInternalId()]) ]); $domains = $dbForPlatform->count('rules', [ - Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('projectInternalId', [$project->getInternalId()]), Query::equal('owner', ['']), ]); @@ -216,13 +216,13 @@ class StatsResources extends Action $totalFiles = 0; $totalStorage = 0; $this->foreachDocument($dbForProject, 'buckets', [], function ($bucket) use ($dbForProject, $dbForLogs, $region, &$totalFiles, &$totalStorage) { - $files = $dbForProject->count('bucket_' . $bucket->getSequence()); + $files = $dbForProject->count('bucket_' . $bucket->getInternalId()); - $metric = str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES); + $metric = str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES); $this->createStatsDocuments($region, $metric, $files); - $storage = $dbForProject->sum('bucket_' . $bucket->getSequence(), 'sizeActual'); - $metric = str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_STORAGE); + $storage = $dbForProject->sum('bucket_' . $bucket->getInternalId(), 'sizeActual'); + $metric = str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE); $this->createStatsDocuments($region, $metric, $storage); $totalStorage += $storage; @@ -241,10 +241,10 @@ class StatsResources extends Action $totalImageTransformations = 0; $last30Days = (new \DateTime())->sub(\DateInterval::createFromDateString('30 days'))->format('Y-m-d 00:00:00'); $this->foreachDocument($dbForProject, 'buckets', [], function ($bucket) use ($dbForProject, $last30Days, $region, &$totalImageTransformations) { - $imageTransformations = $dbForProject->count('bucket_' . $bucket->getSequence(), [ + $imageTransformations = $dbForProject->count('bucket_' . $bucket->getInternalId(), [ Query::greaterThanEqual('transformedAt', $last30Days), ]); - $metric = str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED); + $metric = str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED); $this->createStatsDocuments($region, $metric, $imageTransformations); $totalImageTransformations += $imageTransformations; }); @@ -260,9 +260,9 @@ class StatsResources extends Action $totalDatabaseStorage = 0; $this->foreachDocument($dbForProject, 'databases', [], function ($database) use ($dbForProject, $region, &$totalCollections, &$totalDocuments, &$totalDatabaseStorage) { - $collections = $dbForProject->count('database_' . $database->getSequence()); + $collections = $dbForProject->count('database_' . $database->getInternalId()); - $metric = str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_COLLECTIONS); + $metric = str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS); $this->createStatsDocuments($region, $metric, $collections); [$documents, $storage] = $this->countForCollections($dbForProject, $database, $region); @@ -280,23 +280,23 @@ class StatsResources extends Action { $databaseDocuments = 0; $databaseStorage = 0; - $this->foreachDocument($dbForProject, 'database_' . $database->getSequence(), [], function ($collection) use ($dbForProject, $database, $region, &$databaseStorage, &$databaseDocuments) { - $documents = $dbForProject->count('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); - $metric = str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getSequence(), $collection->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS); + $this->foreachDocument($dbForProject, 'database_' . $database->getInternalId(), [], function ($collection) use ($dbForProject, $database, $region, &$databaseStorage, &$databaseDocuments) { + $documents = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $metric = str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS); $this->createStatsDocuments($region, $metric, $documents); $databaseDocuments += $documents; - $collectionStorage = $dbForProject->getSizeOfCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); - $metric = str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getSequence(), $collection->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE); + $collectionStorage = $dbForProject->getSizeOfCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $metric = str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE); $this->createStatsDocuments($region, $metric, $collectionStorage); $databaseStorage += $collectionStorage; }); - $metric = str_replace(['{databaseInternalId}'], [$database->getSequence()], METRIC_DATABASE_ID_DOCUMENTS); + $metric = str_replace(['{databaseInternalId}'], [$database->getInternalId()], METRIC_DATABASE_ID_DOCUMENTS); $this->createStatsDocuments($region, $metric, $databaseDocuments); - $metric = str_replace(['{databaseInternalId}'], [$database->getSequence()], METRIC_DATABASE_ID_STORAGE); + $metric = str_replace(['{databaseInternalId}'], [$database->getInternalId()], METRIC_DATABASE_ID_STORAGE); $this->createStatsDocuments($region, $metric, $databaseStorage); return [$databaseDocuments, $databaseStorage]; @@ -337,33 +337,33 @@ class StatsResources extends Action $this->foreachDocument($dbForProject, 'functions', [], function (Document $function) use ($dbForProject, $region) { $functionDeploymentsStorage = $dbForProject->sum('deployments', 'sourceSize', [ - Query::equal('resourceInternalId', [$function->getSequence()]), + Query::equal('resourceInternalId', [$function->getInternalId()]), Query::equal('resourceType', [RESOURCE_TYPE_FUNCTIONS]), ]); - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), $functionDeploymentsStorage); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), $functionDeploymentsStorage); $functionDeployments = $dbForProject->count('deployments', [ - Query::equal('resourceInternalId', [$function->getSequence()]), + Query::equal('resourceInternalId', [$function->getInternalId()]), Query::equal('resourceType', [RESOURCE_TYPE_FUNCTIONS]), ]); - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), $functionDeployments); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), $functionDeployments); /** * As deployments and builds have 1-1 relationship, * the count for one should match the other */ - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS), $functionDeployments); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS), $functionDeployments); $functionBuildsStorage = 0; $this->foreachDocument($dbForProject, 'deployments', [ - Query::equal('resourceInternalId', [$function->getSequence()]), + Query::equal('resourceInternalId', [$function->getInternalId()]), Query::equal('resourceType', [RESOURCE_TYPE_FUNCTIONS]), ], function (Document $deployment) use (&$functionBuildsStorage): void { $functionBuildsStorage += $deployment->getAttribute('buildSize', 0); }); - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $functionBuildsStorage); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $functionBuildsStorage); }); } @@ -387,29 +387,29 @@ class StatsResources extends Action $this->foreachDocument($dbForProject, 'sites', [], function (Document $site) use ($dbForProject, $region) { $siteDeploymentsStorage = $dbForProject->sum('deployments', 'sourceSize', [ - Query::equal('resourceInternalId', [$site->getSequence()]), + Query::equal('resourceInternalId', [$site->getInternalId()]), Query::equal('resourceType', [RESOURCE_TYPE_SITES]), ]); - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), $siteDeploymentsStorage); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), $siteDeploymentsStorage); $siteDeployments = $dbForProject->count('deployments', [ - Query::equal('resourceInternalId', [$site->getSequence()]), + Query::equal('resourceInternalId', [$site->getInternalId()]), Query::equal('resourceType', [RESOURCE_TYPE_SITES]), ]); - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), $siteDeployments); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), $siteDeployments); /** * As deployments and builds have 1-1 relationship, * the count for one should match the other */ - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS), $siteDeployments); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS), $siteDeployments); $siteBuildsStorage = $dbForProject->sum('deployments', 'buildSize', [ - Query::equal('resourceInternalId', [$site->getSequence()]), + Query::equal('resourceInternalId', [$site->getInternalId()]), Query::equal('resourceType', [RESOURCE_TYPE_SITES]), ]); - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $siteBuildsStorage); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_SITES,$site->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $siteBuildsStorage); }); } @@ -437,6 +437,6 @@ class StatsResources extends Action $this->documents ); $this->documents = []; - Console::success('Stats written to logs db for project: ' . $project->getId() . '(' . $project->getSequence() . ')'); + Console::success('Stats written to logs db for project: ' . $project->getId() . '(' . $project->getInternalId() . ')'); } } diff --git a/src/Appwrite/Platform/Workers/StatsUsage.php b/src/Appwrite/Platform/Workers/StatsUsage.php index 59b5a15ada..25c80fabdc 100644 --- a/src/Appwrite/Platform/Workers/StatsUsage.php +++ b/src/Appwrite/Platform/Workers/StatsUsage.php @@ -145,7 +145,7 @@ class StatsUsage extends Action $aggregationInterval = (int) System::getEnv('_APP_USAGE_AGGREGATION_INTERVAL', '20'); $project = new Document($payload['project'] ?? []); - $projectId = $project->getSequence(); + $projectId = $project->getInternalId(); foreach ($payload['reduce'] ?? [] as $document) { if (empty($document)) { continue; @@ -211,8 +211,8 @@ class StatsUsage extends Action } break; case $document->getCollection() === 'databases': // databases - $collections = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getSequence(), METRIC_DATABASE_ID_COLLECTIONS))); - $documents = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getSequence(), METRIC_DATABASE_ID_DOCUMENTS))); + $collections = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS))); + $documents = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS))); if (!empty($collections['value'])) { $metrics[] = [ 'key' => METRIC_COLLECTIONS, @@ -232,7 +232,7 @@ class StatsUsage extends Action $databaseInternalId = $parts[1] ?? 0; $documents = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace( ['{databaseInternalId}', '{collectionInternalId}'], - [$databaseInternalId, $document->getSequence()], + [$databaseInternalId, $document->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS ))); @@ -249,8 +249,8 @@ class StatsUsage extends Action break; case $document->getCollection() === 'buckets': - $files = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getSequence(), METRIC_BUCKET_ID_FILES))); - $storage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getSequence(), METRIC_BUCKET_ID_FILES_STORAGE))); + $files = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES))); + $storage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE))); if (!empty($files['value'])) { $metrics[] = [ @@ -268,13 +268,13 @@ class StatsUsage extends Action break; case $document->getCollection() === 'functions' || $document->getCollection() === 'sites': - $deployments = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS))); - $deploymentsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE))); - $builds = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS))); - $buildsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE))); - $buildsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE))); - $executions = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS))); - $executionsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getSequence()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE))); + $deployments = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS))); + $deploymentsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE))); + $builds = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS))); + $buildsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE))); + $buildsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_COMPUTE))); + $executions = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS))); + $executionsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], [$document->getCollection(), $document->getInternalId()], METRIC_RESOURCE_TYPE_ID_EXECUTIONS_COMPUTE))); if (!empty($deployments['value'])) { $metrics[] = [ @@ -357,7 +357,7 @@ class StatsUsage extends Action break; } } catch (Throwable $e) { - Console::error("[reducer] " . " {DateTime::now()} " . " {$project->getSequence()} " . " {$e->getMessage()}"); + Console::error("[reducer] " . " {DateTime::now()} " . " {$project->getInternalId()} " . " {$e->getMessage()}"); } } @@ -376,7 +376,7 @@ class StatsUsage extends Action continue; } - Console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getSequence(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); + Console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); try { foreach ($stats['keys'] ?? [] as $key => $value) { @@ -402,23 +402,23 @@ class StatsUsage extends Action ]); - $this->projects[$project->getSequence()]['project'] = new Document([ + $this->projects[$project->getInternalId()]['project'] = new Document([ '$id' => $project->getId(), - '$sequence' => $project->getSequence(), + '$internalId' => $project->getInternalId(), 'database' => $project->getAttribute('database'), ]); - $this->projects[$project->getSequence()]['stats'][] = $document; + $this->projects[$project->getInternalId()]['stats'][] = $document; $this->prepareForLogsDB($project, $document); } } } catch (Exception $e) { - Console::error('[' . DateTime::now() . '] project [' . $project->getSequence() . '] database [' . $project['database'] . '] ' . ' ' . $e->getMessage()); + Console::error('[' . DateTime::now() . '] project [' . $project->getInternalId() . '] database [' . $project['database'] . '] ' . ' ' . $e->getMessage()); } } - foreach ($this->projects as $sequence => $projectStats) { - if (empty($sequence)) { + foreach ($this->projects as $internalId => $projectStats) { + if (empty($internalId)) { continue; } try { @@ -427,7 +427,7 @@ class StatsUsage extends Action $dbForProject->createOrUpdateDocumentsWithIncrease('stats', 'value', $projectStats['stats']); Console::success('Batch successfully written to DB'); - unset($this->projects[$sequence]); + unset($this->projects[$internalId]); } catch (Throwable $e) { Console::error('Error processing stats: ' . $e->getMessage()); } @@ -451,7 +451,7 @@ class StatsUsage extends Action } } $documentClone = clone $stat; - $documentClone->setAttribute('$tenant', (int) $project->getSequence()); + $documentClone->setAttribute('$tenant', (int) $project->getInternalId()); $this->statDocuments[] = $documentClone; } diff --git a/src/Appwrite/Platform/Workers/StatsUsageDump.php b/src/Appwrite/Platform/Workers/StatsUsageDump.php index 7c2da8fd4d..77ec3f13e6 100644 --- a/src/Appwrite/Platform/Workers/StatsUsageDump.php +++ b/src/Appwrite/Platform/Workers/StatsUsageDump.php @@ -126,7 +126,7 @@ class StatsUsageDump extends Action continue; } - Console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getSequence(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); + Console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); try { /** @var Database $dbForProject */ @@ -169,7 +169,7 @@ class StatsUsageDump extends Action } } } catch (\Exception $e) { - Console::error('[' . DateTime::now() . '] project [' . $project->getSequence() . '] database [' . $project['database'] . '] ' . ' ' . $e->getMessage()); + Console::error('[' . DateTime::now() . '] project [' . $project->getInternalId() . '] database [' . $project['database'] . '] ' . ' ' . $e->getMessage()); } } } diff --git a/src/Appwrite/Platform/Workers/Webhooks.php b/src/Appwrite/Platform/Workers/Webhooks.php index 4c081aaa13..ada4d6faaa 100644 --- a/src/Appwrite/Platform/Workers/Webhooks.php +++ b/src/Appwrite/Platform/Workers/Webhooks.php @@ -176,7 +176,7 @@ class Webhooks extends Action $this->errors[] = $logs; $queueForStatsUsage ->addMetric(METRIC_WEBHOOKS_FAILED, 1) - ->addMetric(str_replace('{webhookInternalId}', $webhook->getSequence(), METRIC_WEBHOOK_ID_FAILED), 1) + ->addMetric(str_replace('{webhookInternalId}', $webhook->getInternalId(), METRIC_WEBHOOK_ID_FAILED), 1) ; @@ -186,7 +186,7 @@ class Webhooks extends Action $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $queueForStatsUsage ->addMetric(METRIC_WEBHOOKS_SENT, 1) - ->addMetric(str_replace('{webhookInternalId}', $webhook->getSequence(), METRIC_WEBHOOK_ID_SENT), 1) + ->addMetric(str_replace('{webhookInternalId}', $webhook->getInternalId(), METRIC_WEBHOOK_ID_SENT), 1) ; } diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php index 20e7d5cb93..e8eafba5a0 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php @@ -71,8 +71,8 @@ class Base extends Queries 'array' => false, ]); - $sequence = new Document([ - 'key' => '$sequence', + $internalId = new Document([ + 'key' => '$internalId', 'type' => Database::VAR_STRING, 'array' => false, ]); @@ -82,7 +82,7 @@ class Base extends Queries new Offset(), new Cursor(), new Filter($attributes, APP_DATABASE_QUERY_MAX_VALUES), - new Order([...$attributes, $sequence]), + new Order([...$attributes, $internalId]), ]; parent::__construct($validators); diff --git a/src/Appwrite/Utopia/Response/Model/Document.php b/src/Appwrite/Utopia/Response/Model/Document.php index c4f7eb3044..41a10cee89 100644 --- a/src/Appwrite/Utopia/Response/Model/Document.php +++ b/src/Appwrite/Utopia/Response/Model/Document.php @@ -71,7 +71,7 @@ class Document extends Any public function filter(DatabaseDocument $document): DatabaseDocument { - $document->removeAttribute('$sequence'); + $document->removeAttribute('$internalId'); $document->removeAttribute('$collection'); $document->removeAttribute('$tenant'); diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 9c7e19c76c..9aed3684de 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -2003,9 +2003,9 @@ trait DatabasesBase $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); $this->assertEquals(2017, $documents['body']['documents'][1]['releaseYear']); $this->assertEquals(2019, $documents['body']['documents'][2]['releaseYear']); - $this->assertFalse(array_key_exists('$sequence', $documents['body']['documents'][0])); - $this->assertFalse(array_key_exists('$sequence', $documents['body']['documents'][1])); - $this->assertFalse(array_key_exists('$sequence', $documents['body']['documents'][2])); + $this->assertFalse(array_key_exists('$internalId', $documents['body']['documents'][0])); + $this->assertFalse(array_key_exists('$internalId', $documents['body']['documents'][1])); + $this->assertFalse(array_key_exists('$internalId', $documents['body']['documents'][2])); $this->assertCount(3, $documents['body']['documents']); foreach ($documents['body']['documents'] as $document) { @@ -2098,7 +2098,7 @@ trait DatabasesBase $this->assertEquals($response['body']['releaseYear'], $document['releaseYear']); $this->assertEquals($response['body']['$permissions'], $document['$permissions']); $this->assertEquals($response['body']['birthDay'], $document['birthDay']); - $this->assertFalse(array_key_exists('$sequence', $response['body'])); + $this->assertFalse(array_key_exists('$internalId', $response['body'])); $this->assertFalse(array_key_exists('$tenant', $response['body'])); } } @@ -4361,8 +4361,8 @@ trait DatabasesBase $this->assertArrayNotHasKey('$collection', $person1['body']); $this->assertArrayNotHasKey('$collection', $person1['body']['library']); - $this->assertArrayNotHasKey('$sequence', $person1['body']); - $this->assertArrayNotHasKey('$sequence', $person1['body']['library']); + $this->assertArrayNotHasKey('$internalId', $person1['body']); + $this->assertArrayNotHasKey('$internalId', $person1['body']['library']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ 'content-type' => 'application/json', From 8ce46c791fddd83b4d965a266503c2ae27f14325 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Wed, 21 May 2025 15:16:25 -0700 Subject: [PATCH 092/219] fix(migration): set owner and region while migrating rules These attributes were added to the rules collection in 1.6.2, but the migration script was not updated to set them. Because they're empty, the 1.7 migration fails while updating rules documents because region is required. --- src/Appwrite/Migration/Version/V22.php | 34 ++++++++++++++++++++------ 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/src/Appwrite/Migration/Version/V22.php b/src/Appwrite/Migration/Version/V22.php index 50d5bdbb85..a10017c99f 100644 --- a/src/Appwrite/Migration/Version/V22.php +++ b/src/Appwrite/Migration/Version/V22.php @@ -12,6 +12,7 @@ use Utopia\Database\Exception\Conflict; use Utopia\Database\Exception\Structure; use Utopia\Database\Exception\Timeout; use Utopia\Database\Query; +use Utopia\System\System; class V22 extends Migration { @@ -324,7 +325,9 @@ class V22 extends Migration 4. Fill "trigger" with "manual" 5. Fill "deploymentResourceType". If "resourceType" is "function", set "deploymentResourceType" to "function" 6. Fill "search" with "{$id} {domain}" - 7. Fill "deploymentId" and "deploymentInternalId". If "deploymentResourceType" is "function", get project DB, and find function with ID "resourceId". Then fill rule's "deploymentId" with function's "deployment", and "deploymentId" as backup + 7. Set "region" to project region + 8. Fill "owner" with "Appwrite" if "domain" ends with "functions" or "sites" + 9. Fill "deploymentId" and "deploymentInternalId". If "deploymentResourceType" is "function", get project DB, and find function with ID "resourceId". Then fill rule's "deploymentId" with function's "deployment", and "deploymentId" as backup */ $deploymentResourceType = null; @@ -346,14 +349,29 @@ class V22 extends Migration ->setAttribute('deploymentResourceType', $document->getAttribute('deploymentResourceType', $deploymentResourceType)) ->setAttribute('search', \implode(' ', [$document->getId(), $document->getAttribute('domain', '')])); + $project = $this->dbForProject->getDocument('projects', $document->getAttribute('projectId')); + + if ($project->isEmpty()) { + Console::warning("Project \"{$document->getAttribute('projectId')}\" not found for rule \"{$document->getId()}\""); + $document->setAttribute('region', System::getEnv('_APP_DEFAULT_REGION')); + break; + } + + $document->setAttribute('region', $project->getAttribute('region', System::getEnv('_APP_DEFAULT_REGION'))); + + $domain = $document->getAttribute('domain', ''); + $functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); + $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); + $owner = $document->getAttribute('owner', ''); + if ( + empty($owner) && + (!empty($functionsDomain) && \str_ends_with($domain, $functionsDomain)) || + (!empty($sitesDomain) && \str_ends_with($domain, $sitesDomain)) + ) { + $document->setAttribute('owner', 'Appwrite'); + } + if ($deploymentResourceType === 'function') { - $project = $this->dbForProject->getDocument('projects', $document->getAttribute('projectId')); - - if ($project->isEmpty()) { - Console::warning("Project \"{$document->getAttribute('projectId')}\" not found for rule \"{$document->getId()}\""); - break; - } - $dbForOwnerProject = ($this->getProjectDB)($project); $function = $dbForOwnerProject->getDocument('functions', $resourceId); From 0ec7dcf08da747705b22f36d5ddff69b6bce665b Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Fri, 23 May 2025 15:07:45 -0700 Subject: [PATCH 093/219] Bump console to version 6.0.11 --- app/views/install/compose.phtml | 2 +- docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index f53a6f2545..d78bca7a38 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -177,7 +177,7 @@ $image = $this->getParam('image', ''); appwrite-console: <<: *x-logging container_name: appwrite-console - image: /console:6.0.8 + image: /console:6.0.11 restart: unless-stopped networks: - appwrite diff --git a/docker-compose.yml b/docker-compose.yml index 6c7900ac78..847e2fa72c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -213,7 +213,7 @@ services: appwrite-console: <<: *x-logging container_name: appwrite-console - image: appwrite/console:6.0.8 + image: appwrite/console:6.0.11 restart: unless-stopped networks: - appwrite From b932db34f3099ce3c90a1d94402601acae271030 Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Fri, 23 May 2025 15:57:49 -0700 Subject: [PATCH 094/219] Bump appwrite version to 1.7.3 --- README-CN.md | 6 +++--- README.md | 6 +++--- app/init/constants.php | 2 +- src/Appwrite/Migration/Migration.php | 1 + 4 files changed, 8 insertions(+), 7 deletions(-) diff --git a/README-CN.md b/README-CN.md index 811fe6435c..49a97aab53 100644 --- a/README-CN.md +++ b/README-CN.md @@ -72,7 +72,7 @@ docker run -it --rm \ --volume /var/run/docker.sock:/var/run/docker.sock \ --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \ --entrypoint="install" \ - appwrite/appwrite:1.7.2 + appwrite/appwrite:1.7.3 ``` ### Windows @@ -84,7 +84,7 @@ docker run -it --rm ^ --volume //var/run/docker.sock:/var/run/docker.sock ^ --volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^ --entrypoint="install" ^ - appwrite/appwrite:1.7.2 + appwrite/appwrite:1.7.3 ``` #### PowerShell @@ -94,7 +94,7 @@ docker run -it --rm ` --volume /var/run/docker.sock:/var/run/docker.sock ` --volume ${pwd}/appwrite:/usr/src/code/appwrite:rw ` --entrypoint="install" ` - appwrite/appwrite:1.7.2 + appwrite/appwrite:1.7.3 ``` 运行后,可以在浏览器上访问 http://localhost 找到 Appwrite 控制台。在非 Linux 的本机主机上完成安装后,服务器可能需要几分钟才能启动。 diff --git a/README.md b/README.md index f29be0bd61..d19d56fdd0 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ docker run -it --rm \ --volume /var/run/docker.sock:/var/run/docker.sock \ --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \ --entrypoint="install" \ - appwrite/appwrite:1.7.2 + appwrite/appwrite:1.7.3 ``` ### Windows @@ -90,7 +90,7 @@ docker run -it --rm ^ --volume //var/run/docker.sock:/var/run/docker.sock ^ --volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^ --entrypoint="install" ^ - appwrite/appwrite:1.7.2 + appwrite/appwrite:1.7.3 ``` #### PowerShell @@ -100,7 +100,7 @@ docker run -it --rm ` --volume /var/run/docker.sock:/var/run/docker.sock ` --volume ${pwd}/appwrite:/usr/src/code/appwrite:rw ` --entrypoint="install" ` - appwrite/appwrite:1.7.2 + appwrite/appwrite:1.7.3 ``` Once the Docker installation is complete, go to http://localhost to access the Appwrite console from your browser. Please note that on non-Linux native hosts, the server might take a few minutes to start after completing the installation. diff --git a/app/init/constants.php b/app/init/constants.php index f364b10d6e..e1b595a10f 100644 --- a/app/init/constants.php +++ b/app/init/constants.php @@ -38,7 +38,7 @@ const APP_RESOURCE_TOKEN_ACCESS = 24 * 60 * 60; // 24 hours const APP_FILE_ACCESS = 24 * 60 * 60; // 24 hours const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours const APP_CACHE_BUSTER = 4319; -const APP_VERSION_STABLE = '1.7.2'; +const APP_VERSION_STABLE = '1.7.3'; const APP_DATABASE_ATTRIBUTE_EMAIL = 'email'; const APP_DATABASE_ATTRIBUTE_ENUM = 'enum'; const APP_DATABASE_ATTRIBUTE_IP = 'ip'; diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 81ea1ef263..a2b1109eb3 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -87,6 +87,7 @@ abstract class Migration '1.7.0' => 'V22', '1.7.1' => 'V22', '1.7.2' => 'V22', + '1.7.3' => 'V22', ]; /** From 295e2773f33d4d13de2dde42aee24a8906c2975f Mon Sep 17 00:00:00 2001 From: Steven Nguyen Date: Fri, 23 May 2025 17:39:54 -0700 Subject: [PATCH 095/219] fix(migration): _APP_DEFAULT_REGION is not a valid env var Across the rest of the codebase, we use _APP_REGION with 'default' as the fallback value. This commit updates the migration to do the same. --- src/Appwrite/Migration/Version/V22.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Migration/Version/V22.php b/src/Appwrite/Migration/Version/V22.php index a10017c99f..2a6a64ed48 100644 --- a/src/Appwrite/Migration/Version/V22.php +++ b/src/Appwrite/Migration/Version/V22.php @@ -353,11 +353,11 @@ class V22 extends Migration if ($project->isEmpty()) { Console::warning("Project \"{$document->getAttribute('projectId')}\" not found for rule \"{$document->getId()}\""); - $document->setAttribute('region', System::getEnv('_APP_DEFAULT_REGION')); + $document->setAttribute('region', System::getEnv('_APP_REGION', 'default')); break; } - $document->setAttribute('region', $project->getAttribute('region', System::getEnv('_APP_DEFAULT_REGION'))); + $document->setAttribute('region', $project->getAttribute('region', System::getEnv('_APP_REGION', 'default'))); $domain = $document->getAttribute('domain', ''); $functionsDomain = System::getEnv('_APP_DOMAIN_FUNCTIONS', ''); From 17eab0ecb500c67d99ab0e0df7fff841d7a67566 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Sat, 24 May 2025 23:42:19 +0200 Subject: [PATCH 096/219] Upgrade to fix createDeployment chunk upload --- composer.json | 2 +- composer.lock | 47 ++++++++++++++++++++++++++++------------------- 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/composer.json b/composer.json index 7e445cd36b..d166384e3a 100644 --- a/composer.json +++ b/composer.json @@ -86,7 +86,7 @@ }, "require-dev": { "ext-fileinfo": "*", - "appwrite/sdk-generator": "0.40.*", + "appwrite/sdk-generator": "dev-fix-functions-sites-files as 0.40.99", "phpunit/phpunit": "9.*", "swoole/ide-helper": "5.1.2", "phpstan/phpstan": "1.8.*", diff --git a/composer.lock b/composer.lock index f36b815777..d4241739da 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9f5de64d73e2ef73d796fa64f2baf232", + "content-hash": "095386e258e35b6bf54f46c6b384aca7", "packages": [ { "name": "adhocore/jwt", @@ -1238,16 +1238,16 @@ }, { "name": "open-telemetry/exporter-otlp", - "version": "1.3.0", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/exporter-otlp.git", - "reference": "19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c" + "reference": "8b3ca1f86d01429c73b407bf1a2075d9c187001e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c", - "reference": "19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c", + "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/8b3ca1f86d01429c73b407bf1a2075d9c187001e", + "reference": "8b3ca1f86d01429c73b407bf1a2075d9c187001e", "shasum": "" }, "require": { @@ -1298,7 +1298,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-12T00:36:35+00:00" + "time": "2025-05-21T12:02:20+00:00" }, { "name": "open-telemetry/gen-otlp-protobuf", @@ -1365,16 +1365,16 @@ }, { "name": "open-telemetry/sdk", - "version": "1.4.0", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/sdk.git", - "reference": "939d3a28395c249a763676458140dad44b3a8011" + "reference": "cd0d7367599717fc29e04eb8838ec061e6c2c657" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/939d3a28395c249a763676458140dad44b3a8011", - "reference": "939d3a28395c249a763676458140dad44b3a8011", + "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/cd0d7367599717fc29e04eb8838ec061e6c2c657", + "reference": "cd0d7367599717fc29e04eb8838ec061e6c2c657", "shasum": "" }, "require": { @@ -1451,7 +1451,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-07T12:32:21+00:00" + "time": "2025-05-22T02:33:34+00:00" }, { "name": "open-telemetry/sem-conv", @@ -4816,16 +4816,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.40.17", + "version": "dev-fix-functions-sites-files", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de" + "reference": "d831f172056e412158d4c950128e015daf9c11c6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de", - "reference": "7e333c1003bfd4763e4d6f3a0a799fde5e7bc4de", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/d831f172056e412158d4c950128e015daf9c11c6", + "reference": "d831f172056e412158d4c950128e015daf9c11c6", "shasum": "" }, "require": { @@ -4861,9 +4861,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.40.17" + "source": "https://github.com/appwrite/sdk-generator/tree/fix-functions-sites-files" }, - "time": "2025-05-16T15:10:54+00:00" + "time": "2025-05-24T21:40:27+00:00" }, { "name": "doctrine/annotations", @@ -8240,9 +8240,18 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "appwrite/sdk-generator", + "version": "dev-fix-functions-sites-files", + "alias": "0.40.99", + "alias_normalized": "0.40.99.0" + } + ], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": { + "appwrite/sdk-generator": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { From eb8da87eedd66826b5e2c859cf98acd91ad873f6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Sat, 24 May 2025 23:47:27 +0200 Subject: [PATCH 097/219] Fix bug; trigger sdk generation --- app/config/specs/open-api3-latest-client.json | 25 ++++++++++++++- .../specs/open-api3-latest-console.json | 31 ++++++++++++++++++- app/config/specs/open-api3-latest-server.json | 31 ++++++++++++++++++- app/config/specs/swagger2-latest-client.json | 25 ++++++++++++++- app/config/specs/swagger2-latest-console.json | 31 ++++++++++++++++++- app/config/specs/swagger2-latest-server.json | 31 ++++++++++++++++++- composer.lock | 8 ++--- 7 files changed, 172 insertions(+), 10 deletions(-) diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index abeab8a56f..e87a892063 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.7.0", + "version": "1.7.3", "title": "Appwrite", "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -4490,6 +4490,29 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/components\/schemas\/documentList" + } + ], + "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 19ce78915c..ad500a8811 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.7.0", + "version": "1.7.3", "title": "Appwrite", "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -8049,6 +8049,29 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/components\/schemas\/documentList" + } + ], + "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -36564,6 +36587,12 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "default", "nullable": true + }, + "encrypt": { + "type": "boolean", + "description": "Defines whether this attribute is encrypted or not.", + "x-example": false, + "nullable": true } }, "required": [ diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index db615d642c..8ac05cb97b 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.7.0", + "version": "1.7.3", "title": "Appwrite", "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -7530,6 +7530,29 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/components\/schemas\/documentList" + } + ], + "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -26532,6 +26555,12 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "default", "nullable": true + }, + "encrypt": { + "type": "boolean", + "description": "Defines whether this attribute is encrypted or not.", + "x-example": false, + "nullable": true } }, "required": [ diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index 5c1b764e1e..972b4a34da 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.7.0", + "version": "1.7.3", "title": "Appwrite", "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -4636,6 +4636,29 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/definitions\/documentList" + } + ], + "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 96705f3e61..a52f09d691 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.7.0", + "version": "1.7.3", "title": "Appwrite", "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -8178,6 +8178,29 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/definitions\/documentList" + } + ], + "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -36793,6 +36816,12 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "default", "x-nullable": true + }, + "encrypt": { + "type": "boolean", + "description": "Defines whether this attribute is encrypted or not.", + "x-example": false, + "x-nullable": true } }, "required": [ diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index c033008417..a37c972aae 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.7.0", + "version": "1.7.3", "title": "Appwrite", "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -7649,6 +7649,29 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/definitions\/documentList" + } + ], + "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -26828,6 +26851,12 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "default", "x-nullable": true + }, + "encrypt": { + "type": "boolean", + "description": "Defines whether this attribute is encrypted or not.", + "x-example": false, + "x-nullable": true } }, "required": [ diff --git a/composer.lock b/composer.lock index d4241739da..d2c689437c 100644 --- a/composer.lock +++ b/composer.lock @@ -4820,12 +4820,12 @@ "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "d831f172056e412158d4c950128e015daf9c11c6" + "reference": "1579aa907eced019d2d4236e141081a83d3394e1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/d831f172056e412158d4c950128e015daf9c11c6", - "reference": "d831f172056e412158d4c950128e015daf9c11c6", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/1579aa907eced019d2d4236e141081a83d3394e1", + "reference": "1579aa907eced019d2d4236e141081a83d3394e1", "shasum": "" }, "require": { @@ -4863,7 +4863,7 @@ "issues": "https://github.com/appwrite/sdk-generator/issues", "source": "https://github.com/appwrite/sdk-generator/tree/fix-functions-sites-files" }, - "time": "2025-05-24T21:40:27+00:00" + "time": "2025-05-24T21:46:46+00:00" }, { "name": "doctrine/annotations", From aa9f554853519d99ecc4f1a983265ce3c3c20044 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Sun, 25 May 2025 00:05:30 +0200 Subject: [PATCH 098/219] Fix chunk uploaded manual deployment --- .../Platform/Modules/Sites/Http/Deployments/Create.php | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php index 13b1e0c830..d78d43aec7 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Create.php @@ -347,10 +347,16 @@ class Create extends Action 'domain' => $domain, 'type' => 'deployment', 'trigger' => 'deployment', - 'value' => $deployment->getId(), + 'deploymentId' => $deployment->isEmpty() ? '' : $deployment->getId(), + 'deploymentInternalId' => $deployment->isEmpty() ? '' : $deployment->getInternalId(), + 'deploymentResourceType' => 'site', + 'deploymentResourceId' => $site->getId(), + 'deploymentResourceInternalId' => $site->getInternalId(), 'status' => 'verified', 'certificateId' => '', 'search' => implode(' ', [$ruleId, $domain]), + 'owner' => 'Appwrite', + 'region' => $project->getAttribute('region') ])) ); } else { From d3533840c8889561f0cedb301676229110ce580e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Sun, 25 May 2025 00:50:51 +0200 Subject: [PATCH 099/219] Chore: Use release, not branch --- composer.json | 2 +- composer.lock | 27 +++++++++------------------ 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/composer.json b/composer.json index d166384e3a..7e445cd36b 100644 --- a/composer.json +++ b/composer.json @@ -86,7 +86,7 @@ }, "require-dev": { "ext-fileinfo": "*", - "appwrite/sdk-generator": "dev-fix-functions-sites-files as 0.40.99", + "appwrite/sdk-generator": "0.40.*", "phpunit/phpunit": "9.*", "swoole/ide-helper": "5.1.2", "phpstan/phpstan": "1.8.*", diff --git a/composer.lock b/composer.lock index d2c689437c..ef067116d0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "095386e258e35b6bf54f46c6b384aca7", + "content-hash": "9f5de64d73e2ef73d796fa64f2baf232", "packages": [ { "name": "adhocore/jwt", @@ -4816,16 +4816,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "dev-fix-functions-sites-files", + "version": "0.40.19", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "1579aa907eced019d2d4236e141081a83d3394e1" + "reference": "05b53cf30c59fe5934d57207fefbc8ae8feb5dbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/1579aa907eced019d2d4236e141081a83d3394e1", - "reference": "1579aa907eced019d2d4236e141081a83d3394e1", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/05b53cf30c59fe5934d57207fefbc8ae8feb5dbf", + "reference": "05b53cf30c59fe5934d57207fefbc8ae8feb5dbf", "shasum": "" }, "require": { @@ -4861,9 +4861,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/fix-functions-sites-files" + "source": "https://github.com/appwrite/sdk-generator/tree/0.40.19" }, - "time": "2025-05-24T21:46:46+00:00" + "time": "2025-05-24T22:49:50+00:00" }, { "name": "doctrine/annotations", @@ -8240,18 +8240,9 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [ - { - "package": "appwrite/sdk-generator", - "version": "dev-fix-functions-sites-files", - "alias": "0.40.99", - "alias_normalized": "0.40.99.0" - } - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "appwrite/sdk-generator": 20 - }, + "stability-flags": [], "prefer-stable": false, "prefer-lowest": false, "platform": { From 24e0b3e8cb5fdf9ee6ea1e258c6431f0adc4c509 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 25 May 2025 12:19:52 +0530 Subject: [PATCH 100/219] fix: missing project check. --- app/controllers/api/teams.php | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 9c383803f2..cc930eca90 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -1314,10 +1314,11 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') )) ->param('teamId', '', new UID(), 'Team ID.') ->param('membershipId', '', new UID(), 'Membership ID.') + ->inject('project') ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $teamId, string $membershipId, Response $response, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $teamId, string $membershipId, Document $project, Response $response, Database $dbForProject, Event $queueForEvents) { $membership = $dbForProject->getDocument('memberships', $membershipId); @@ -1341,6 +1342,27 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH); } + if ($project->getId() === 'console') { + // Quick check: + // fetch up to 2 owners to determine if only one exists + $ownersCount = $dbForProject->count( + collection: 'memberships', + queries: [ + Query::contains('roles', ['owner']), + Query::equal('teamInternalId', [$team->getInternalId()]) + ], + max: 2 + ); + + if ($ownersCount === 1) { + /* Prevent removal if the user is the only owner. */ + throw new Exception( + Exception::GENERAL_ARGUMENT_INVALID, + 'There must be at least one owner in the organization.' + ); + } + } + try { $dbForProject->deleteDocument('memberships', $membership->getId()); } catch (AuthorizationException $exception) { From 3f839e380788e901c20336784e01c3183dc33ea2 Mon Sep 17 00:00:00 2001 From: Darshan Date: Sun, 25 May 2025 12:27:29 +0530 Subject: [PATCH 101/219] update: tests to account for console and custom client projects. --- tests/e2e/Services/Teams/TeamsBaseClient.php | 79 ++++++++++++++++--- .../Services/Teams/TeamsConsoleClientTest.php | 4 +- 2 files changed, 69 insertions(+), 14 deletions(-) diff --git a/tests/e2e/Services/Teams/TeamsBaseClient.php b/tests/e2e/Services/Teams/TeamsBaseClient.php index 3fcd9c043d..2aacf4abc1 100644 --- a/tests/e2e/Services/Teams/TeamsBaseClient.php +++ b/tests/e2e/Services/Teams/TeamsBaseClient.php @@ -10,6 +10,17 @@ use Utopia\Database\Validator\Datetime as DatetimeValidator; trait TeamsBaseClient { + /** + * Checks if the current project is the Console project. + * + * This is necessary because the last admin of an org + * cannot be removed, which affects certain test conditions. + */ + private function isConsoleProject(): bool + { + return $this->getProject()['$id'] === 'console'; + } + /** * @depends testCreateTeam */ @@ -60,7 +71,11 @@ trait TeamsBaseClient ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertCount(0, $response['body']['memberships']); + if ($this->isConsoleProject()) { + $this->assertCount(1, $response['body']['memberships']); + } else { + $this->assertCount(0, $response['body']['memberships']); + } $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', @@ -84,7 +99,11 @@ trait TeamsBaseClient ]); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertCount(0, $response['body']['memberships']); + if ($this->isConsoleProject()) { + $this->assertCount(1, $response['body']['memberships']); + } else { + $this->assertCount(0, $response['body']['memberships']); + } $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', @@ -373,7 +392,11 @@ trait TeamsBaseClient $this->assertEquals(200, $memberships['headers']['status-code']); $this->assertIsInt($memberships['body']['total']); $this->assertNotEmpty($memberships['body']['memberships']); - $this->assertCount(3, $memberships['body']['memberships']); + if ($this->isConsoleProject()) { + $this->assertCount(4, $memberships['body']['memberships']); + } else { + $this->assertCount(3, $memberships['body']['memberships']); + } $response = $this->client->call(Client::METHOD_GET, '/teams/' . $data['teamUid'] . '/memberships', array_merge([ 'content-type' => 'application/json', @@ -387,7 +410,11 @@ trait TeamsBaseClient $this->assertEquals(200, $response['headers']['status-code']); $this->assertIsInt($response['body']['total']); $this->assertNotEmpty($response['body']['memberships']); - $this->assertCount(2, $response['body']['memberships']); + if ($this->isConsoleProject()) { + $this->assertCount(3, $response['body']['memberships']); + } else { + $this->assertCount(2, $response['body']['memberships']); + } $this->assertEquals($memberships['body']['memberships'][1]['$id'], $response['body']['memberships'][0]['$id']); } @@ -724,7 +751,11 @@ trait TeamsBaseClient ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(4, $response['body']['total']); + if ($this->isConsoleProject()) { + $this->assertCount(5, $response['body']['memberships']); + } else { + $this->assertCount(4, $response['body']['memberships']); + } $ownerMembershipUid = $response['body']['memberships'][0]['$id']; @@ -754,14 +785,18 @@ trait TeamsBaseClient 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]); - $this->assertEquals(401, $response['headers']['status-code']); + if ($this->isConsoleProject()) { + $this->assertEquals(400, $response['headers']['status-code']); + } else { + $this->assertEquals(401, $response['headers']['status-code']); + } /** * Test for SUCCESS */ /** - * Test for when a user other than the owner tries to delete their membership + * Test for when a user other than the owner tries to delete an owner's membership. */ $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/' . $membershipUid, [ 'origin' => 'http://localhost', @@ -770,8 +805,13 @@ trait TeamsBaseClient 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]); - $this->assertEquals(204, $response['headers']['status-code']); - $this->assertEmpty($response['body']); + if ($this->isConsoleProject()) { + $this->assertEquals(400, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']); + } else { + $this->assertEquals(204, $response['headers']['status-code']); + $this->assertEmpty($response['body']); + } $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', @@ -779,7 +819,11 @@ trait TeamsBaseClient ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(3, $response['body']['total']); + if ($this->isConsoleProject()) { + $this->assertEquals(5, $response['body']['total']); + } else { + $this->assertEquals(3, $response['body']['total']); + } /** * Test for when the owner tries to delete their membership @@ -790,8 +834,13 @@ trait TeamsBaseClient 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(204, $response['headers']['status-code']); - $this->assertEmpty($response['body']); + if ($this->isConsoleProject()) { + $this->assertEquals(400, $response['headers']['status-code']); + $this->assertNotEmpty($response['body']); + } else { + $this->assertEquals(204, $response['headers']['status-code']); + $this->assertEmpty($response['body']); + } $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $ownerMembershipUid, array_merge([ 'origin' => 'http://localhost', @@ -799,7 +848,11 @@ trait TeamsBaseClient 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(404, $response['headers']['status-code']); + if ($this->isConsoleProject()) { + $this->assertEquals(200, $response['headers']['status-code']); + } else { + $this->assertEquals(404, $response['headers']['status-code']); + } return []; } diff --git a/tests/e2e/Services/Teams/TeamsConsoleClientTest.php b/tests/e2e/Services/Teams/TeamsConsoleClientTest.php index 06358765f6..3798019884 100644 --- a/tests/e2e/Services/Teams/TeamsConsoleClientTest.php +++ b/tests/e2e/Services/Teams/TeamsConsoleClientTest.php @@ -73,7 +73,9 @@ class TeamsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - $this->assertEquals(204, $response['headers']['status-code']); + + $this->assertEquals(400, $response['headers']['status-code']); + $this->assertEquals('There must be at least one owner in the organization.', $response['body']['message']); return $data; } From ddf5b8e15665d505adbbeed8e4b0ec317b3f63d7 Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Sun, 25 May 2025 19:39:06 +0200 Subject: [PATCH 102/219] Update console image to version 6.0.13 --- app/views/install/compose.phtml | 2 +- docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index d78bca7a38..7a25898647 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -177,7 +177,7 @@ $image = $this->getParam('image', ''); appwrite-console: <<: *x-logging container_name: appwrite-console - image: /console:6.0.11 + image: /console:6.0.13 restart: unless-stopped networks: - appwrite diff --git a/docker-compose.yml b/docker-compose.yml index 847e2fa72c..18dc0aa7b7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -213,7 +213,7 @@ services: appwrite-console: <<: *x-logging container_name: appwrite-console - image: appwrite/console:6.0.11 + image: appwrite/console:6.0.13 restart: unless-stopped networks: - appwrite From 7531c64b31ce6c5a1a9bed4e2d8fd112b624730f Mon Sep 17 00:00:00 2001 From: Torsten Dittmann Date: Sun, 25 May 2025 19:44:51 +0200 Subject: [PATCH 103/219] Update version from 1.7.3 to 1.7.4 --- README-CN.md | 6 +++--- README.md | 6 +++--- app/init/constants.php | 4 ++-- src/Appwrite/Migration/Migration.php | 1 + 4 files changed, 9 insertions(+), 8 deletions(-) diff --git a/README-CN.md b/README-CN.md index 49a97aab53..a9a6b3c867 100644 --- a/README-CN.md +++ b/README-CN.md @@ -72,7 +72,7 @@ docker run -it --rm \ --volume /var/run/docker.sock:/var/run/docker.sock \ --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \ --entrypoint="install" \ - appwrite/appwrite:1.7.3 + appwrite/appwrite:1.7.4 ``` ### Windows @@ -84,7 +84,7 @@ docker run -it --rm ^ --volume //var/run/docker.sock:/var/run/docker.sock ^ --volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^ --entrypoint="install" ^ - appwrite/appwrite:1.7.3 + appwrite/appwrite:1.7.4 ``` #### PowerShell @@ -94,7 +94,7 @@ docker run -it --rm ` --volume /var/run/docker.sock:/var/run/docker.sock ` --volume ${pwd}/appwrite:/usr/src/code/appwrite:rw ` --entrypoint="install" ` - appwrite/appwrite:1.7.3 + appwrite/appwrite:1.7.4 ``` 运行后,可以在浏览器上访问 http://localhost 找到 Appwrite 控制台。在非 Linux 的本机主机上完成安装后,服务器可能需要几分钟才能启动。 diff --git a/README.md b/README.md index d19d56fdd0..88d3fe89df 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,7 @@ docker run -it --rm \ --volume /var/run/docker.sock:/var/run/docker.sock \ --volume "$(pwd)"/appwrite:/usr/src/code/appwrite:rw \ --entrypoint="install" \ - appwrite/appwrite:1.7.3 + appwrite/appwrite:1.7.4 ``` ### Windows @@ -90,7 +90,7 @@ docker run -it --rm ^ --volume //var/run/docker.sock:/var/run/docker.sock ^ --volume "%cd%"/appwrite:/usr/src/code/appwrite:rw ^ --entrypoint="install" ^ - appwrite/appwrite:1.7.3 + appwrite/appwrite:1.7.4 ``` #### PowerShell @@ -100,7 +100,7 @@ docker run -it --rm ` --volume /var/run/docker.sock:/var/run/docker.sock ` --volume ${pwd}/appwrite:/usr/src/code/appwrite:rw ` --entrypoint="install" ` - appwrite/appwrite:1.7.3 + appwrite/appwrite:1.7.4 ``` Once the Docker installation is complete, go to http://localhost to access the Appwrite console from your browser. Please note that on non-Linux native hosts, the server might take a few minutes to start after completing the installation. diff --git a/app/init/constants.php b/app/init/constants.php index e1b595a10f..ebf79086a7 100644 --- a/app/init/constants.php +++ b/app/init/constants.php @@ -37,8 +37,8 @@ const APP_PROJECT_ACCESS = 24 * 60 * 60; // 24 hours const APP_RESOURCE_TOKEN_ACCESS = 24 * 60 * 60; // 24 hours const APP_FILE_ACCESS = 24 * 60 * 60; // 24 hours const APP_CACHE_UPDATE = 24 * 60 * 60; // 24 hours -const APP_CACHE_BUSTER = 4319; -const APP_VERSION_STABLE = '1.7.3'; +const APP_CACHE_BUSTER = 4320; +const APP_VERSION_STABLE = '1.7.4'; const APP_DATABASE_ATTRIBUTE_EMAIL = 'email'; const APP_DATABASE_ATTRIBUTE_ENUM = 'enum'; const APP_DATABASE_ATTRIBUTE_IP = 'ip'; diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index a2b1109eb3..26b0a0301f 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -88,6 +88,7 @@ abstract class Migration '1.7.1' => 'V22', '1.7.2' => 'V22', '1.7.3' => 'V22', + '1.7.4' => 'V22', ]; /** From 9bb52cda93a8123380fefde69ac8a4001fac08f8 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Mon, 26 May 2025 04:32:10 +0000 Subject: [PATCH 104/219] chore: update flutter sdk and changelog --- app/config/platforms.php | 2 +- composer.lock | 74 +++++++++++++++++----------------- docs/sdks/flutter/CHANGELOG.md | 4 +- 3 files changed, 41 insertions(+), 39 deletions(-) diff --git a/app/config/platforms.php b/app/config/platforms.php index 4ebb049633..4e705516fa 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -59,7 +59,7 @@ return [ [ 'key' => 'flutter', 'name' => 'Flutter', - 'version' => '16.1.0', + 'version' => '17.0.0', 'url' => 'https://github.com/appwrite/sdk-for-flutter', 'package' => 'https://pub.dev/packages/appwrite', 'enabled' => true, diff --git a/composer.lock b/composer.lock index 9ba4927742..875f012fc9 100644 --- a/composer.lock +++ b/composer.lock @@ -1238,16 +1238,16 @@ }, { "name": "open-telemetry/exporter-otlp", - "version": "1.3.0", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/exporter-otlp.git", - "reference": "19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c" + "reference": "8b3ca1f86d01429c73b407bf1a2075d9c187001e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c", - "reference": "19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c", + "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/8b3ca1f86d01429c73b407bf1a2075d9c187001e", + "reference": "8b3ca1f86d01429c73b407bf1a2075d9c187001e", "shasum": "" }, "require": { @@ -1298,7 +1298,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-12T00:36:35+00:00" + "time": "2025-05-21T12:02:20+00:00" }, { "name": "open-telemetry/gen-otlp-protobuf", @@ -1365,16 +1365,16 @@ }, { "name": "open-telemetry/sdk", - "version": "1.4.0", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/sdk.git", - "reference": "939d3a28395c249a763676458140dad44b3a8011" + "reference": "cd0d7367599717fc29e04eb8838ec061e6c2c657" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/939d3a28395c249a763676458140dad44b3a8011", - "reference": "939d3a28395c249a763676458140dad44b3a8011", + "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/cd0d7367599717fc29e04eb8838ec061e6c2c657", + "reference": "cd0d7367599717fc29e04eb8838ec061e6c2c657", "shasum": "" }, "require": { @@ -1451,7 +1451,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-07T12:32:21+00:00" + "time": "2025-05-22T02:33:34+00:00" }, { "name": "open-telemetry/sem-conv", @@ -2486,16 +2486,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { @@ -2508,7 +2508,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -2533,7 +2533,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" }, "funding": [ { @@ -2549,7 +2549,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/http-client", @@ -2648,16 +2648,16 @@ }, { "name": "symfony/http-client-contracts", - "version": "v3.5.2", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645" + "reference": "75d7043853a42837e68111812f4d964b01e5101c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/ee8d807ab20fcb51267fdace50fbe3494c31e645", - "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/75d7043853a42837e68111812f4d964b01e5101c", + "reference": "75d7043853a42837e68111812f4d964b01e5101c", "shasum": "" }, "require": { @@ -2670,7 +2670,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -2706,7 +2706,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.2" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.6.0" }, "funding": [ { @@ -2722,7 +2722,7 @@ "type": "tidelift" } ], - "time": "2024-12-07T08:49:48+00:00" + "time": "2025-04-29T11:18:49+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -2883,16 +2883,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", "shasum": "" }, "require": { @@ -2910,7 +2910,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -2946,7 +2946,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" }, "funding": [ { @@ -2962,7 +2962,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2025-04-25T09:37:31+00:00" }, { "name": "tbachert/spi", @@ -4816,16 +4816,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.40.18", + "version": "0.40.19", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "38de4b9c58112d7e83eb75955994c8412a401093" + "reference": "05b53cf30c59fe5934d57207fefbc8ae8feb5dbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/38de4b9c58112d7e83eb75955994c8412a401093", - "reference": "38de4b9c58112d7e83eb75955994c8412a401093", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/05b53cf30c59fe5934d57207fefbc8ae8feb5dbf", + "reference": "05b53cf30c59fe5934d57207fefbc8ae8feb5dbf", "shasum": "" }, "require": { @@ -4861,9 +4861,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.40.18" + "source": "https://github.com/appwrite/sdk-generator/tree/0.40.19" }, - "time": "2025-05-21T14:14:47+00:00" + "time": "2025-05-24T22:49:50+00:00" }, { "name": "doctrine/annotations", diff --git a/docs/sdks/flutter/CHANGELOG.md b/docs/sdks/flutter/CHANGELOG.md index f707c645e6..1a9b8c2e29 100644 --- a/docs/sdks/flutter/CHANGELOG.md +++ b/docs/sdks/flutter/CHANGELOG.md @@ -1,9 +1,11 @@ # Change Log -## 16.1.1 +## 17.0.0 * Update `flutter_web_auth_2` dependency to version 4.1.0 * Update `auth.html` example in README.md to align with `flutter_web_auth_2` documentation +* Breaking changes: + * Minimum iOS version supported is now 17.4 due to the updated requirements of `flutter_web_auth_2` version 4.1.0 ## 16.1.0 From a616aa0e93d80e67b9caf2704872357b59ee0f29 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 26 May 2025 17:36:55 +1200 Subject: [PATCH 105/219] Revert "Merge pull request #9877 from appwrite/revert-9871-feat-sync" This reverts commit 1a0e82b4e419e7d84e986664bde9405cbd675770, reversing changes made to 8bc51172594889c29b6f7cf35404953561beba97. --- app/controllers/api/databases.php | 19 +++++++++--- app/init/database/filters.php | 21 ++++++++++---- .../Utopia/Response/Model/AttributeString.php | 7 +++++ .../e2e/Services/Databases/DatabasesBase.php | 2 +- .../Databases/DatabasesCustomServerTest.php | 29 +++++++++++++++++-- 5 files changed, 65 insertions(+), 13 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 68d8891067..54a4c565f4 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1347,7 +1347,11 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { + ->inject('plan') + ->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, array $plan) { + if ($encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) { + throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string attributes are not available on your plan. Please upgrade to create encrypted string attributes.'); + } // Ensure attribute default is within required size $validator = new Text($size, 0); if (!is_null($default) && !$validator->isValid($default)) { @@ -1368,7 +1372,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string 'array' => $array, 'filters' => $filters, ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - + $attribute->setAttribute('encrypt', $encrypt); $response ->setStatusCode(Response::STATUS_CODE_ACCEPTED) ->dynamic($attribute, Response::MODEL_ATTRIBUTE_STRING); @@ -2047,6 +2051,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') throw new Exception(Exception::GENERAL_QUERY_INVALID); } + foreach ($attributes as $attribute) { + if ($attribute->getAttribute('type') === Database::VAR_STRING) { + $filters = $attribute->getAttribute('filters', []); + $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); + } + } + $response->dynamic(new Document([ 'attributes' => $attributes, 'total' => $total, @@ -2111,7 +2122,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') $type = $attribute->getAttribute('type'); $format = $attribute->getAttribute('format'); $options = $attribute->getAttribute('options', []); - + $filters = $attribute->getAttribute('filters', []); foreach ($options as $key => $option) { $attribute->setAttribute($key, $option); } @@ -2131,7 +2142,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') }, default => Response::MODEL_ATTRIBUTE, }; - + $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); $response->dynamic($attribute, $model); }); diff --git a/app/init/database/filters.php b/app/init/database/filters.php index 8223b1c677..49d7845699 100644 --- a/app/init/database/filters.php +++ b/app/init/database/filters.php @@ -77,12 +77,21 @@ Database::addFilter( ]); foreach ($attributes as $attribute) { - if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { - $options = $attribute->getAttribute('options'); - foreach ($options as $key => $value) { - $attribute->setAttribute($key, $value); - } - $attribute->removeAttribute('options'); + $attributeType = $attribute->getAttribute('type'); + + switch ($attributeType) { + case Database::VAR_RELATIONSHIP: + $options = $attribute->getAttribute('options'); + foreach ($options as $key => $value) { + $attribute->setAttribute($key, $value); + } + $attribute->removeAttribute('options'); + break; + + case Database::VAR_STRING: + $filters = $attribute->getAttribute('filters', []); + $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); + break; } } diff --git a/src/Appwrite/Utopia/Response/Model/AttributeString.php b/src/Appwrite/Utopia/Response/Model/AttributeString.php index 12bb42009d..fded48fddc 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeString.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeString.php @@ -24,6 +24,13 @@ class AttributeString extends Attribute 'required' => false, 'example' => 'default', ]) + ->addRule('encrypt', [ + 'type' => self::TYPE_BOOLEAN, + 'description' => 'Defines whether this attribute is encrypted or not.', + 'default' => false, + 'required' => false, + 'example' => false, + ]) ; } diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 7c0060ecaa..9aed3684de 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -298,7 +298,7 @@ trait DatabasesBase $this->assertEquals($title['body']['type'], 'string'); $this->assertEquals($title['body']['size'], 256); $this->assertEquals($title['body']['required'], true); - + $this->assertFalse($title['body']['encrypt']); $this->assertEquals(202, $description['headers']['status-code']); $this->assertEquals($description['body']['key'], 'description'); $this->assertEquals($description['body']['type'], 'string'); diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 829960b54f..c0d8763aa7 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -695,9 +695,16 @@ class DatabasesCustomServerTest extends Scope 'key' => 'lastName', 'size' => 256, 'required' => true, - 'encrypt' => true, + 'encrypt' => true ]); - + $this->assertTrue($lastName['body']['encrypt']); + sleep(1); + $response = $this->client->call(Client::METHOD_GET, $attributesPath . '/lastName', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'], + ])); + $this->assertTrue($response['body']['encrypt']); /** * Check status of every attribute @@ -741,6 +748,24 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $document['headers']['status-code']); $this->assertEquals('Jonah', $document['body']['firstName']); $this->assertEquals('Jameson', $document['body']['lastName']); + + + $actors = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'], array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), []); + $attributes = $actors['body']['attributes']; + foreach ($attributes as $attribute) { + $this->assertArrayHasKey('encrypt', $attribute); + if ($attribute['key'] === 'firstName') { + $this->assertFalse($attribute['encrypt']); + } + if ($attribute['key'] === 'lastName') { + $this->assertTrue($attribute['encrypt']); + } + } + } public function testDeleteAttribute(): array From c51cf2f3e41f5d1ff146ee6e494ac0f6989787f4 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 23 May 2025 15:27:35 +0000 Subject: [PATCH 106/219] Merge pull request #9878 from ArnabChatterjee20k/dat-532 updated errro for the string encryption --- app/controllers/api/databases.php | 6 ++++++ app/init/constants.php | 1 + .../Services/Databases/DatabasesCustomServerTest.php | 12 ++++++++++++ 3 files changed, 19 insertions(+) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 54a4c565f4..ce0b94c488 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1352,6 +1352,12 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string if ($encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string attributes are not available on your plan. Please upgrade to create encrypted string attributes.'); } + if ($encrypt && $size < APP_DATABASE_ENCRYPT_SIZE_MIN) { + throw new Exception( + Exception::GENERAL_BAD_REQUEST, + "Size too small. Encrypted strings require a minimum size of " . APP_DATABASE_ENCRYPT_SIZE_MIN . " characters." + ); + } // Ensure attribute default is within required size $validator = new Text($size, 0); if (!is_null($default) && !$validator->isValid($default)) { diff --git a/app/init/constants.php b/app/init/constants.php index d7676d36ac..b96d514817 100644 --- a/app/init/constants.php +++ b/app/init/constants.php @@ -46,6 +46,7 @@ const APP_DATABASE_TIMEOUT_MILLISECONDS_API = 15 * 1000; // 15 seconds const APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER = 300 * 1000; // 5 minutes const APP_DATABASE_TIMEOUT_MILLISECONDS_TASK = 300 * 1000; // 5 minutes const APP_DATABASE_QUERY_MAX_VALUES = 500; +const APP_DATABASE_ENCRYPT_SIZE_MIN = 150; const APP_STORAGE_UPLOADS = '/storage/uploads'; const APP_STORAGE_FUNCTIONS = '/storage/functions'; const APP_STORAGE_BUILDS = '/storage/builds'; diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index c0d8763aa7..e66207b215 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -686,6 +686,18 @@ class DatabasesCustomServerTest extends Scope 'size' => 256, 'required' => true, ]); + // checking size test + $lastName = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'lastName', + 'size' => 149, + 'required' => true, + 'encrypt' => true + ]); + $this->assertEquals("Size too small. Encrypted strings require a minimum size of " . APP_DATABASE_ENCRYPT_SIZE_MIN . " characters.", $lastName['body']['message']); $lastName = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([ 'content-type' => 'application/json', From 86f7489640fc22b536fb3ada132af5c7b186ee2c Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 26 May 2025 17:42:11 +1200 Subject: [PATCH 107/219] Internal ID -> sequence --- CONTRIBUTING.md | 10 +- app/cli.php | 12 +- app/config/console.php | 2 +- app/controllers/api/account.php | 70 ++--- app/controllers/api/avatars.php | 12 +- app/controllers/api/databases.php | 260 +++++++++--------- app/controllers/api/functions.php | 94 +++---- app/controllers/api/messaging.php | 28 +- app/controllers/api/project.php | 18 +- app/controllers/api/projects.php | 46 ++-- app/controllers/api/proxy.php | 12 +- app/controllers/api/storage.php | 68 ++--- app/controllers/api/teams.php | 24 +- app/controllers/api/users.php | 28 +- app/controllers/api/vcs.php | 18 +- app/controllers/general.php | 12 +- app/controllers/mock.php | 4 +- app/controllers/shared/api.php | 4 +- app/http.php | 2 +- app/init/database/filters.php | 28 +- app/init/resources.php | 14 +- app/realtime.php | 10 +- app/worker.php | 16 +- src/Appwrite/Deletes/Targets.php | 4 +- src/Appwrite/Event/Event.php | 2 +- src/Appwrite/Migration/Migration.php | 10 +- src/Appwrite/Migration/Version/V15.php | 30 +- src/Appwrite/Migration/Version/V16.php | 2 +- src/Appwrite/Migration/Version/V17.php | 4 +- src/Appwrite/Migration/Version/V18.php | 16 +- src/Appwrite/Migration/Version/V19.php | 24 +- src/Appwrite/Migration/Version/V20.php | 24 +- src/Appwrite/Migration/Version/V21.php | 8 +- src/Appwrite/Platform/Tasks/Migrate.php | 4 +- src/Appwrite/Platform/Tasks/ScheduleBase.php | 10 +- .../Platform/Tasks/ScheduleExecutions.php | 4 +- .../Platform/Tasks/ScheduleMessages.php | 2 +- .../Platform/Tasks/StatsResources.php | 2 +- src/Appwrite/Platform/Workers/Audits.php | 14 +- src/Appwrite/Platform/Workers/Builds.php | 22 +- .../Platform/Workers/Certificates.php | 2 +- src/Appwrite/Platform/Workers/Databases.php | 44 +-- src/Appwrite/Platform/Workers/Deletes.php | 30 +- src/Appwrite/Platform/Workers/Functions.php | 12 +- src/Appwrite/Platform/Workers/Messaging.php | 4 +- src/Appwrite/Platform/Workers/Migrations.php | 2 +- .../Platform/Workers/StatsResources.php | 56 ++-- src/Appwrite/Platform/Workers/StatsUsage.php | 46 ++-- .../Platform/Workers/StatsUsageDump.php | 4 +- src/Appwrite/Platform/Workers/Webhooks.php | 4 +- .../Database/Validator/Queries/Base.php | 6 +- .../Utopia/Response/Model/Document.php | 2 +- .../e2e/Services/Databases/DatabasesBase.php | 12 +- .../Databases/DatabasesCustomServerTest.php | 1 - tests/resources/sites/static/code.tar.gz | Bin 0 -> 349 bytes 55 files changed, 599 insertions(+), 600 deletions(-) create mode 100644 tests/resources/sites/static/code.tar.gz diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index df88cfcfb9..d67b1627b2 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -393,8 +393,8 @@ In addition, you will also need to add some logic to the `reduce()` method of th ```php case $document->getCollection() === 'buckets': - $files = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES))); - $storage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE))); + $files = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getSequence(), METRIC_BUCKET_ID_FILES))); + $storage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getSequence(), METRIC_BUCKET_ID_FILES_STORAGE))); if (!empty($files['value'])) { $metrics[] = [ @@ -441,9 +441,9 @@ $queueForStatsUsage ->addMetric(METRIC_BUILDS, 1) ->addMetric(METRIC_BUILDS_STORAGE, $build->getAttribute('size', 0)) ->addMetric(METRIC_BUILDS_COMPUTE, (int)$build->getAttribute('duration', 0) * 1000) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS), 1) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE), $build->getAttribute('size', 0)) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int)$build->getAttribute('duration', 0) * 1000) + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS), 1) + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_STORAGE), $build->getAttribute('size', 0)) + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int)$build->getAttribute('duration', 0) * 1000) ->setProject($project) ->trigger(); ``` diff --git a/app/cli.php b/app/cli.php index 7b8d6cd52f..2520a50e8a 100644 --- a/app/cli.php +++ b/app/cli.php @@ -125,13 +125,13 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getInternalId()) + ->setTenant($project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); + ->setNamespace('_' . $project->getSequence()); } return $database; @@ -145,13 +145,13 @@ CLI::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getInternalId()) + ->setTenant($project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); + ->setNamespace('_' . $project->getSequence()); } $database @@ -167,7 +167,7 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) { return function (?Document $project = null) use ($pools, $cache, $database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { - $database->setTenant($project->getInternalId()); + $database->setTenant($project->getSequence()); return $database; } @@ -182,7 +182,7 @@ CLI::setResource('getLogsDB', function (Group $pools, Cache $cache) { // set tenant if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') { - $database->setTenant($project->getInternalId()); + $database->setTenant($project->getSequence()); } return $database; diff --git a/app/config/console.php b/app/config/console.php index e37c9b7836..1de3a99370 100644 --- a/app/config/console.php +++ b/app/config/console.php @@ -11,7 +11,7 @@ use Utopia\System\System; $console = [ '$id' => ID::custom('console'), - '$internalId' => ID::custom('console'), + '$sequence' => ID::custom('console'), 'name' => 'Appwrite', '$collection' => ID::custom('projects'), 'description' => 'Appwrite core engine', diff --git a/app/controllers/api/account.php b/app/controllers/api/account.php index 810c27c5f2..a21951d302 100644 --- a/app/controllers/api/account.php +++ b/app/controllers/api/account.php @@ -190,7 +190,7 @@ $createSession = function (string $userId, string $secret, Request $request, Res [ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'provider' => Auth::getSessionProviderByTokenType($verifiedToken->getAttribute('type')), 'secret' => Auth::hash($sessionSecret), // One way hash encryption to protect DB leak 'userAgent' => $request->getUserAgent('UNKNOWN'), @@ -387,7 +387,7 @@ App::post('/v1/account') 'search' => implode(' ', [$userId, $email, $name]), 'accessedAt' => DateTime::now(), ]); - $user->removeAttribute('$internalId'); + $user->removeAttribute('$sequence'); $user = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); try { $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ @@ -397,7 +397,7 @@ App::post('/v1/account') Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'providerType' => MESSAGE_TYPE_EMAIL, 'identifier' => $email, ]))); @@ -907,7 +907,7 @@ App::post('/v1/account/sessions/email') [ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'provider' => Auth::SESSION_PROVIDER_EMAIL, 'providerUid' => $email, 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak @@ -1056,7 +1056,7 @@ App::post('/v1/account/sessions/anonymous') 'search' => $userId, 'accessedAt' => DateTime::now(), ]); - $user->removeAttribute('$internalId'); + $user->removeAttribute('$sequence'); Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); // Create session token @@ -1069,7 +1069,7 @@ App::post('/v1/account/sessions/anonymous') [ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'provider' => Auth::SESSION_PROVIDER_ANONYMOUS, 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'userAgent' => $request->getUserAgent('UNKNOWN'), @@ -1440,7 +1440,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), - Query::notEqual('userInternalId', $user->getInternalId()), + Query::notEqual('userInternalId', $user->getSequence()), ]); if (!$identityWithMatchingEmail->isEmpty()) { $failureRedirect(Exception::USER_ALREADY_EXISTS); @@ -1554,7 +1554,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') 'search' => implode(' ', [$userId, $email, $name]), 'accessedAt' => DateTime::now(), ]); - $user->removeAttribute('$internalId'); + $user->removeAttribute('$sequence'); $userDoc = Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); $dbForProject->createDocument('targets', new Document([ '$permissions' => [ @@ -1563,7 +1563,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') Permission::delete(Role::user($user->getId())), ], 'userId' => $userDoc->getId(), - 'userInternalId' => $userDoc->getInternalId(), + 'userInternalId' => $userDoc->getSequence(), 'providerType' => MESSAGE_TYPE_EMAIL, 'identifier' => $email, ])); @@ -1582,7 +1582,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') } $identity = $dbForProject->findOne('identities', [ - Query::equal('userInternalId', [$user->getInternalId()]), + Query::equal('userInternalId', [$user->getSequence()]), Query::equal('provider', [$provider]), Query::equal('providerUid', [$oauth2ID]), ]); @@ -1592,7 +1592,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $identitiesWithMatchingEmail = $dbForProject->find('identities', [ Query::equal('providerEmail', [$email]), - Query::notEqual('userInternalId', $user->getInternalId()), + Query::notEqual('userInternalId', $user->getSequence()), ]); if (!empty($identitiesWithMatchingEmail)) { $failureRedirect(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */ @@ -1605,7 +1605,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') Permission::update(Role::user($userId)), Permission::delete(Role::user($userId)), ], - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'userId' => $userId, 'provider' => $provider, 'providerUid' => $oauth2ID, @@ -1648,7 +1648,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $token = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'type' => Auth::TOKEN_TYPE_OAUTH2, 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'expire' => $expire, @@ -1683,7 +1683,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $session = new Document(array_merge([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'provider' => $provider, 'providerUid' => $oauth2ID, 'providerAccessToken' => $accessToken, @@ -1736,7 +1736,7 @@ App::get('/v1/account/sessions/oauth2/:provider/redirect') $target ->setAttribute('sessionId', $session->getId()) - ->setAttribute('sessionInternalId', $session->getInternalId()); + ->setAttribute('sessionInternalId', $session->getSequence()); $dbForProject->updateDocument('targets', $target->getId(), $target); } @@ -1931,7 +1931,7 @@ App::post('/v1/account/tokens/magic-url') 'accessedAt' => DateTime::now(), ]); - $user->removeAttribute('$internalId'); + $user->removeAttribute('$sequence'); Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); } @@ -1941,7 +1941,7 @@ App::post('/v1/account/tokens/magic-url') $token = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'type' => Auth::TOKEN_TYPE_MAGIC_URL, 'secret' => Auth::hash($tokenSecret), // One way hash encryption to protect DB leak 'expire' => $expire, @@ -2168,7 +2168,7 @@ App::post('/v1/account/tokens/email') 'accessedAt' => DateTime::now(), ]); - $user->removeAttribute('$internalId'); + $user->removeAttribute('$sequence'); Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); } @@ -2178,7 +2178,7 @@ App::post('/v1/account/tokens/email') $token = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'type' => Auth::TOKEN_TYPE_EMAIL, 'secret' => Auth::hash($tokenSecret), // One way hash encryption to protect DB leak 'expire' => $expire, @@ -2460,7 +2460,7 @@ App::post('/v1/account/tokens/phone') 'accessedAt' => DateTime::now(), ]); - $user->removeAttribute('$internalId'); + $user->removeAttribute('$sequence'); Authorization::skip(fn () => $dbForProject->createDocument('users', $user)); try { $target = Authorization::skip(fn () => $dbForProject->createDocument('targets', new Document([ @@ -2470,7 +2470,7 @@ App::post('/v1/account/tokens/phone') Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'providerType' => MESSAGE_TYPE_SMS, 'identifier' => $phone, ]))); @@ -2501,7 +2501,7 @@ App::post('/v1/account/tokens/phone') $token = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'type' => Auth::TOKEN_TYPE_PHONE, 'secret' => Auth::hash($secret), 'expire' => $expire, @@ -2703,7 +2703,7 @@ App::get('/v1/account/logs') $audit = new EventAudit($dbForProject); - $logs = $audit->getLogsByUser($user->getInternalId(), $queries); + $logs = $audit->getLogsByUser($user->getSequence(), $queries); $output = []; @@ -2732,7 +2732,7 @@ App::get('/v1/account/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByUser($user->getInternalId(), $queries), + 'total' => $audit->countLogsByUser($user->getSequence(), $queries), 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -2900,7 +2900,7 @@ App::patch('/v1/account/email') // Makes sure this email is not already used in another identity $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), - Query::notEqual('userInternalId', $user->getInternalId()), + Query::notEqual('userInternalId', $user->getSequence()), ]); if (!$identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::GENERAL_BAD_REQUEST); /** Return a generic bad request to prevent exposing existing accounts */ @@ -3183,7 +3183,7 @@ App::post('/v1/account/recovery') $recovery = new Document([ '$id' => ID::unique(), 'userId' => $profile->getId(), - 'userInternalId' => $profile->getInternalId(), + 'userInternalId' => $profile->getSequence(), 'type' => Auth::TOKEN_TYPE_RECOVERY, 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'expire' => $expire, @@ -3438,7 +3438,7 @@ App::post('/v1/account/verification') $verification = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'type' => Auth::TOKEN_TYPE_VERIFICATION, 'secret' => Auth::hash($verificationSecret), // One way hash encryption to protect DB leak 'expire' => $expire, @@ -3685,7 +3685,7 @@ App::post('/v1/account/verification/phone') $verification = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'type' => Auth::TOKEN_TYPE_PHONE, 'secret' => Auth::hash($secret), 'expire' => $expire, @@ -3979,7 +3979,7 @@ App::post('/v1/account/mfa/authenticators/:type') $authenticator = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'type' => Type::TOTP, 'verified' => false, 'data' => [ @@ -4292,7 +4292,7 @@ App::post('/v1/account/mfa/challenge') $code = Auth::codeGenerator(); $challenge = new Document([ 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'type' => $factor, 'token' => Auth::tokenGenerator(), 'code' => $code, @@ -4621,12 +4621,12 @@ App::post('/v1/account/targets/push') Permission::delete(Role::user($user->getId())), ], 'providerId' => !empty($providerId) ? $providerId : null, - 'providerInternalId' => !empty($providerId) ? $provider->getInternalId() : null, + 'providerInternalId' => !empty($providerId) ? $provider->getSequence() : null, 'providerType' => MESSAGE_TYPE_PUSH, 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'sessionId' => $session->getId(), - 'sessionInternalId' => $session->getInternalId(), + 'sessionInternalId' => $session->getSequence(), 'identifier' => $identifier, 'name' => "{$device['deviceBrand']} {$device['deviceModel']}" ])); @@ -4745,7 +4745,7 @@ App::delete('/v1/account/targets/:targetId/push') throw new Exception(Exception::USER_TARGET_NOT_FOUND); } - if ($user->getInternalId() !== $target->getAttribute('userInternalId')) { + if ($user->getSequence() !== $target->getAttribute('userInternalId')) { throw new Exception(Exception::USER_TARGET_NOT_FOUND); } @@ -4794,7 +4794,7 @@ App::get('/v1/account/identities') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $queries[] = Query::equal('userInternalId', [$user->getInternalId()]); + $queries[] = Query::equal('userInternalId', [$user->getSequence()]); /** * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries diff --git a/app/controllers/api/avatars.php b/app/controllers/api/avatars.php index 05a9af81f8..719bcae81a 100644 --- a/app/controllers/api/avatars.php +++ b/app/controllers/api/avatars.php @@ -668,7 +668,7 @@ App::get('/v1/cards/cloud') } } - $isPlatinum = $user->getInternalId() % 100 === 0; + $isPlatinum = $user->getSequence() % 100 === 0; } else { $name = $mock === 'normal-long' ? 'Sir First Walter O\'Brian Junior' : 'Walter O\'Brian'; $createdAt = new \DateTime('now'); @@ -858,7 +858,7 @@ App::get('/v1/cards/cloud-back') $isEmployee = \array_key_exists($email, $employees); $isGolden = $isEmployee || $isHero || $isContributor; - $isPlatinum = $user->getInternalId() % 100 === 0; + $isPlatinum = $user->getSequence() % 100 === 0; } else { $userId = '63e0bcf3c3eb803ba530'; @@ -925,9 +925,9 @@ App::get('/v1/cards/cloud-og') } if (!$mock) { - $internalId = $user->getInternalId(); - $bgVariation = $internalId % 3 === 0 ? '1' : ($internalId % 3 === 1 ? '2' : '3'); - $cardVariation = $internalId % 3 === 0 ? '1' : ($internalId % 3 === 1 ? '2' : '3'); + $sequence = $user->getSequence(); + $bgVariation = $sequence % 3 === 0 ? '1' : ($sequence % 3 === 1 ? '2' : '3'); + $cardVariation = $sequence % 3 === 0 ? '1' : ($sequence % 3 === 1 ? '2' : '3'); $name = $user->getAttribute('name', 'Anonymous'); $email = $user->getAttribute('email', ''); @@ -957,7 +957,7 @@ App::get('/v1/cards/cloud-og') } } - $isPlatinum = $user->getInternalId() % 100 === 0; + $isPlatinum = $user->getSequence() % 100 === 0; } else { $bgVariation = \str_ends_with($mock, '-bg2') ? '2' : (\str_ends_with($mock, '-bg3') ? '3' : '1'); $cardVariation = \str_ends_with($mock, '-right') ? '2' : (\str_ends_with($mock, '-middle') ? '3' : '1'); diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index ce0b94c488..0d6f98e8c8 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -107,7 +107,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -130,7 +130,7 @@ function createAttribute(string $databaseId, string $collectionId, Document $att if ($type === Database::VAR_RELATIONSHIP) { $options['side'] = Database::RELATION_SIDE_PARENT; - $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection'] ?? ''); + $relatedCollection = $dbForProject->getDocument('database_' . $database->getSequence(), $options['relatedCollection'] ?? ''); if ($relatedCollection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND, 'The related collection was not found.'); } @@ -138,11 +138,11 @@ function createAttribute(string $databaseId, string $collectionId, Document $att try { $attribute = new Document([ - '$id' => ID::custom($database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key), + '$id' => ID::custom($database->getSequence() . '_' . $collection->getSequence() . '_' . $key), 'key' => $key, - 'databaseInternalId' => $database->getInternalId(), + 'databaseInternalId' => $database->getSequence(), 'databaseId' => $database->getId(), - 'collectionInternalId' => $collection->getInternalId(), + 'collectionInternalId' => $collection->getSequence(), 'collectionId' => $collectionId, 'type' => $type, 'status' => 'processing', // processing, available, failed, deleting, stuck @@ -164,13 +164,13 @@ function createAttribute(string $databaseId, string $collectionId, Document $att } catch (LimitException) { throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED); } catch (\Throwable $e) { - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); throw $e; } - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); if ($type === Database::VAR_RELATIONSHIP && $options['twoWay']) { $twoWayKey = $options['twoWayKey']; @@ -181,11 +181,11 @@ function createAttribute(string $databaseId, string $collectionId, Document $att try { try { $twoWayAttribute = new Document([ - '$id' => ID::custom($database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $twoWayKey), + '$id' => ID::custom($database->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $twoWayKey), 'key' => $twoWayKey, - 'databaseInternalId' => $database->getInternalId(), + 'databaseInternalId' => $database->getSequence(), 'databaseId' => $database->getId(), - 'collectionInternalId' => $relatedCollection->getInternalId(), + 'collectionInternalId' => $relatedCollection->getSequence(), 'collectionId' => $relatedCollection->getId(), 'type' => $type, 'status' => 'processing', // processing, available, failed, deleting, stuck @@ -213,13 +213,13 @@ function createAttribute(string $databaseId, string $collectionId, Document $att $dbForProject->deleteDocument('attributes', $attribute->getId()); throw $e; } finally { - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); } // If operation succeeded, purge the cache for the related collection too - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $relatedCollection->getId()); + $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence()); } $queueForDatabase @@ -262,12 +262,12 @@ function updateAttribute( throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $attribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $collection->getSequence() . '_' . $key); if ($attribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); } @@ -292,7 +292,7 @@ function updateAttribute( throw new Exception(Exception::ATTRIBUTE_DEFAULT_UNSUPPORTED, 'Cannot set default value for array attributes'); } - $collectionId = 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(); + $collectionId = 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(); $attribute ->setAttribute('default', $default) @@ -378,8 +378,8 @@ function updateAttribute( } if ($primaryDocumentOptions['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $primaryDocumentOptions['relatedCollection']); - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey']); + $relatedCollection = $dbForProject->getDocument('database_' . $database->getSequence(), $primaryDocumentOptions['relatedCollection']); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $primaryDocumentOptions['twoWayKey']); if (!empty($newKey) && $newKey !== $key) { $options['twoWayKey'] = $newKey; @@ -389,8 +389,8 @@ function updateAttribute( $relatedAttribute->setAttribute('options', $relatedOptions); - $dbForProject->updateDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $primaryDocumentOptions['twoWayKey'], $relatedAttribute); - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); + $dbForProject->updateDocument('attributes', $database->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $primaryDocumentOptions['twoWayKey'], $relatedAttribute); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $relatedCollection->getId()); } } else { try { @@ -418,7 +418,7 @@ function updateAttribute( $originalUid = $attribute->getId(); $attribute - ->setAttribute('$id', ID::custom($database->getInternalId() . '_' . $collection->getInternalId() . '_' . $newKey)) + ->setAttribute('$id', ID::custom($database->getSequence() . '_' . $collection->getSequence() . '_' . $newKey)) ->setAttribute('key', $newKey); try { @@ -444,10 +444,10 @@ function updateAttribute( } } } else { - $attribute = $dbForProject->updateDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key, $attribute); + $attribute = $dbForProject->updateDocument('attributes', $database->getSequence() . '_' . $collection->getSequence() . '_' . $key, $attribute); } - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collection->getId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collection->getId()); $queueForEvents ->setContext('collection', $collection) @@ -536,7 +536,7 @@ App::post('/v1/databases') } try { - $dbForProject->createCollection('database_' . $database->getInternalId(), $attributes, $indexes); + $dbForProject->createCollection('database_' . $database->getSequence(), $attributes, $indexes); } catch (DuplicateException) { throw new Exception(Exception::DATABASE_ALREADY_EXISTS); } catch (IndexException) { @@ -839,7 +839,7 @@ App::delete('/v1/databases/:databaseId') } $dbForProject->purgeCachedDocument('databases', $database->getId()); - $dbForProject->purgeCachedCollection('databases_' . $database->getInternalId()); + $dbForProject->purgeCachedCollection('databases_' . $database->getSequence()); $queueForDatabase ->setType(DATABASE_TYPE_DELETE_DATABASE) @@ -899,9 +899,9 @@ App::post('/v1/databases/:databaseId/collections') $permissions = Permission::aggregate($permissions) ?? []; try { - $collection = $dbForProject->createDocument('database_' . $database->getInternalId(), new Document([ + $collection = $dbForProject->createDocument('database_' . $database->getSequence(), new Document([ '$id' => $collectionId, - 'databaseInternalId' => $database->getInternalId(), + 'databaseInternalId' => $database->getSequence(), 'databaseId' => $databaseId, '$permissions' => $permissions, 'documentSecurity' => $documentSecurity, @@ -919,7 +919,7 @@ App::post('/v1/databases/:databaseId/collections') try { $dbForProject->createCollection( - id: 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + id: 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), permissions: $permissions, documentSecurity: $documentSecurity ); @@ -1000,7 +1000,7 @@ App::get('/v1/databases/:databaseId/collections') $collectionId = $cursor->getValue(); - $cursorDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $cursorDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Collection '{$collectionId}' for the 'cursor' value not found."); @@ -1009,7 +1009,7 @@ App::get('/v1/databases/:databaseId/collections') $cursor->setValue($cursorDocument); } - $collectionId = 'database_' . $database->getInternalId(); + $collectionId = 'database_' . $database->getSequence(); try { $collections = $dbForProject->find($collectionId, $queries); @@ -1057,7 +1057,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -1100,8 +1100,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/logs') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); + $collectionDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $database->getSequence() . '_collection_' . $collectionDocument->getSequence()); if ($collectionDocument->isEmpty() || $collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -1215,7 +1215,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -1236,12 +1236,12 @@ App::put('/v1/databases/:databaseId/collections/:collectionId') ->setAttribute('search', \implode(' ', [$collectionId, $name])); $collection = $dbForProject->updateDocument( - 'database_' . $database->getInternalId(), + 'database_' . $database->getSequence(), $collectionId, $collection ); - $dbForProject->updateCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $permissions, $documentSecurity); + $dbForProject->updateCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $permissions, $documentSecurity); $queueForEvents ->setContext('database', $database) @@ -1287,17 +1287,17 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - if (!$dbForProject->deleteDocument('database_' . $database->getInternalId(), $collectionId)) { + if (!$dbForProject->deleteDocument('database_' . $database->getSequence(), $collectionId)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove collection from DB'); } - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); $queueForDatabase ->setType(DATABASE_TYPE_DELETE_COLLECTION) @@ -1888,15 +1888,15 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/relati throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $relatedCollectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId); - $relatedCollection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollectionDocument->getInternalId()); + $relatedCollectionDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId); + $relatedCollection = $dbForProject->getCollection('database_' . $database->getSequence() . '_collection_' . $relatedCollectionDocument->getSequence()); if ($relatedCollection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -1997,7 +1997,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -2010,8 +2010,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') \array_push( $queries, - Query::equal('databaseInternalId', [$database->getInternalId()]), - Query::equal('collectionInternalId', [$collection->getInternalId()]), + Query::equal('databaseInternalId', [$database->getSequence()]), + Query::equal('collectionInternalId', [$collection->getSequence()]), ); /** @@ -2033,8 +2033,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') try { $cursorDocument = $dbForProject->findOne('attributes', [ - Query::equal('databaseInternalId', [$database->getInternalId()]), - Query::equal('collectionInternalId', [$collection->getInternalId()]), + Query::equal('databaseInternalId', [$database->getSequence()]), + Query::equal('collectionInternalId', [$collection->getSequence()]), Query::equal('key', [$attributeId]), ]); } catch (QueryException $e) { @@ -2112,13 +2112,13 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $attribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $collection->getSequence() . '_' . $key); if ($attribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); @@ -2725,13 +2725,13 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $attribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $attribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $collection->getSequence() . '_' . $key); if ($attribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); @@ -2754,19 +2754,19 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key $attribute = $dbForProject->updateDocument('attributes', $attribute->getId(), $attribute->setAttribute('status', 'deleting')); } - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); + $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { $options = $attribute->getAttribute('options'); if ($options['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); + $relatedCollection = $dbForProject->getDocument('database_' . $database->getSequence(), $options['relatedCollection']); if ($relatedCollection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $options['twoWayKey']); if ($relatedAttribute->isEmpty()) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); @@ -2776,8 +2776,8 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/attributes/:key $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'deleting')); } - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $options['relatedCollection']); - $dbForProject->purgeCachedCollection('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $options['relatedCollection']); + $dbForProject->purgeCachedCollection('database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence()); } } @@ -2859,7 +2859,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -2868,8 +2868,8 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') $limit = $dbForProject->getLimitForIndexes(); $count = $dbForProject->count('indexes', [ - Query::equal('collectionInternalId', [$collection->getInternalId()]), - Query::equal('databaseInternalId', [$database->getInternalId()]) + Query::equal('collectionInternalId', [$collection->getSequence()]), + Query::equal('databaseInternalId', [$database->getSequence()]) ], max: $limit); @@ -2939,12 +2939,12 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') } $index = new Document([ - '$id' => ID::custom($database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key), + '$id' => ID::custom($database->getSequence() . '_' . $collection->getSequence() . '_' . $key), 'key' => $key, 'status' => 'processing', // processing, available, failed, deleting, stuck - 'databaseInternalId' => $database->getInternalId(), + 'databaseInternalId' => $database->getSequence(), 'databaseId' => $databaseId, - 'collectionInternalId' => $collection->getInternalId(), + 'collectionInternalId' => $collection->getSequence(), 'collectionId' => $collectionId, 'type' => $type, 'attributes' => $attributes, @@ -2968,7 +2968,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') throw new Exception(Exception::INDEX_ALREADY_EXISTS); } - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); $queueForDatabase ->setType(DATABASE_TYPE_CREATE_INDEX) @@ -3020,7 +3020,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -3051,8 +3051,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes') $indexId = $cursor->getValue(); $cursorDocument = Authorization::skip(fn () => $dbForProject->find('indexes', [ - Query::equal('collectionInternalId', [$collection->getInternalId()]), - Query::equal('databaseInternalId', [$database->getInternalId()]), + Query::equal('collectionInternalId', [$collection->getSequence()]), + Query::equal('databaseInternalId', [$database->getSequence()]), Query::equal('key', [$indexId]), Query::limit(1) ])); @@ -3111,7 +3111,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -3164,13 +3164,13 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $index = $dbForProject->getDocument('indexes', $database->getInternalId() . '_' . $collection->getInternalId() . '_' . $key); + $index = $dbForProject->getDocument('indexes', $database->getSequence() . '_' . $collection->getSequence() . '_' . $key); if ($index->isEmpty()) { throw new Exception(Exception::INDEX_NOT_FOUND); @@ -3181,7 +3181,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') $index = $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'deleting')); } - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); $queueForDatabase ->setType(DATABASE_TYPE_DELETE_INDEX) @@ -3317,7 +3317,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -3426,7 +3426,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($relations as &$relation) { @@ -3440,7 +3440,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') } if ($relation instanceof Document) { $current = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), $relation->getId()) + fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId()) ); if ($current->isEmpty()) { @@ -3495,7 +3495,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') try { $dbForProject->createDocuments( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documents ); } catch (DuplicateException) { @@ -3537,7 +3537,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -3554,7 +3554,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); // per collection + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); // per collection $response->setStatusCode(Response::STATUS_CODE_CREATED); @@ -3612,7 +3612,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -3640,7 +3640,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $documentId = $cursor->getValue(); - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); if ($cursorDocument->isEmpty()) { throw new Exception(Exception::GENERAL_CURSOR_NOT_FOUND, "Document '{$documentId}' for the 'cursor' value not found."); @@ -3649,8 +3649,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $cursor->setValue($cursorDocument); } try { - $documents = $dbForProject->find('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries); - $total = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $queries, APP_LIMIT_COUNT); + $documents = $dbForProject->find('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $queries); + $total = $dbForProject->count('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $queries, APP_LIMIT_COUNT); } catch (OrderException $e) { throw new Exception(Exception::DATABASE_QUERY_ORDER_NULL, "The order attribute '{$e->getAttribute()}' had a null value. Cursor pagination requires all documents order attribute values are non-null."); } catch (QueryException $e) { @@ -3694,7 +3694,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $relatedCollectionId = $relationship->getAttribute('relatedCollection'); // todo: Use local cache for this getDocument - $relatedCollection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId)); + $relatedCollection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId)); foreach ($relations as $index => $doc) { if ($doc instanceof Document) { @@ -3720,7 +3720,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_READS, \max(1, $operations)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), \max(1, $operations)); + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_READS), \max(1, $operations)); $select = \array_reduce($queries, function ($result, $query) { return $result || ($query->getMethod() === Query::TYPE_SELECT); @@ -3791,7 +3791,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -3803,7 +3803,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen } try { - $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId, $queries); + $document = $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId, $queries); } catch (QueryException $e) { throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } @@ -3847,7 +3847,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -3862,7 +3862,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_READS, \max(1, $operations)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), \max(1, $operations)); + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_READS), \max(1, $operations)); $response->dynamic($document, Response::MODEL_DOCUMENT); }); @@ -3901,12 +3901,12 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } - $document = $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId); + $document = $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); @@ -4030,13 +4030,13 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } // Read permission should not be required for update - $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); } @@ -4105,7 +4105,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($relations as &$relation) { @@ -4120,7 +4120,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum } if ($relation instanceof Document) { $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( - 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); $relation->removeAttribute('$collectionId'); @@ -4128,7 +4128,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum // Attribute $collection is required for Utopia. $relation->setAttribute( '$collection', - 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId() + 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence() ); if ($oldDocument->isEmpty()) { @@ -4152,11 +4152,11 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); try { $document = $dbForProject->updateDocument( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $document->getId(), $newDocument ); @@ -4192,7 +4192,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -4274,7 +4274,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -4339,7 +4339,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($relations as &$relation) { @@ -4354,7 +4354,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen } if ($relation instanceof Document) { $oldDocument = Authorization::skip(fn () => $dbForProject->getDocument( - 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), $relation->getId() )); $relation->removeAttribute('$collectionId'); @@ -4362,7 +4362,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen // Attribute $collection is required for Utopia. $relation->setAttribute( '$collection', - 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId() + 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence() ); if ($oldDocument->isEmpty()) { @@ -4386,12 +4386,12 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); $upserted = []; try { $modified = $dbForProject->createOrUpdateDocuments( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), [$newDocument], onNext: function (Document $document) use (&$upserted) { $upserted[] = $document; @@ -4430,7 +4430,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -4509,7 +4509,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -4540,7 +4540,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents') try { $modified = $dbForProject->updateDocuments( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), new Document($data), $queries, onNext: function (Document $document) use ($plan, &$documents) { @@ -4564,7 +4564,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $modified)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); $response->dynamic(new Document([ 'total' => $modified, @@ -4609,7 +4609,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -4631,7 +4631,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents') try { $modified = $dbForProject->createOrUpdateDocuments( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documents, onNext: function (Document $document) use ($plan, &$upserted) { if (\count($upserted) < ($plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH)) { @@ -4656,7 +4656,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $modified)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); $response->dynamic(new Document([ 'total' => $modified, @@ -4707,20 +4707,20 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId)); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty() || (!$collection->getAttribute('enabled', false) && !$isAPIKey && !$isPrivilegedUser)) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } // Read permission should not be required for delete - $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $documentId)); + $document = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId)); if ($document->isEmpty()) { throw new Exception(Exception::DOCUMENT_NOT_FOUND); } try { $dbForProject->deleteDocument( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $documentId ); } catch (ConflictException) { @@ -4755,7 +4755,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $relatedCollectionId = $relationship->getAttribute('relatedCollection'); $relatedCollection = Authorization::skip( - fn () => $dbForProject->getDocument('database_' . $database->getInternalId(), $relatedCollectionId) + fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $relatedCollectionId) ); foreach ($related as $relation) { @@ -4770,7 +4770,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents/:docu $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $operations)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $operations)); $relationships = \array_map( fn ($document) => $document->getAttribute('key'), @@ -4829,7 +4829,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents') throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -4853,7 +4853,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents') try { $modified = $dbForProject->deleteDocuments( - 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), + 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $queries, onNext: function (Document $document) use ($plan, &$documents) { if (\count($documents) < ($plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH)) { @@ -4874,7 +4874,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents') $queueForStatsUsage ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, \max(1, $modified)) - ->addMetric(str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), \max(1, $modified)); $response->dynamic(new Document([ 'total' => $modified, @@ -5010,11 +5010,11 @@ App::get('/v1/databases/:databaseId/usage') $stats = $usage = []; $days = $periods[$range]; $metrics = [ - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS), - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS), - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_STORAGE), - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_READS), - str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_OPERATIONS_WRITES) + str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_COLLECTIONS), + str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_DOCUMENTS), + str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_STORAGE), + str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_READS), + str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES) ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { @@ -5103,8 +5103,8 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') ->inject('dbForProject') ->action(function (string $databaseId, string $range, string $collectionId, Response $response, Database $dbForProject) { $database = $dbForProject->getDocument('databases', $databaseId); - $collectionDocument = $dbForProject->getDocument('database_' . $database->getInternalId(), $collectionId); - $collection = $dbForProject->getCollection('database_' . $database->getInternalId() . '_collection_' . $collectionDocument->getInternalId()); + $collectionDocument = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = $dbForProject->getCollection('database_' . $database->getSequence() . '_collection_' . $collectionDocument->getSequence()); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); @@ -5114,7 +5114,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/usage') $stats = $usage = []; $days = $periods[$range]; $metrics = [ - str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collectionDocument->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), + str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getSequence(), $collectionDocument->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS), ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { diff --git a/app/controllers/api/functions.php b/app/controllers/api/functions.php index 179cd0b6e5..da8aedb130 100644 --- a/app/controllers/api/functions.php +++ b/app/controllers/api/functions.php @@ -109,13 +109,13 @@ $redeployVcs = function (Request $request, Document $function, Document $project Permission::delete(Role::any()), ], 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceType' => 'functions', 'entrypoint' => $entrypoint, 'commands' => $function->getAttribute('commands', ''), 'type' => 'vcs', 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), + 'installationInternalId' => $installation->getSequence(), 'providerRepositoryId' => $providerRepositoryId, 'repositoryId' => $function->getAttribute('repositoryId', ''), 'repositoryInternalId' => $function->getAttribute('repositoryInternalId', ''), @@ -285,7 +285,7 @@ App::post('/v1/functions') 'search' => implode(' ', [$functionId, $name, $runtime]), 'version' => 'v4', 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), + 'installationInternalId' => $installation->getSequence(), 'providerRepositoryId' => $providerRepositoryId, 'repositoryId' => '', 'repositoryInternalId' => '', @@ -300,7 +300,7 @@ App::post('/v1/functions') 'region' => $project->getAttribute('region'), 'resourceType' => 'function', 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $function->getAttribute('schedule'), @@ -309,7 +309,7 @@ App::post('/v1/functions') ); $function->setAttribute('scheduleId', $schedule->getId()); - $function->setAttribute('scheduleInternalId', $schedule->getInternalId()); + $function->setAttribute('scheduleInternalId', $schedule->getSequence()); // Git connect logic if (!empty($providerRepositoryId)) { @@ -325,18 +325,18 @@ App::post('/v1/functions') Permission::delete(Role::team(ID::custom($teamId), 'developer')), ], 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), + 'installationInternalId' => $installation->getSequence(), 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'providerRepositoryId' => $providerRepositoryId, 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceType' => 'function', 'providerPullRequestIds' => [] ])); $function->setAttribute('repositoryId', $repository->getId()); - $function->setAttribute('repositoryInternalId', $repository->getInternalId()); + $function->setAttribute('repositoryInternalId', $repository->getSequence()); } $function = $dbForProject->updateDocument('functions', $function->getId(), $function); @@ -355,7 +355,7 @@ App::post('/v1/functions') Permission::delete(Role::any()), ], 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceType' => 'functions', 'entrypoint' => $function->getAttribute('entrypoint', ''), 'commands' => $function->getAttribute('commands', ''), @@ -382,11 +382,11 @@ App::post('/v1/functions') fn () => $dbForPlatform->createDocument('rules', new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'domain' => $domain, 'resourceType' => 'function', 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'status' => 'verified', 'certificateId' => '', 'owner' => 'Appwrite', @@ -650,15 +650,15 @@ App::get('/v1/functions/:functionId/usage') $stats = $usage = []; $days = $periods[$range]; $metrics = [ - str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $function->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS), - str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $function->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE), - str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS), - str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE), - str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), - str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), - str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), - str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS), - str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS) + str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $function->getSequence()], METRIC_FUNCTION_ID_DEPLOYMENTS), + str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $function->getSequence()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE), + str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS), + str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_STORAGE), + str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), + str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_EXECUTIONS), + str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), + str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS), + str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS) ]; Authorization::skip(function () use ($dbForProject, $days, $metrics, &$stats) { @@ -928,8 +928,8 @@ App::put('/v1/functions/:functionId') // Git disconnect logic. Disconnecting only when providerRepositoryId is empty, allowing for continue updates without disconnecting git if ($isConnected && ($providerRepositoryId !== null && empty($providerRepositoryId))) { $repositories = $dbForPlatform->find('repositories', [ - Query::equal('projectInternalId', [$project->getInternalId()]), - Query::equal('resourceInternalId', [$function->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('resourceInternalId', [$function->getSequence()]), Query::equal('resourceType', ['function']), Query::limit(100), ]); @@ -961,18 +961,18 @@ App::put('/v1/functions/:functionId') Permission::delete(Role::team(ID::custom($teamId), 'developer')), ], 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), + 'installationInternalId' => $installation->getSequence(), 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'providerRepositoryId' => $providerRepositoryId, 'resourceId' => $function->getId(), - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceType' => 'function', 'providerPullRequestIds' => [] ])); $repositoryId = $repository->getId(); - $repositoryInternalId = $repository->getInternalId(); + $repositoryInternalId = $repository->getSequence(); } $live = true; @@ -1015,7 +1015,7 @@ App::put('/v1/functions/:functionId') 'commands' => $commands, 'scopes' => $scopes, 'installationId' => $installation->getId(), - 'installationInternalId' => $installation->getInternalId(), + 'installationInternalId' => $installation->getSequence(), 'providerRepositoryId' => $providerRepositoryId, 'repositoryId' => $repositoryId, 'repositoryInternalId' => $repositoryInternalId, @@ -1188,7 +1188,7 @@ App::patch('/v1/functions/:functionId/deployments/:deploymentId') } $function = $dbForProject->updateDocument('functions', $function->getId(), new Document(array_merge($function->getArrayCopy(), [ - 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->getSequence(), 'deployment' => $deployment->getId(), ]))); @@ -1427,7 +1427,7 @@ App::post('/v1/functions/:functionId/deployments') Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceId' => $function->getId(), 'resourceType' => 'functions', 'buildInternalId' => '', @@ -1458,7 +1458,7 @@ App::post('/v1/functions/:functionId/deployments') Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceId' => $function->getId(), 'resourceType' => 'functions', 'buildInternalId' => '', @@ -1531,7 +1531,7 @@ App::get('/v1/functions/:functionId/deployments') } // Set resource queries - $queries[] = Query::equal('resourceInternalId', [$function->getInternalId()]); + $queries[] = Query::equal('resourceInternalId', [$function->getSequence()]); $queries[] = Query::equal('resourceType', ['functions']); /** @@ -1759,9 +1759,9 @@ App::post('/v1/functions/:functionId/deployments/:deploymentId/build') $destination = $deviceForFunctions->getPath($deploymentId . '.' . \pathinfo('code.tar.gz', PATHINFO_EXTENSION)); $deviceForFunctions->transfer($path, $destination, $deviceForFunctions); - $deployment->removeAttribute('$internalId'); + $deployment->removeAttribute('$sequence'); $deployment = $dbForProject->createDocument('deployments', $deployment->setAttributes([ - '$internalId' => '', + '$sequence' => '', '$id' => $deploymentId, 'buildId' => '', 'buildInternalId' => '', @@ -1831,7 +1831,7 @@ App::patch('/v1/functions/:functionId/deployments/:deploymentId/build') '$id' => $buildId, '$permissions' => [], 'startTime' => DateTime::now(), - 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->getSequence(), 'deploymentId' => $deployment->getId(), 'status' => 'canceled', 'path' => '', @@ -1844,7 +1844,7 @@ App::patch('/v1/functions/:functionId/deployments/:deploymentId/build') ])); $deployment->setAttribute('buildId', $build->getId()); - $deployment->setAttribute('buildInternalId', $build->getInternalId()); + $deployment->setAttribute('buildInternalId', $build->getSequence()); $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); } else { if (\in_array($build->getAttribute('status'), ['ready', 'failed'])) { @@ -2061,9 +2061,9 @@ App::post('/v1/functions/:functionId/executions') $execution = new Document([ '$id' => $executionId, '$permissions' => !$user->isEmpty() ? [Permission::read(Role::user($user->getId()))] : [], - 'functionInternalId' => $function->getInternalId(), + 'functionInternalId' => $function->getSequence(), 'functionId' => $function->getId(), - 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->getSequence(), 'deploymentId' => $deployment->getId(), 'trigger' => (!is_null($scheduledAt)) ? 'schedule' : 'http', 'status' => $status, // waiting / processing / completed / failed / scheduled @@ -2113,7 +2113,7 @@ App::post('/v1/functions/:functionId/executions') 'region' => $project->getAttribute('region'), 'resourceType' => ScheduleExecutions::getSupportedResource(), 'resourceId' => $execution->getId(), - 'resourceInternalId' => $execution->getInternalId(), + 'resourceInternalId' => $execution->getSequence(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -2123,7 +2123,7 @@ App::post('/v1/functions/:functionId/executions') $execution = $execution ->setAttribute('scheduleId', $schedule->getId()) - ->setAttribute('scheduleInternalId', $schedule->getInternalId()) + ->setAttribute('scheduleInternalId', $schedule->getSequence()) ->setAttribute('scheduledAt', $scheduledAt); $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); @@ -2246,11 +2246,11 @@ App::post('/v1/functions/:functionId/executions') } finally { $queueForStatsUsage ->addMetric(METRIC_EXECUTIONS, 1) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), 1) + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_EXECUTIONS), 1) ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000)) // per project - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function ->addMetric(METRIC_EXECUTIONS_MB_SECONDS, (int)(($spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT))) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT))) + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT))) ; $execution = Authorization::skip(fn () => $dbForProject->createDocument('executions', $execution)); @@ -2533,7 +2533,7 @@ App::post('/v1/functions/:functionId/variables') Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'resourceInternalId' => $function->getInternalId(), + 'resourceInternalId' => $function->getSequence(), 'resourceId' => $function->getId(), 'resourceType' => 'function', 'key' => $key, @@ -2635,7 +2635,7 @@ App::get('/v1/functions/:functionId/variables/:variableId') if ( $variable === false || $variable->isEmpty() || - $variable->getAttribute('resourceInternalId') !== $function->getInternalId() || + $variable->getAttribute('resourceInternalId') !== $function->getSequence() || $variable->getAttribute('resourceType') !== 'function' ) { throw new Exception(Exception::VARIABLE_NOT_FOUND); @@ -2684,7 +2684,7 @@ App::put('/v1/functions/:functionId/variables/:variableId') } $variable = $dbForProject->getDocument('variables', $variableId); - if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $function->getInternalId() || $variable->getAttribute('resourceType') !== 'function') { + if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $function->getSequence() || $variable->getAttribute('resourceType') !== 'function') { throw new Exception(Exception::VARIABLE_NOT_FOUND); } @@ -2750,7 +2750,7 @@ App::delete('/v1/functions/:functionId/variables/:variableId') } $variable = $dbForProject->getDocument('variables', $variableId); - if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $function->getInternalId() || $variable->getAttribute('resourceType') !== 'function') { + if ($variable === false || $variable->isEmpty() || $variable->getAttribute('resourceInternalId') !== $function->getSequence() || $variable->getAttribute('resourceType') !== 'function') { throw new Exception(Exception::VARIABLE_NOT_FOUND); } diff --git a/app/controllers/api/messaging.php b/app/controllers/api/messaging.php index 1d11e6c392..0bc6f93787 100644 --- a/app/controllers/api/messaging.php +++ b/app/controllers/api/messaging.php @@ -2511,11 +2511,11 @@ App::post('/v1/messaging/topics/:topicId/subscribers') Permission::delete(Role::user($user->getId())), ], 'topicId' => $topicId, - 'topicInternalId' => $topic->getInternalId(), + 'topicInternalId' => $topic->getSequence(), 'targetId' => $targetId, - 'targetInternalId' => $target->getInternalId(), + 'targetInternalId' => $target->getSequence(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'providerType' => $target->getAttribute('providerType'), 'search' => implode(' ', [ $subscriberId, @@ -2597,7 +2597,7 @@ App::get('/v1/messaging/topics/:topicId/subscribers') throw new Exception(Exception::TOPIC_NOT_FOUND); } - $queries[] = Query::equal('topicInternalId', [$topic->getInternalId()]); + $queries[] = Query::equal('topicInternalId', [$topic->getSequence()]); /** * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries @@ -2947,7 +2947,7 @@ App::post('/v1/messaging/messages/email') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -2989,7 +2989,7 @@ App::post('/v1/messaging/messages/email') 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), - 'resourceInternalId' => $message->getInternalId(), + 'resourceInternalId' => $message->getSequence(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -3112,7 +3112,7 @@ App::post('/v1/messaging/messages/sms') 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), - 'resourceInternalId' => $message->getInternalId(), + 'resourceInternalId' => $message->getSequence(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -3232,7 +3232,7 @@ App::post('/v1/messaging/messages/push') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -3330,7 +3330,7 @@ App::post('/v1/messaging/messages/push') 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), - 'resourceInternalId' => $message->getInternalId(), + 'resourceInternalId' => $message->getSequence(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -3731,7 +3731,7 @@ App::patch('/v1/messaging/messages/email/:messageId') 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), - 'resourceInternalId' => $message->getInternalId(), + 'resourceInternalId' => $message->getSequence(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -3796,7 +3796,7 @@ App::patch('/v1/messaging/messages/email/:messageId') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -3933,7 +3933,7 @@ App::patch('/v1/messaging/messages/sms/:messageId') 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), - 'resourceInternalId' => $message->getInternalId(), + 'resourceInternalId' => $message->getSequence(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -4107,7 +4107,7 @@ App::patch('/v1/messaging/messages/push/:messageId') 'region' => $project->getAttribute('region'), 'resourceType' => 'message', 'resourceId' => $message->getId(), - 'resourceInternalId' => $message->getInternalId(), + 'resourceInternalId' => $message->getSequence(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $project->getId(), 'schedule' => $scheduledAt, @@ -4210,7 +4210,7 @@ App::patch('/v1/messaging/messages/push/:messageId') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } diff --git a/app/controllers/api/project.php b/app/controllers/api/project.php index ae6c58e4f5..a9215eb20a 100644 --- a/app/controllers/api/project.php +++ b/app/controllers/api/project.php @@ -149,7 +149,7 @@ App::get('/v1/project/usage') $executionsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS); + $metric = str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_EXECUTIONS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -165,7 +165,7 @@ App::get('/v1/project/usage') $executionsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS); + $metric = str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -181,7 +181,7 @@ App::get('/v1/project/usage') $buildsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS); + $metric = str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -197,7 +197,7 @@ App::get('/v1/project/usage') $bucketsBreakdown = array_map(function ($bucket) use ($dbForProject) { $id = $bucket->getId(); $name = $bucket->getAttribute('name'); - $metric = str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE); + $metric = str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_STORAGE); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -213,7 +213,7 @@ App::get('/v1/project/usage') $databasesStorageBreakdown = array_map(function ($database) use ($dbForProject) { $id = $database->getId(); $name = $database->getAttribute('name'); - $metric = str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_STORAGE); + $metric = str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_STORAGE); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), @@ -230,13 +230,13 @@ App::get('/v1/project/usage') $functionsStorageBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $deploymentMetric = str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $function->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE); + $deploymentMetric = str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $function->getSequence()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE); $deploymentValue = $dbForProject->findOne('stats', [ Query::equal('metric', [$deploymentMetric]), Query::equal('period', ['inf']) ]); - $buildMetric = str_replace(['{functionInternalId}'], [$function->getInternalId()], METRIC_FUNCTION_ID_BUILDS_STORAGE); + $buildMetric = str_replace(['{functionInternalId}'], [$function->getSequence()], METRIC_FUNCTION_ID_BUILDS_STORAGE); $buildValue = $dbForProject->findOne('stats', [ Query::equal('metric', [$buildMetric]), Query::equal('period', ['inf']) @@ -254,7 +254,7 @@ App::get('/v1/project/usage') $executionsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS); + $metric = str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) @@ -270,7 +270,7 @@ App::get('/v1/project/usage') $buildsMbSecondsBreakdown = array_map(function ($function) use ($dbForProject) { $id = $function->getId(); $name = $function->getAttribute('name'); - $metric = str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS); + $metric = str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS); $value = $dbForProject->findOne('stats', [ Query::equal('metric', [$metric]), Query::equal('period', ['inf']) diff --git a/app/controllers/api/projects.php b/app/controllers/api/projects.php index c4f0b6a9df..7d74bd0497 100644 --- a/app/controllers/api/projects.php +++ b/app/controllers/api/projects.php @@ -182,7 +182,7 @@ App::post('/v1/projects') Permission::delete(Role::team(ID::custom($teamId), 'developer')), ], 'name' => $name, - 'teamInternalId' => $team->getInternalId(), + 'teamInternalId' => $team->getSequence(), 'teamId' => $team->getId(), 'region' => $region, 'description' => $description, @@ -230,13 +230,13 @@ App::post('/v1/projects') if ($sharedTables) { $dbForProject ->setSharedTables(true) - ->setTenant($sharedTablesV1 ? $project->getInternalId() : null) + ->setTenant($sharedTablesV1 ? $project->getSequence() : null) ->setNamespace($dsn->getParam('namespace')); } else { $dbForProject ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); + ->setNamespace('_' . $project->getSequence()); } $create = true; @@ -504,12 +504,12 @@ App::patch('/v1/projects/:projectId/team') $project ->setAttribute('teamId', $teamId) - ->setAttribute('teamInternalId', $team->getInternalId()) + ->setAttribute('teamInternalId', $team->getSequence()) ->setAttribute('$permissions', $permissions); $project = $dbForPlatform->updateDocument('projects', $project->getId(), $project); $installations = $dbForPlatform->find('installations', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); foreach ($installations as $installation) { $installation->getAttribute('$permissions', $permissions); @@ -517,7 +517,7 @@ App::patch('/v1/projects/:projectId/team') } $repositories = $dbForPlatform->find('repositories', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); foreach ($repositories as $repository) { $repository->getAttribute('$permissions', $permissions); @@ -525,7 +525,7 @@ App::patch('/v1/projects/:projectId/team') } $vcsComments = $dbForPlatform->find('vcsComments', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); foreach ($vcsComments as $vcsComment) { $vcsComment->getAttribute('$permissions', $permissions); @@ -1229,7 +1229,7 @@ App::post('/v1/projects/:projectId/webhooks') Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'projectId' => $project->getId(), 'name' => $name, 'events' => $events, @@ -1279,7 +1279,7 @@ App::get('/v1/projects/:projectId/webhooks') } $webhooks = $dbForPlatform->find('webhooks', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), Query::limit(5000), ]); @@ -1320,7 +1320,7 @@ App::get('/v1/projects/:projectId/webhooks/:webhookId') $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($webhook->isEmpty()) { @@ -1370,7 +1370,7 @@ App::put('/v1/projects/:projectId/webhooks/:webhookId') $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($webhook->isEmpty()) { @@ -1427,7 +1427,7 @@ App::patch('/v1/projects/:projectId/webhooks/:webhookId/signature') $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($webhook->isEmpty()) { @@ -1474,7 +1474,7 @@ App::delete('/v1/projects/:projectId/webhooks/:webhookId') $webhook = $dbForPlatform->findOne('webhooks', [ Query::equal('$id', [$webhookId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($webhook->isEmpty()) { @@ -1528,7 +1528,7 @@ App::post('/v1/projects/:projectId/keys') Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'projectId' => $project->getId(), 'name' => $name, 'scopes' => $scopes, @@ -1576,7 +1576,7 @@ App::get('/v1/projects/:projectId/keys') } $keys = $dbForPlatform->find('keys', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), Query::limit(5000), ]); @@ -1617,7 +1617,7 @@ App::get('/v1/projects/:projectId/keys/:keyId') $key = $dbForPlatform->findOne('keys', [ Query::equal('$id', [$keyId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($key->isEmpty()) { @@ -1661,7 +1661,7 @@ App::put('/v1/projects/:projectId/keys/:keyId') $key = $dbForPlatform->findOne('keys', [ Query::equal('$id', [$keyId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($key->isEmpty()) { @@ -1712,7 +1712,7 @@ App::delete('/v1/projects/:projectId/keys/:keyId') $key = $dbForPlatform->findOne('keys', [ Query::equal('$id', [$keyId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($key->isEmpty()) { @@ -1811,7 +1811,7 @@ App::post('/v1/projects/:projectId/platforms') Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'projectId' => $project->getId(), 'type' => $type, 'name' => $name, @@ -1858,7 +1858,7 @@ App::get('/v1/projects/:projectId/platforms') } $platforms = $dbForPlatform->find('platforms', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), Query::limit(5000), ]); @@ -1899,7 +1899,7 @@ App::get('/v1/projects/:projectId/platforms/:platformId') $platform = $dbForPlatform->findOne('platforms', [ Query::equal('$id', [$platformId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($platform->isEmpty()) { @@ -1943,7 +1943,7 @@ App::put('/v1/projects/:projectId/platforms/:platformId') $platform = $dbForPlatform->findOne('platforms', [ Query::equal('$id', [$platformId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($platform->isEmpty()) { @@ -1997,7 +1997,7 @@ App::delete('/v1/projects/:projectId/platforms/:platformId') $platform = $dbForPlatform->findOne('platforms', [ Query::equal('$id', [$platformId]), - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), ]); if ($platform->isEmpty()) { diff --git a/app/controllers/api/proxy.php b/app/controllers/api/proxy.php index cb3b249d8d..0fbbcc938d 100644 --- a/app/controllers/api/proxy.php +++ b/app/controllers/api/proxy.php @@ -121,7 +121,7 @@ App::post('/v1/proxy/rules') throw new Exception(Exception::RULE_RESOURCE_NOT_FOUND); } - $resourceInternalId = $function->getInternalId(); + $resourceInternalId = $function->getSequence(); } try { @@ -136,7 +136,7 @@ App::post('/v1/proxy/rules') $rule = new Document([ '$id' => $ruleId, 'projectId' => $project->getId(), - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'domain' => $domain->get(), 'resourceType' => $resourceType, 'resourceId' => $resourceId, @@ -212,7 +212,7 @@ App::get('/v1/proxy/rules') $queries[] = Query::search('search', $search); } - $queries[] = Query::equal('projectInternalId', [$project->getInternalId()]); + $queries[] = Query::equal('projectInternalId', [$project->getSequence()]); /** * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries @@ -278,7 +278,7 @@ App::get('/v1/proxy/rules/:ruleId') ->action(function (string $ruleId, Response $response, Document $project, Database $dbForPlatform) { $rule = $dbForPlatform->getDocument('rules', $ruleId); - if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getInternalId()) { + if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getSequence()) { throw new Exception(Exception::RULE_NOT_FOUND); } @@ -319,7 +319,7 @@ App::delete('/v1/proxy/rules/:ruleId') ->action(function (string $ruleId, Response $response, Document $project, Database $dbForPlatform, Delete $queueForDeletes, Event $queueForEvents) { $rule = $dbForPlatform->getDocument('rules', $ruleId); - if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getInternalId()) { + if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getSequence()) { throw new Exception(Exception::RULE_NOT_FOUND); } @@ -364,7 +364,7 @@ App::patch('/v1/proxy/rules/:ruleId/verification') ->action(function (string $ruleId, Response $response, Certificate $queueForCertificates, Event $queueForEvents, Document $project, Database $dbForPlatform, Log $log) { $rule = $dbForPlatform->getDocument('rules', $ruleId); - if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getInternalId()) { + if ($rule->isEmpty() || $rule->getAttribute('projectInternalId') !== $project->getSequence()) { throw new Exception(Exception::RULE_NOT_FOUND); } diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index 4a158bb68e..47f7483f94 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -145,7 +145,7 @@ App::post('/v1/storage/buckets') $bucket = $dbForProject->getDocument('buckets', $bucketId); - $dbForProject->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes, permissions: $permissions ?? [], documentSecurity: $fileSecurity); + $dbForProject->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes, permissions: $permissions ?? [], documentSecurity: $fileSecurity); } catch (DuplicateException) { throw new Exception(Exception::STORAGE_BUCKET_ALREADY_EXISTS); } @@ -326,7 +326,7 @@ App::put('/v1/storage/buckets/:bucketId') ->setAttribute('compression', $compression) ->setAttribute('antivirus', $antivirus)); - $dbForProject->updateCollection('bucket_' . $bucket->getInternalId(), $permissions, $fileSecurity); + $dbForProject->updateCollection('bucket_' . $bucket->getSequence(), $permissions, $fileSecurity); $queueForEvents ->setParam('bucketId', $bucket->getId()); @@ -558,7 +558,7 @@ App::post('/v1/storage/buckets/:bucketId/files') $path = $deviceForFiles->getPath($fileId . '.' . \pathinfo($fileName, PATHINFO_EXTENSION)); $path = str_ireplace($deviceForFiles->getRoot(), $deviceForFiles->getRoot() . DIRECTORY_SEPARATOR . $bucket->getId(), $path); // Add bucket id to path after root - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); $metadata = ['content_type' => $deviceForLocal->getFileMimeType($fileTmpName)]; if (!$file->isEmpty()) { @@ -652,7 +652,7 @@ App::post('/v1/storage/buckets/:bucketId/files') '$id' => $fileId, '$permissions' => $permissions, 'bucketId' => $bucket->getId(), - 'bucketInternalId' => $bucket->getInternalId(), + 'bucketInternalId' => $bucket->getSequence(), 'name' => $fileName, 'path' => $path, 'signature' => $fileHash, @@ -671,7 +671,7 @@ App::post('/v1/storage/buckets/:bucketId/files') 'metadata' => $metadata, ]); - $file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc); + $file = $dbForProject->createDocument('bucket_' . $bucket->getSequence(), $doc); } else { $file = $file ->setAttribute('$permissions', $permissions) @@ -696,7 +696,7 @@ App::post('/v1/storage/buckets/:bucketId/files') if (!$validator->isValid($bucket->getCreate())) { throw new Exception(Exception::USER_UNAUTHORIZED); } - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file)); + $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } } else { if ($file->isEmpty()) { @@ -704,7 +704,7 @@ App::post('/v1/storage/buckets/:bucketId/files') '$id' => ID::custom($fileId), '$permissions' => $permissions, 'bucketId' => $bucket->getId(), - 'bucketInternalId' => $bucket->getInternalId(), + 'bucketInternalId' => $bucket->getSequence(), 'name' => $fileName, 'path' => $path, 'signature' => '', @@ -720,7 +720,7 @@ App::post('/v1/storage/buckets/:bucketId/files') ]); try { - $file = $dbForProject->createDocument('bucket_' . $bucket->getInternalId(), $doc); + $file = $dbForProject->createDocument('bucket_' . $bucket->getSequence(), $doc); } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -741,7 +741,7 @@ App::post('/v1/storage/buckets/:bucketId/files') } try { - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file)); + $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } @@ -826,9 +826,9 @@ App::get('/v1/storage/buckets/:bucketId/files') $fileId = $cursor->getValue(); if ($fileSecurity && !$valid) { - $cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $cursorDocument = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $cursorDocument = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($cursorDocument->isEmpty()) { @@ -842,11 +842,11 @@ App::get('/v1/storage/buckets/:bucketId/files') try { if ($fileSecurity && !$valid) { - $files = $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries); - $total = $dbForProject->count('bucket_' . $bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT); + $files = $dbForProject->find('bucket_' . $bucket->getSequence(), $queries); + $total = $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT); } else { - $files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getInternalId(), $queries)); - $total = Authorization::skip(fn () => $dbForProject->count('bucket_' . $bucket->getInternalId(), $filterQueries, APP_LIMIT_COUNT)); + $files = Authorization::skip(fn () => $dbForProject->find('bucket_' . $bucket->getSequence(), $queries)); + $total = Authorization::skip(fn () => $dbForProject->count('bucket_' . $bucket->getSequence(), $filterQueries, APP_LIMIT_COUNT)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -902,9 +902,9 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId') } if ($fileSecurity && !$valid) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($file->isEmpty()) { @@ -978,9 +978,9 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') } if ($fileSecurity && !$valid) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($file->isEmpty()) { @@ -1147,9 +1147,9 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') } if ($fileSecurity && !$valid) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($file->isEmpty()) { @@ -1298,9 +1298,9 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') } if ($fileSecurity && !$valid) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($file->isEmpty()) { @@ -1454,7 +1454,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); } - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -1619,7 +1619,7 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') } // Read permission should not be required for update - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -1665,9 +1665,9 @@ App::put('/v1/storage/buckets/:bucketId/files/:fileId') try { if ($fileSecurity && !$valid) { - $file = $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file); + $file = $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file); } else { - $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getInternalId(), $fileId, $file)); + $file = Authorization::skip(fn () => $dbForProject->updateDocument('bucket_' . $bucket->getSequence(), $fileId, $file)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -1733,7 +1733,7 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') } // Read permission should not be required for delete - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); if ($file->isEmpty()) { throw new Exception(Exception::STORAGE_FILE_NOT_FOUND); @@ -1763,9 +1763,9 @@ App::delete('/v1/storage/buckets/:bucketId/files/:fileId') try { if ($fileSecurity && !$valid) { - $deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId); + $deleted = $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $deleted = Authorization::skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $deleted = Authorization::skip(fn () => $dbForProject->deleteDocument('bucket_' . $bucket->getSequence(), $fileId)); } } catch (NotFoundException) { throw new Exception(Exception::STORAGE_BUCKET_NOT_FOUND); @@ -1912,14 +1912,14 @@ App::get('/v1/storage/:bucketId/usage') $stats = $usage = []; $days = $periods[$range]; $metrics = [ - str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES), - str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE), - str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED), + str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES), + str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_STORAGE), + str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED), ]; Authorization::skip(function () use ($dbForProject, $dbForLogs, $bucket, $days, $metrics, &$stats) { foreach ($metrics as $metric) { - $db = ($metric === str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED)) + $db = ($metric === str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED)) ? $dbForLogs : $dbForProject; diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 9c383803f2..00e24b5c12 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -122,9 +122,9 @@ App::post('/v1/teams') Permission::delete(Role::team($team->getId(), 'owner')), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'teamId' => $team->getId(), - 'teamInternalId' => $team->getInternalId(), + 'teamInternalId' => $team->getSequence(), 'roles' => $roles, 'invited' => DateTime::now(), 'joined' => DateTime::now(), @@ -594,8 +594,8 @@ App::post('/v1/teams/:teamId/memberships') } $membership = $dbForProject->findOne('memberships', [ - Query::equal('userInternalId', [$invitee->getInternalId()]), - Query::equal('teamInternalId', [$team->getInternalId()]), + Query::equal('userInternalId', [$invitee->getSequence()]), + Query::equal('teamInternalId', [$team->getSequence()]), ]); $secret = Auth::tokenGenerator(); @@ -611,9 +611,9 @@ App::post('/v1/teams/:teamId/memberships') Permission::delete(Role::team($team->getId(), 'owner')), ], 'userId' => $invitee->getId(), - 'userInternalId' => $invitee->getInternalId(), + 'userInternalId' => $invitee->getSequence(), 'teamId' => $team->getId(), - 'teamInternalId' => $team->getInternalId(), + 'teamInternalId' => $team->getSequence(), 'roles' => $roles, 'invited' => DateTime::now(), 'joined' => ($isPrivilegedUser || $isAppUser) ? DateTime::now() : null, @@ -841,7 +841,7 @@ App::get('/v1/teams/:teamId/memberships') } // Set internal queries - $queries[] = Query::equal('teamInternalId', [$team->getInternalId()]); + $queries[] = Query::equal('teamInternalId', [$team->getSequence()]); /** * Get cursor document if there was a cursor query, we use array_filter and reset for reference $cursor to $queries @@ -1091,7 +1091,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') collection: 'memberships', queries: [ Query::contains('roles', ['owner']), - Query::equal('teamInternalId', [$team->getInternalId()]) + Query::equal('teamInternalId', [$team->getSequence()]) ], max: 2 ); @@ -1179,7 +1179,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') throw new Exception(Exception::TEAM_NOT_FOUND); } - if ($membership->getAttribute('teamInternalId') !== $team->getInternalId()) { + if ($membership->getAttribute('teamInternalId') !== $team->getSequence()) { throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH); } @@ -1196,7 +1196,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') $user->setAttributes($dbForProject->getDocument('users', $userId)->getArrayCopy()); // Get user } - if ($membership->getAttribute('userInternalId') !== $user->getInternalId()) { + if ($membership->getAttribute('userInternalId') !== $user->getSequence()) { throw new Exception(Exception::TEAM_INVITE_MISMATCH, 'Invite does not belong to current user (' . $user->getAttribute('email') . ')'); } @@ -1228,7 +1228,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId/status') Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'provider' => Auth::SESSION_PROVIDER_EMAIL, 'providerUid' => $user->getAttribute('email'), 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak @@ -1337,7 +1337,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') throw new Exception(Exception::TEAM_NOT_FOUND); } - if ($membership->getAttribute('teamInternalId') !== $team->getInternalId()) { + if ($membership->getAttribute('teamInternalId') !== $team->getSequence()) { throw new Exception(Exception::TEAM_MEMBERSHIP_MISMATCH); } diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index bf2435936a..4e75f24c56 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -139,7 +139,7 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'providerType' => 'email', 'identifier' => $email, ])); @@ -163,7 +163,7 @@ function createUser(string $hash, mixed $hashOptions, string $userId, ?string $e Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'providerType' => 'sms', 'identifier' => $phone, ])); @@ -563,10 +563,10 @@ App::post('/v1/users/:userId/targets') Permission::delete(Role::user($user->getId())), ], 'providerId' => empty($provider->getId()) ? null : $provider->getId(), - 'providerInternalId' => $provider->isEmpty() ? null : $provider->getInternalId(), + 'providerInternalId' => $provider->isEmpty() ? null : $provider->getSequence(), 'providerType' => $providerType, 'userId' => $userId, - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'identifier' => $identifier, 'name' => ($name !== '') ? $name : null, ])); @@ -894,7 +894,7 @@ App::get('/v1/users/:userId/logs') $audit = new Audit($dbForProject); - $logs = $audit->getLogsByUser($user->getInternalId(), $queries); + $logs = $audit->getLogsByUser($user->getSequence(), $queries); $output = []; @@ -941,7 +941,7 @@ App::get('/v1/users/:userId/logs') } $response->dynamic(new Document([ - 'total' => $audit->countLogsByUser($user->getInternalId(), $queries), + 'total' => $audit->countLogsByUser($user->getSequence(), $queries), 'logs' => $output, ]), Response::MODEL_LOG_LIST); }); @@ -1380,7 +1380,7 @@ App::patch('/v1/users/:userId/email') // Makes sure this email is not already used in another identity $identityWithMatchingEmail = $dbForProject->findOne('identities', [ Query::equal('providerEmail', [$email]), - Query::notEqual('userInternalId', $user->getInternalId()), + Query::notEqual('userInternalId', $user->getSequence()), ]); if (!$identityWithMatchingEmail->isEmpty()) { throw new Exception(Exception::USER_EMAIL_ALREADY_EXISTS); @@ -1424,7 +1424,7 @@ App::patch('/v1/users/:userId/email') Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'providerType' => 'email', 'identifier' => $email, ])); @@ -1513,7 +1513,7 @@ App::patch('/v1/users/:userId/phone') Permission::delete(Role::user($user->getId())), ], 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'providerType' => 'sms', 'identifier' => $number, ])); @@ -1695,7 +1695,7 @@ App::patch('/v1/users/:userId/targets/:targetId') $target ->setAttribute('providerId', $provider->getId()) - ->setAttribute('providerInternalId', $provider->getInternalId()); + ->setAttribute('providerInternalId', $provider->getSequence()); } if ($name) { @@ -2035,7 +2035,7 @@ App::post('/v1/users/:userId/sessions') [ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'provider' => Auth::SESSION_PROVIDER_SERVER, 'secret' => Auth::hash($secret), // One way hash encryption to protect DB leak 'userAgent' => $request->getUserAgent('UNKNOWN'), @@ -2115,7 +2115,7 @@ App::post('/v1/users/:userId/tokens') $token = new Document([ '$id' => ID::unique(), 'userId' => $user->getId(), - 'userInternalId' => $user->getInternalId(), + 'userInternalId' => $user->getSequence(), 'type' => Auth::TOKEN_TYPE_GENERIC, 'secret' => Auth::hash($secret), 'expire' => $expire, @@ -2277,8 +2277,8 @@ App::delete('/v1/users/:userId') $clone = clone $user; $dbForProject->deleteDocument('users', $userId); - DeleteIdentities::delete($dbForProject, Query::equal('userInternalId', [$user->getInternalId()])); - DeleteTargets::delete($dbForProject, Query::equal('userInternalId', [$user->getInternalId()])); + DeleteIdentities::delete($dbForProject, Query::equal('userInternalId', [$user->getSequence()])); + DeleteTargets::delete($dbForProject, Query::equal('userInternalId', [$user->getSequence()])); $queueForDeletes ->setType(DELETE_TYPE_DOCUMENT) diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index d94279beac..03d9f7b736 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -64,11 +64,11 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $functionId = $resource->getAttribute('resourceId'); $function = Authorization::skip(fn () => $dbForProject->getDocument('functions', $functionId)); - $functionInternalId = $function->getInternalId(); + $functionInternalId = $function->getSequence(); $deploymentId = ID::unique(); $repositoryId = $resource->getId(); - $repositoryInternalId = $resource->getInternalId(); + $repositoryInternalId = $resource->getSequence(); $providerRepositoryId = $resource->getAttribute('providerRepositoryId'); $installationId = $resource->getAttribute('installationId'); $installationInternalId = $resource->getAttribute('installationInternalId'); @@ -142,7 +142,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId ], 'installationInternalId' => $installationInternalId, 'installationId' => $installationId, - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'projectId' => $project->getId(), 'providerRepositoryId' => $providerRepositoryId, 'providerBranch' => $providerBranch, @@ -376,7 +376,7 @@ App::get('/v1/vcs/github/callback') $github->initializeVariables($providerInstallationId, $privateKey, $githubAppId); $owner = $github->getOwnerName($providerInstallationId) ?? ''; - $projectInternalId = $project->getInternalId(); + $projectInternalId = $project->getSequence(); $installation = $dbForPlatform->findOne('installations', [ Query::equal('providerInstallationId', [$providerInstallationId]), @@ -740,7 +740,7 @@ App::post('/v1/vcs/github/installations/:installationId/providerRepositories') if (empty($accessToken) || empty($refreshToken) || empty($accessTokenExpiry)) { $identity = $dbForPlatform->findOne('identities', [ Query::equal('provider', ['github']), - Query::equal('userInternalId', [$user->getInternalId()]), + Query::equal('userInternalId', [$user->getSequence()]), ]); if ($identity->isEmpty()) { throw new Exception(Exception::USER_IDENTITY_NOT_FOUND); @@ -987,7 +987,7 @@ App::post('/v1/vcs/github/events') foreach ($installations as $installation) { $repositories = Authorization::skip(fn () => $dbForPlatform->find('repositories', [ - Query::equal('installationInternalId', [$installation->getInternalId()]), + Query::equal('installationInternalId', [$installation->getSequence()]), Query::limit(1000) ])); @@ -1090,7 +1090,7 @@ App::get('/v1/vcs/installations') throw new Exception(Exception::GENERAL_QUERY_INVALID, $e->getMessage()); } - $queries[] = Query::equal('projectInternalId', [$project->getInternalId()]); + $queries[] = Query::equal('projectInternalId', [$project->getSequence()]); if (!empty($search)) { $queries[] = Query::search('search', $search); @@ -1163,7 +1163,7 @@ App::get('/v1/vcs/installations/:installationId') throw new Exception(Exception::INSTALLATION_NOT_FOUND); } - if ($installation->getAttribute('projectInternalId') !== $project->getInternalId()) { + if ($installation->getAttribute('projectInternalId') !== $project->getSequence()) { throw new Exception(Exception::INSTALLATION_NOT_FOUND); } @@ -1246,7 +1246,7 @@ App::patch('/v1/vcs/github/installations/:installationId/repositories/:repositor } $repository = Authorization::skip(fn () => $dbForPlatform->getDocument('repositories', $repositoryId, [ - Query::equal('projectInternalId', [$project->getInternalId()]) + Query::equal('projectInternalId', [$project->getSequence()]) ])); if ($repository->isEmpty()) { diff --git a/app/controllers/general.php b/app/controllers/general.php index 322787cbd0..ddb7e04ec1 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -268,9 +268,9 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw $execution = new Document([ '$id' => $executionId, '$permissions' => [], - 'functionInternalId' => $function->getInternalId(), + 'functionInternalId' => $function->getSequence(), 'functionId' => $function->getId(), - 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->getSequence(), 'deploymentId' => $deployment->getId(), 'trigger' => 'http', // http / schedule / event 'status' => 'processing', // waiting / processing / completed / failed @@ -446,11 +446,11 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw ->addMetric(METRIC_NETWORK_INBOUND, $request->getSize() + $fileSize) ->addMetric(METRIC_NETWORK_OUTBOUND, $response->getSize()) ->addMetric(METRIC_EXECUTIONS, 1) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), 1) + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_EXECUTIONS), 1) ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000)) // per project - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) // per function ->addMetric(METRIC_EXECUTIONS_MB_SECONDS, (int)(($spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT))) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT))) + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT))) ->setProject($project) ->trigger() ; @@ -604,7 +604,7 @@ App::init() 'resourceType' => 'api', 'status' => 'verifying', 'projectId' => $console->getId(), - 'projectInternalId' => $console->getInternalId(), + 'projectInternalId' => $console->getSequence(), 'owner' => $owner, 'region' => $console->getAttribute('region') ]); diff --git a/app/controllers/mock.php b/app/controllers/mock.php index 16d8e03841..fd7b9ab495 100644 --- a/app/controllers/mock.php +++ b/app/controllers/mock.php @@ -185,7 +185,7 @@ App::post('/v1/mock/api-key-unprefixed') Permission::update(Role::any()), Permission::delete(Role::any()), ], - 'projectInternalId' => $project->getInternalId(), + 'projectInternalId' => $project->getSequence(), 'projectId' => $project->getId(), 'name' => 'Outdated key', 'scopes' => $scopes, @@ -235,7 +235,7 @@ App::get('/v1/mock/github/callback') $github->initializeVariables($providerInstallationId, $privateKey, $githubAppId); $owner = $github->getOwnerName($providerInstallationId) ?? ''; - $projectInternalId = $project->getInternalId(); + $projectInternalId = $project->getSequence(); $teamId = $project->getAttribute('teamId', ''); diff --git a/app/controllers/shared/api.php b/app/controllers/shared/api.php index dfa070063c..86ea95c9b9 100644 --- a/app/controllers/shared/api.php +++ b/app/controllers/shared/api.php @@ -576,9 +576,9 @@ App::init() $fileId = $parts[1] ?? null; if ($fileSecurity && !$valid) { - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); } else { - $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId)); + $file = Authorization::skip(fn () => $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId)); } if ($file->isEmpty()) { diff --git a/app/http.php b/app/http.php index 4d78837a8a..547eed965c 100644 --- a/app/http.php +++ b/app/http.php @@ -307,7 +307,7 @@ $http->on(Constant::EVENT_START, function (Server $http) use ($payloadSize, $reg 'orders' => $index['orders'], ]), $files['indexes']); - $dbForPlatform->createCollection('bucket_' . $bucket->getInternalId(), $attributes, $indexes); + $dbForPlatform->createCollection('bucket_' . $bucket->getSequence(), $attributes, $indexes); } }); diff --git a/app/init/database/filters.php b/app/init/database/filters.php index 49d7845699..9e12f5f7f2 100644 --- a/app/init/database/filters.php +++ b/app/init/database/filters.php @@ -71,7 +71,7 @@ Database::addFilter( }, function (mixed $value, Document $document, Database $database) { $attributes = $database->find('attributes', [ - Query::equal('collectionInternalId', [$document->getInternalId()]), + Query::equal('collectionInternalId', [$document->getSequence()]), Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), Query::limit($database->getLimitForAttributes()), ]); @@ -107,7 +107,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return $database ->find('indexes', [ - Query::equal('collectionInternalId', [$document->getInternalId()]), + Query::equal('collectionInternalId', [$document->getSequence()]), Query::equal('databaseInternalId', [$document->getAttribute('databaseInternalId')]), Query::limit($database->getLimitForIndexes()), ]); @@ -122,7 +122,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return $database ->find('platforms', [ - Query::equal('projectInternalId', [$document->getInternalId()]), + Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ]); } @@ -136,7 +136,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return $database ->find('keys', [ - Query::equal('projectInternalId', [$document->getInternalId()]), + Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ]); } @@ -150,7 +150,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return $database ->find('webhooks', [ - Query::equal('projectInternalId', [$document->getInternalId()]), + Query::equal('projectInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ]); } @@ -163,7 +163,7 @@ Database::addFilter( }, function (mixed $value, Document $document, Database $database) { return Authorization::skip(fn () => $database->find('sessions', [ - Query::equal('userInternalId', [$document->getInternalId()]), + Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ])); } @@ -177,7 +177,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return Authorization::skip(fn () => $database ->find('tokens', [ - Query::equal('userInternalId', [$document->getInternalId()]), + Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ])); } @@ -191,7 +191,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return Authorization::skip(fn () => $database ->find('challenges', [ - Query::equal('userInternalId', [$document->getInternalId()]), + Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ])); } @@ -205,7 +205,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return Authorization::skip(fn () => $database ->find('authenticators', [ - Query::equal('userInternalId', [$document->getInternalId()]), + Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ])); } @@ -219,7 +219,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return Authorization::skip(fn () => $database ->find('memberships', [ - Query::equal('userInternalId', [$document->getInternalId()]), + Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY), ])); } @@ -233,7 +233,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return $database ->find('variables', [ - Query::equal('resourceInternalId', [$document->getInternalId()]), + Query::equal('resourceInternalId', [$document->getSequence()]), Query::equal('resourceType', ['function']), Query::limit(APP_LIMIT_SUBQUERY), ]); @@ -311,7 +311,7 @@ Database::addFilter( function (mixed $value, Document $document, Database $database) { return Authorization::skip(fn () => $database ->find('targets', [ - Query::equal('userInternalId', [$document->getInternalId()]), + Query::equal('userInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBQUERY) ])); } @@ -326,13 +326,13 @@ Database::addFilter( $targetIds = Authorization::skip(fn () => \array_map( fn ($document) => $document->getAttribute('targetInternalId'), $database->find('subscribers', [ - Query::equal('topicInternalId', [$document->getInternalId()]), + Query::equal('topicInternalId', [$document->getSequence()]), Query::limit(APP_LIMIT_SUBSCRIBERS_SUBQUERY) ]) )); if (\count($targetIds) > 0) { return $database->skipValidation(fn () => $database->find('targets', [ - Query::equal('$internalId', $targetIds) + Query::equal('$sequence', $targetIds) ])); } return []; diff --git a/app/init/resources.php b/app/init/resources.php index f48efbe177..8ff7fd081a 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -346,13 +346,13 @@ App::setResource('dbForProject', function (Group $pools, Database $dbForPlatform if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getInternalId()) + ->setTenant($project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); + ->setNamespace('_' . $project->getSequence()); } return $database; @@ -399,13 +399,13 @@ App::setResource('getProjectDB', function (Group $pools, Database $dbForPlatform if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getInternalId()) + ->setTenant($project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); + ->setNamespace('_' . $project->getSequence()); } }); @@ -429,7 +429,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) { return function (?Document $project = null) use ($pools, $cache, &$database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { - $database->setTenant($project->getInternalId()); + $database->setTenant($project->getSequence()); return $database; } @@ -444,7 +444,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) { // set tenant if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') { - $database->setTenant($project->getInternalId()); + $database->setTenant($project->getSequence()); } return $database; @@ -791,7 +791,7 @@ App::setResource('team', function (Document $project, Database $dbForPlatform, A $team = Authorization::skip(function () use ($dbForPlatform, $teamInternalId) { return $dbForPlatform->findOne('teams', [ - Query::equal('$internalId', [$teamInternalId]), + Query::equal('$sequence', [$teamInternalId]), ]); }); diff --git a/app/realtime.php b/app/realtime.php index 7e6fc0e311..96484c8a35 100644 --- a/app/realtime.php +++ b/app/realtime.php @@ -79,8 +79,8 @@ if (!function_exists('getProjectDB')) { static $databases = []; - if (isset($databases[$project->getInternalId()])) { - return $databases[$project->getInternalId()]; + if (isset($databases[$project->getSequence()])) { + return $databases[$project->getSequence()]; } /** @var Group $pools */ @@ -105,20 +105,20 @@ if (!function_exists('getProjectDB')) { if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getInternalId()) + ->setTenant($project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); + ->setNamespace('_' . $project->getSequence()); } $database ->setMetadata('host', \gethostname()) ->setMetadata('project', $project->getId()); - return $databases[$project->getInternalId()] = $database; + return $databases[$project->getSequence()] = $database; } } diff --git a/app/worker.php b/app/worker.php index 1ae2108a62..9fe428283b 100644 --- a/app/worker.php +++ b/app/worker.php @@ -89,13 +89,13 @@ Server::setResource('dbForProject', function (Cache $cache, Registry $register, if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getInternalId()) + ->setTenant($project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); + ->setNamespace('_' . $project->getSequence()); } $database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); @@ -126,13 +126,13 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getInternalId()) + ->setTenant($project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); + ->setNamespace('_' . $project->getSequence()); } return $database; @@ -148,13 +148,13 @@ Server::setResource('getProjectDB', function (Group $pools, Database $dbForPlatf if (\in_array($dsn->getHost(), $sharedTables)) { $database ->setSharedTables(true) - ->setTenant($project->getInternalId()) + ->setTenant($project->getSequence()) ->setNamespace($dsn->getParam('namespace')); } else { $database ->setSharedTables(false) ->setTenant(null) - ->setNamespace('_' . $project->getInternalId()); + ->setNamespace('_' . $project->getSequence()); } $database->setTimeout(APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER); @@ -167,7 +167,7 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) { $database = null; return function (?Document $project = null) use ($pools, $cache, $database) { if ($database !== null && $project !== null && !$project->isEmpty() && $project->getId() !== 'console') { - $database->setTenant($project->getInternalId()); + $database->setTenant($project->getSequence()); return $database; } @@ -182,7 +182,7 @@ Server::setResource('getLogsDB', function (Group $pools, Cache $cache) { // set tenant if ($project !== null && !$project->isEmpty() && $project->getId() !== 'console') { - $database->setTenant($project->getInternalId()); + $database->setTenant($project->getSequence()); } return $database; diff --git a/src/Appwrite/Deletes/Targets.php b/src/Appwrite/Deletes/Targets.php index 95e744ddf1..794ab0b87a 100644 --- a/src/Appwrite/Deletes/Targets.php +++ b/src/Appwrite/Deletes/Targets.php @@ -27,7 +27,7 @@ class Targets $database->deleteDocuments( 'subscribers', [ - Query::equal('targetInternalId', [$target->getInternalId()]), + Query::equal('targetInternalId', [$target->getSequence()]), Query::orderAsc(), ], Database::DELETE_BATCH_SIZE, @@ -35,7 +35,7 @@ class Targets $topicId = $subscriber->getAttribute('topicId'); $topicInternalId = $subscriber->getAttribute('topicInternalId'); $topic = $database->getDocument('topics', $topicId); - if (!$topic->isEmpty() && $topic->getInternalId() === $topicInternalId) { + if (!$topic->isEmpty() && $topic->getSequence() === $topicInternalId) { $totalAttribute = match ($target->getAttribute('providerType')) { MESSAGE_TYPE_EMAIL => 'emailTotal', MESSAGE_TYPE_SMS => 'smsTotal', diff --git a/src/Appwrite/Event/Event.php b/src/Appwrite/Event/Event.php index 2c735ef2d4..934647f7c3 100644 --- a/src/Appwrite/Event/Event.php +++ b/src/Appwrite/Event/Event.php @@ -320,7 +320,7 @@ class Event if ($this->project) { $trimmed['project'] = new Document([ '$id' => $this->project->getId(), - '$internalId' => $this->project->getInternalId(), + '$sequence' => $this->project->getSequence(), 'database' => $this->project->getAttribute('database') ]); } diff --git a/src/Appwrite/Migration/Migration.php b/src/Appwrite/Migration/Migration.php index 1e3625b5a3..f85554d0a4 100644 --- a/src/Appwrite/Migration/Migration.php +++ b/src/Appwrite/Migration/Migration.php @@ -164,7 +164,7 @@ abstract class Migration */ public function forEachDocument(callable $callback): void { - $internalProjectId = $this->project->getInternalId(); + $internalProjectId = $this->project->getSequence(); $collections = match ($internalProjectId) { 'console' => $this->collections['console'], @@ -256,7 +256,7 @@ abstract class Migration { $name ??= $id; - $collectionType = match ($this->project->getInternalId()) { + $collectionType = match ($this->project->getSequence()) { 'console' => 'console', default => 'projects', }; @@ -312,7 +312,7 @@ abstract class Migration { $from ??= $collectionId; - $collectionType = match ($this->project->getInternalId()) { + $collectionType = match ($this->project->getSequence()) { 'console' => 'console', default => 'projects', }; @@ -370,7 +370,7 @@ abstract class Migration { $from ??= $collectionId; - $collectionType = match ($this->project->getInternalId()) { + $collectionType = match ($this->project->getSequence()) { 'console' => 'console', default => 'projects', }; @@ -415,7 +415,7 @@ abstract class Migration */ protected function changeAttributeInternalType(string $collection, string $attribute, string $type): void { - $stmt = $this->pdo->prepare("ALTER TABLE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$collection}` MODIFY `$attribute` $type;"); + $stmt = $this->pdo->prepare("ALTER TABLE `{$this->projectDB->getDatabase()}`.`_{$this->project->getSequence()}_{$collection}` MODIFY `$attribute` $type;"); try { $stmt->execute(); diff --git a/src/Appwrite/Migration/Version/V15.php b/src/Appwrite/Migration/Version/V15.php index ca20b6d7b3..56fcc2a396 100644 --- a/src/Appwrite/Migration/Version/V15.php +++ b/src/Appwrite/Migration/Version/V15.php @@ -95,7 +95,7 @@ class V15 extends Migration $this->migrateStatsMetric('storage.files.delete', 'files.$all.requests.delete'); foreach ($this->documentsIterator('buckets') as $bucket) { - $bucketTable = "bucket_{$bucket->getInternalId()}"; + $bucketTable = "bucket_{$bucket->getSequence()}"; $this->createPermissionsColumn($bucketTable); $this->migrateDateTimeAttribute($bucketTable, '_createdAt'); @@ -178,7 +178,7 @@ class V15 extends Migration * Migrate every Database. */ foreach ($this->documentsIterator('databases') as $database) { - $databaseTable = "database_{$database->getInternalId()}"; + $databaseTable = "database_{$database->getSequence()}"; $this->createPermissionsColumn($databaseTable); $this->migrateDateTimeAttribute($databaseTable, '_createdAt'); $this->migrateDateTimeAttribute($databaseTable, '_updatedAt'); @@ -216,7 +216,7 @@ class V15 extends Migration */ Console::info("Migrating Collections of {$database->getId()} ({$database->getAttribute('name')})"); foreach ($this->documentsIterator($databaseTable) as $collection) { - $collectionTable = "{$databaseTable}_collection_{$collection->getInternalId()}"; + $collectionTable = "{$databaseTable}_collection_{$collection->getSequence()}"; $this->createPermissionsColumn($collectionTable); $this->migrateDateTimeAttribute($collectionTable, '_createdAt'); $this->migrateDateTimeAttribute($collectionTable, '_updatedAt'); @@ -277,7 +277,7 @@ class V15 extends Migration $this->removeWritePermissions($databaseTable); try { - $this->projectDB->deleteAttribute("database_{$database->getInternalId()}", 'permission'); + $this->projectDB->deleteAttribute("database_{$database->getSequence()}", 'permission'); } catch (\Throwable $th) { Console::warning("'permission' from {$databaseTable}: {$th->getMessage()}"); } @@ -293,7 +293,7 @@ class V15 extends Migration protected function removeWritePermissions(string $table): void { try { - $this->pdo->prepare("DELETE FROM `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}_perms` WHERE _type = 'write'")->execute(); + $this->pdo->prepare("DELETE FROM `{$this->projectDB->getDatabase()}`.`_{$this->project->getSequence()}_{$table}_perms` WHERE _type = 'write'")->execute(); } catch (\Throwable $th) { Console::warning("Remove 'write' permissions from {$table}: {$th->getMessage()}"); } @@ -309,7 +309,7 @@ class V15 extends Migration */ protected function getSQLColumnTypes(string $table): array { - $query = $this->pdo->prepare("SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '_{$this->project->getInternalId()}_{$table}' AND table_schema = '{$this->projectDB->getDatabase()}'"); + $query = $this->pdo->prepare("SELECT COLUMN_NAME, DATA_TYPE FROM INFORMATION_SCHEMA.COLUMNS WHERE table_name = '_{$this->project->getSequence()}_{$table}' AND table_schema = '{$this->projectDB->getDatabase()}'"); $query->execute(); return array_reduce($query->fetchAll(), function (array $carry, array $item) { @@ -331,8 +331,8 @@ class V15 extends Migration if ($columns[$attribute] === 'int') { try { - $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` MODIFY {$attribute} VARCHAR(64)")->execute(); - $this->pdo->prepare("UPDATE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` SET {$attribute} = IF({$attribute} = 0, NULL, FROM_UNIXTIME({$attribute}))")->execute(); + $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDatabase()}`.`_{$this->project->getSequence()}_{$table}` MODIFY {$attribute} VARCHAR(64)")->execute(); + $this->pdo->prepare("UPDATE `{$this->projectDB->getDatabase()}`.`_{$this->project->getSequence()}_{$table}` SET {$attribute} = IF({$attribute} = 0, NULL, FROM_UNIXTIME({$attribute}))")->execute(); $columns[$attribute] = 'varchar'; } catch (\Throwable $th) { Console::warning($th->getMessage()); @@ -341,7 +341,7 @@ class V15 extends Migration if ($columns[$attribute] === 'varchar') { try { - $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` MODIFY {$attribute} DATETIME(3)")->execute(); + $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDatabase()}`.`_{$this->project->getSequence()}_{$table}` MODIFY {$attribute} DATETIME(3)")->execute(); } catch (\Throwable $th) { Console::warning($th->getMessage()); } @@ -387,7 +387,7 @@ class V15 extends Migration if (!array_key_exists('_permissions', $columns)) { try { - $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}` ADD `_permissions` MEDIUMTEXT DEFAULT NULL")->execute(); + $this->pdo->prepare("ALTER TABLE IF EXISTS `{$this->projectDB->getDatabase()}`.`_{$this->project->getSequence()}_{$table}` ADD `_permissions` MEDIUMTEXT DEFAULT NULL")->execute(); } catch (\Throwable $th) { Console::warning("Add '_permissions' column to '{$table}': {$th->getMessage()}"); } @@ -408,7 +408,7 @@ class V15 extends Migration { $table ??= $document->getCollection(); - $query = $this->pdo->prepare("SELECT * FROM `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_{$table}_perms` WHERE _document = '{$document->getId()}'"); + $query = $this->pdo->prepare("SELECT * FROM `{$this->projectDB->getDatabase()}`.`_{$this->project->getSequence()}_{$table}_perms` WHERE _document = '{$document->getId()}'"); $query->execute(); $results = $query->fetchAll(); $permissions = []; @@ -466,7 +466,7 @@ class V15 extends Migration Console::log("Migrating Collection \"{$id}\""); - $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); + $this->projectDB->setNamespace("_{$this->project->getSequence()}"); switch ($id) { case '_metadata': @@ -746,7 +746,7 @@ class V15 extends Migration Permission::delete(Role::any()), ], 'functionId' => $function->getId(), - 'functionInternalId' => $function->getInternalId(), + 'functionInternalId' => $function->getSequence(), 'key' => (string) $key, 'value' => (string) $value, 'search' => implode(' ', [$variableId, $key, $function->getId()]) @@ -1470,9 +1470,9 @@ class V15 extends Migration $from = $this->pdo->quote($from); $to = $this->pdo->quote($to); - $this->pdo->prepare("UPDATE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_stats` SET metric = {$to} WHERE metric = {$from}")->execute(); + $this->pdo->prepare("UPDATE `{$this->projectDB->getDatabase()}`.`_{$this->project->getSequence()}_stats` SET metric = {$to} WHERE metric = {$from}")->execute(); } catch (\Throwable $th) { - Console::warning("Migrating steps from {$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}_stats:" . $th->getMessage()); + Console::warning("Migrating steps from {$this->projectDB->getDatabase()}`.`_{$this->project->getSequence()}_stats:" . $th->getMessage()); } } diff --git a/src/Appwrite/Migration/Version/V16.php b/src/Appwrite/Migration/Version/V16.php index 49f244598e..6826f94026 100644 --- a/src/Appwrite/Migration/Version/V16.php +++ b/src/Appwrite/Migration/Version/V16.php @@ -45,7 +45,7 @@ class V16 extends Migration Console::log("Migrating Collection \"{$id}\""); - $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); + $this->projectDB->setNamespace("_{$this->project->getSequence()}"); switch ($id) { case 'sessions': diff --git a/src/Appwrite/Migration/Version/V17.php b/src/Appwrite/Migration/Version/V17.php index 96c890c65d..22545550ee 100644 --- a/src/Appwrite/Migration/Version/V17.php +++ b/src/Appwrite/Migration/Version/V17.php @@ -44,7 +44,7 @@ class V17 extends Migration protected function migrateBuckets(): void { foreach ($this->documentsIterator('buckets') as $bucket) { - $id = "bucket_{$bucket->getInternalId()}"; + $id = "bucket_{$bucket->getSequence()}"; try { $this->projectDB->updateAttribute($id, 'mimeType', Database::VAR_STRING, 255, true, false); @@ -67,7 +67,7 @@ class V17 extends Migration Console::log("Migrating Collection \"{$id}\""); - $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); + $this->projectDB->setNamespace("_{$this->project->getSequence()}"); switch ($id) { case 'builds': diff --git a/src/Appwrite/Migration/Version/V18.php b/src/Appwrite/Migration/Version/V18.php index ac4093aaca..84e17f6b59 100644 --- a/src/Appwrite/Migration/Version/V18.php +++ b/src/Appwrite/Migration/Version/V18.php @@ -26,7 +26,7 @@ class V18 extends Migration } Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); - $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); + $this->projectDB->setNamespace("_{$this->project->getSequence()}"); $this->addDocumentSecurityToProject(); Console::info('Migrating Databases'); @@ -48,12 +48,12 @@ class V18 extends Migration private function migrateDatabases(): void { foreach ($this->documentsIterator('databases') as $database) { - $databaseTable = "database_{$database->getInternalId()}"; + $databaseTable = "database_{$database->getSequence()}"; Console::info("Migrating Collections of {$database->getId()} ({$database->getAttribute('name')})"); foreach ($this->documentsIterator($databaseTable) as $collection) { - $collectionTable = "{$databaseTable}_collection_{$collection->getInternalId()}"; + $collectionTable = "{$databaseTable}_collection_{$collection->getSequence()}"; foreach ($collection['attributes'] ?? [] as $attribute) { if ($attribute['type'] !== Database::VAR_FLOAT) { @@ -197,7 +197,7 @@ class V18 extends Migration * Set the bucket permission in the metadata table */ try { - $internalBucketId = "bucket_{$this->project->getInternalId()}"; + $internalBucketId = "bucket_{$this->project->getSequence()}"; $permissions = $document->getPermissions(); $fileSecurity = $document->getAttribute('fileSecurity', false); $this->projectDB->updateCollection($internalBucketId, $permissions, $fileSecurity); @@ -224,8 +224,8 @@ class V18 extends Migration // Nonetheless, there's nothing else we can do here. break; } - $internalId = $user->getInternalId(); - $document->setAttribute('userId', $internalId); + $sequence = $user->getSequence(); + $document->setAttribute('userId', $sequence); $data = $document->getAttribute('data', []); $data['userId'] = $user->getId(); $document->setAttribute('data', $data); @@ -244,7 +244,7 @@ class V18 extends Migration /** * Create 'documentSecurity' column */ - $this->pdo->prepare("ALTER TABLE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}__metadata` ADD COLUMN IF NOT EXISTS documentSecurity TINYINT(1);")->execute(); + $this->pdo->prepare("ALTER TABLE `{$this->projectDB->getDatabase()}`.`_{$this->project->getSequence()}__metadata` ADD COLUMN IF NOT EXISTS documentSecurity TINYINT(1);")->execute(); } catch (\Throwable $th) { Console::warning($th->getMessage()); } @@ -253,7 +253,7 @@ class V18 extends Migration /** * Set 'documentSecurity' column to 1 if NULL */ - $this->pdo->prepare("UPDATE `{$this->projectDB->getDatabase()}`.`_{$this->project->getInternalId()}__metadata` SET documentSecurity = 1 WHERE documentSecurity IS NULL")->execute(); + $this->pdo->prepare("UPDATE `{$this->projectDB->getDatabase()}`.`_{$this->project->getSequence()}__metadata` SET documentSecurity = 1 WHERE documentSecurity IS NULL")->execute(); } catch (\Throwable $th) { Console::warning($th->getMessage()); } diff --git a/src/Appwrite/Migration/Version/V19.php b/src/Appwrite/Migration/Version/V19.php index 4415003bfd..9559540b00 100644 --- a/src/Appwrite/Migration/Version/V19.php +++ b/src/Appwrite/Migration/Version/V19.php @@ -28,7 +28,7 @@ class V19 extends Migration } Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); - $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); + $this->projectDB->setNamespace("_{$this->project->getSequence()}"); Console::info('Migrating Collections'); $this->migrateCollections(); @@ -100,7 +100,7 @@ class V19 extends Migration protected function migrateBuckets(): void { foreach ($this->documentsIterator('buckets') as $bucket) { - $id = "bucket_{$bucket->getInternalId()}"; + $id = "bucket_{$bucket->getSequence()}"; Console::log("Migrating Bucket {$id} {$bucket->getId()} ({$bucket->getAttribute('name')})"); try { @@ -121,7 +121,7 @@ class V19 extends Migration */ private function migrateCollections(): void { - $internalProjectId = $this->project->getInternalId(); + $internalProjectId = $this->project->getSequence(); $collectionType = match ($internalProjectId) { 'console' => 'console', default => 'projects', @@ -680,7 +680,7 @@ class V19 extends Migration case 'builds': $deploymentId = $document->getAttribute('deploymentId'); $deployment = $this->projectDB->getDocument('deployments', $deploymentId); - $document->setAttribute('deploymentInternalId', $deployment->getInternalId()); + $document->setAttribute('deploymentInternalId', $deployment->getSequence()); $stdout = $document->getAttribute('stdout', ''); $stderr = $document->getAttribute('stderr', ''); @@ -692,12 +692,12 @@ class V19 extends Migration case 'deployments': $resourceId = $document->getAttribute('resourceId'); $function = $this->projectDB->getDocument('functions', $resourceId); - $document->setAttribute('resourceInternalId', $function->getInternalId()); + $document->setAttribute('resourceInternalId', $function->getSequence()); $buildId = $document->getAttribute('buildId'); if (!empty($buildId)) { $build = $this->projectDB->getDocument('builds', $buildId); - $document->setAttribute('buildInternalId', $build->getInternalId()); + $document->setAttribute('buildInternalId', $build->getSequence()); } $commands = $this->getFunctionCommands($function); @@ -707,11 +707,11 @@ class V19 extends Migration case 'executions': $functionId = $document->getAttribute('functionId'); $function = $this->projectDB->getDocument('functions', $functionId); - $document->setAttribute('functionInternalId', $function->getInternalId()); + $document->setAttribute('functionInternalId', $function->getSequence()); $deploymentId = $document->getAttribute('deploymentId'); $deployment = $this->projectDB->getDocument('deployments', $deploymentId); - $document->setAttribute('deploymentInternalId', $deployment->getInternalId()); + $document->setAttribute('deploymentInternalId', $deployment->getSequence()); break; case 'functions': $document->setAttribute('live', $document->getAttribute('live', true)); @@ -721,7 +721,7 @@ class V19 extends Migration if (!empty($deploymentId)) { $deployment = $this->projectDB->getDocument('deployments', $deploymentId); - $document->setAttribute('deploymentInternalId', $deployment->getInternalId()); + $document->setAttribute('deploymentInternalId', $deployment->getSequence()); $document->setAttribute('entrypoint', $deployment->getAttribute('entrypoint')); } @@ -733,7 +733,7 @@ class V19 extends Migration 'region' => $project->getAttribute('region'), 'resourceType' => 'function', 'resourceId' => $document->getId(), - 'resourceInternalId' => $document->getInternalId(), + 'resourceInternalId' => $document->getSequence(), 'resourceUpdatedAt' => DateTime::now(), 'projectId' => $this->project->getId(), 'schedule' => $document->getAttribute('schedule'), @@ -741,7 +741,7 @@ class V19 extends Migration ])); $document->setAttribute('scheduleId', $schedule->getId()); - $document->setAttribute('scheduleInternalId', $schedule->getInternalId()); + $document->setAttribute('scheduleInternalId', $schedule->getSequence()); } break; @@ -799,7 +799,7 @@ class V19 extends Migration */ public function forEachDocument(callable $callback): void { - $internalProjectId = $this->project->getInternalId(); + $internalProjectId = $this->project->getSequence(); $collections = match ($internalProjectId) { 'console' => $this->collections['console'], diff --git a/src/Appwrite/Migration/Version/V20.php b/src/Appwrite/Migration/Version/V20.php index 5a0807cedf..16f4e761b9 100644 --- a/src/Appwrite/Migration/Version/V20.php +++ b/src/Appwrite/Migration/Version/V20.php @@ -36,13 +36,13 @@ class V20 extends Migration } Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); - $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); + $this->projectDB->setNamespace("_{$this->project->getSequence()}"); Console::info('Migrating Collections'); $this->migrateCollections(); // No need to migrate stats for console - if ($this->project->getInternalId() !== 'console') { + if ($this->project->getSequence() !== 'console') { $this->migrateUsageMetrics('project.$all.network.requests', 'network.requests'); $this->migrateUsageMetrics('project.$all.network.outbound', 'network.outbound'); $this->migrateUsageMetrics('project.$all.network.inbound', 'network.inbound'); @@ -71,7 +71,7 @@ class V20 extends Migration */ private function migrateCollections(): void { - $internalProjectId = $this->project->getInternalId(); + $internalProjectId = $this->project->getSequence(); $collectionType = match ($internalProjectId) { 'console' => 'console', default => 'projects', @@ -510,7 +510,7 @@ class V20 extends Migration Console::log("Migrating Functions usage stats of {$function->getId()} ({$function->getAttribute('name')})"); $functionId = $function->getId(); - $functionInternalId = $function->getInternalId(); + $functionInternalId = $function->getSequence(); $this->migrateUsageMetrics("deployment.$functionId.storage.size", "function.$functionInternalId.deployments.storage"); $this->migrateUsageMetrics("builds.$functionId.compute.total", "$functionInternalId.builds"); @@ -536,22 +536,22 @@ class V20 extends Migration foreach ($this->documentsIterator('databases') as $database) { Console::log("Migrating Collections of {$database->getId()} ({$database->getAttribute('name')})"); - $databaseTable = "database_{$database->getInternalId()}"; + $databaseTable = "database_{$database->getSequence()}"; // Database level $databaseId = $database->getId(); - $databaseInternalId = $database->getInternalId(); + $databaseInternalId = $database->getSequence(); $this->migrateUsageMetrics("collections.$databaseId.count.total", "$databaseInternalId.collections"); $this->migrateUsageMetrics("documents.$databaseId.count.total", "$databaseInternalId.documents"); foreach ($this->documentsIterator($databaseTable) as $collection) { - $collectionTable = "{$databaseTable}_collection_{$collection->getInternalId()}"; + $collectionTable = "{$databaseTable}_collection_{$collection->getSequence()}"; Console::log("Migrating Collections of {$collectionTable} {$collection->getId()} ({$collection->getAttribute('name')})"); // Collection level $collectionId = $collection->getId(); - $collectionInternalId = $collection->getInternalId(); + $collectionInternalId = $collection->getSequence(); $this->migrateUsageMetrics("documents.$databaseId/$collectionId.count.total", "$databaseInternalId.$collectionInternalId.documents"); } @@ -573,12 +573,12 @@ class V20 extends Migration $this->migrateUsageMetrics('files.$all.storage.size', 'files.storage'); foreach ($this->documentsIterator('buckets') as $bucket) { - $id = "bucket_{$bucket->getInternalId()}"; + $id = "bucket_{$bucket->getSequence()}"; Console::log("Migrating Bucket {$id} {$bucket->getId()} ({$bucket->getAttribute('name')})"); // Bucket level $bucketId = $bucket->getId(); - $bucketInternalId = $bucket->getInternalId(); + $bucketInternalId = $bucket->getSequence(); $this->migrateUsageMetrics("files.$bucketId.count.total", "$bucketInternalId.files"); $this->migrateUsageMetrics("files.$bucketId.storage.size", "$bucketInternalId.files.storage"); @@ -605,7 +605,7 @@ class V20 extends Migration $target = new Document([ '$id' => ID::unique(), 'userId' => $document->getId(), - 'userInternalId' => $document->getInternalId(), + 'userInternalId' => $document->getSequence(), 'providerType' => MESSAGE_TYPE_EMAIL, 'identifier' => $document->getAttribute('email'), ]); @@ -620,7 +620,7 @@ class V20 extends Migration $target = new Document([ '$id' => ID::unique(), 'userId' => $document->getId(), - 'userInternalId' => $document->getInternalId(), + 'userInternalId' => $document->getSequence(), 'providerType' => MESSAGE_TYPE_SMS, 'identifier' => $document->getAttribute('phone'), ]); diff --git a/src/Appwrite/Migration/Version/V21.php b/src/Appwrite/Migration/Version/V21.php index c072c81a34..f874fbfd61 100644 --- a/src/Appwrite/Migration/Version/V21.php +++ b/src/Appwrite/Migration/Version/V21.php @@ -29,12 +29,12 @@ class V21 extends Migration } Console::log('Migrating Project: ' . $this->project->getAttribute('name') . ' (' . $this->project->getId() . ')'); - $this->projectDB->setNamespace("_{$this->project->getInternalId()}"); + $this->projectDB->setNamespace("_{$this->project->getSequence()}"); Console::info('Migrating Collections'); $this->migrateCollections(); - if ($this->project->getInternalId() !== 'console') { + if ($this->project->getSequence() !== 'console') { Console::info('Migrating Buckets'); $this->migrateBuckets(); } @@ -51,7 +51,7 @@ class V21 extends Migration */ private function migrateCollections(): void { - $internalProjectId = $this->project->getInternalId(); + $internalProjectId = $this->project->getSequence(); $collectionType = match ($internalProjectId) { 'console' => 'console', default => 'projects', @@ -251,7 +251,7 @@ class V21 extends Migration private function migrateBuckets(): void { foreach ($this->documentsIterator('buckets') as $bucket) { - $bucketId = 'bucket_' . $bucket['$internalId']; + $bucketId = 'bucket_' . $bucket['$sequence']; Console::log("Migrating Bucket {$bucketId} {$bucket->getId()} ({$bucket->getAttribute('name')})"); diff --git a/src/Appwrite/Platform/Tasks/Migrate.php b/src/Appwrite/Platform/Tasks/Migrate.php index e495ce1d3f..a80af27df4 100644 --- a/src/Appwrite/Platform/Tasks/Migrate.php +++ b/src/Appwrite/Platform/Tasks/Migrate.php @@ -41,7 +41,7 @@ class Migrate extends Action try { $iterator = null; do { - $pattern = "default-cache-_{$project->getInternalId()}:*"; + $pattern = "default-cache-_{$project->getSequence()}:*"; $keys = $this->redis->scan($iterator, $pattern, 1000); if ($keys !== false) { foreach ($keys as $key) { @@ -104,7 +104,7 @@ class Migrate extends Action /** * Skip user projects with id 'console' */ - if ($project->getId() === 'console' && $project->getInternalId() !== 'console') { + if ($project->getId() === 'console' && $project->getSequence() !== 'console') { continue; } diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index ea0476fc33..fdf05a360a 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -124,7 +124,7 @@ abstract class ScheduleBase extends Action ); return [ - '$internalId' => $schedule->getInternalId(), + '$sequence' => $schedule->getSequence(), '$id' => $schedule->getId(), 'resourceId' => $schedule->getAttribute('resourceId'), 'schedule' => $schedule->getAttribute('schedule'), @@ -175,19 +175,19 @@ abstract class ScheduleBase extends Action $total = $total + $sum; foreach ($results as $document) { - $localDocument = $this->schedules[$document->getInternalId()] ?? null; + $localDocument = $this->schedules[$document->getSequence()] ?? null; if ($localDocument !== null) { if (!$document['active']) { Console::info("Removing: {$document['resourceType']}::{$document['resourceId']}"); - unset($this->schedules[$document->getInternalId()]); + unset($this->schedules[$document->getSequence()]); } elseif (strtotime($localDocument['resourceUpdatedAt']) !== strtotime($document['resourceUpdatedAt'])) { Console::info("Updating: {$document['resourceType']}::{$document['resourceId']}"); - $this->schedules[$document->getInternalId()] = $getSchedule($document); + $this->schedules[$document->getSequence()] = $getSchedule($document); } } else { try { - $this->schedules[$document->getInternalId()] = $getSchedule($document); + $this->schedules[$document->getSequence()] = $getSchedule($document); } catch (\Throwable $th) { $collectionId = static::getCollectionId(); Console::error("Failed to load schedule for project {$document['projectId']} {$collectionId} {$document['resourceId']}"); diff --git a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php index 99c84e829a..cf8dbf8e8d 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleExecutions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleExecutions.php @@ -39,7 +39,7 @@ class ScheduleExecutions extends ScheduleBase $schedule['$id'], ); - unset($this->schedules[$schedule['$internalId']]); + unset($this->schedules[$schedule['$sequence']]); continue; } @@ -81,7 +81,7 @@ class ScheduleExecutions extends ScheduleBase $schedule['$id'], ); - unset($this->schedules[$schedule['$internalId']]); + unset($this->schedules[$schedule['$sequence']]); } } } diff --git a/src/Appwrite/Platform/Tasks/ScheduleMessages.php b/src/Appwrite/Platform/Tasks/ScheduleMessages.php index d23e3de575..af15f9583f 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleMessages.php +++ b/src/Appwrite/Platform/Tasks/ScheduleMessages.php @@ -57,7 +57,7 @@ class ScheduleMessages extends ScheduleBase ); $this->recordEnqueueDelay($scheduledAt); - unset($this->schedules[$schedule['$internalId']]); + unset($this->schedules[$schedule['$sequence']]); }); } } diff --git a/src/Appwrite/Platform/Tasks/StatsResources.php b/src/Appwrite/Platform/Tasks/StatsResources.php index ca2a6860ff..a0b5056b0f 100644 --- a/src/Appwrite/Platform/Tasks/StatsResources.php +++ b/src/Appwrite/Platform/Tasks/StatsResources.php @@ -73,7 +73,7 @@ class StatsResources extends Action $queue ->setProject($project) ->trigger(); - Console::success('project: ' . $project->getId() . '(' . $project->getInternalId() . ')' . ' queued'); + Console::success('project: ' . $project->getId() . '(' . $project->getSequence() . ')' . ' queued'); }); }, $interval); diff --git a/src/Appwrite/Platform/Workers/Audits.php b/src/Appwrite/Platform/Workers/Audits.php index 76309145b8..19ca5181ce 100644 --- a/src/Appwrite/Platform/Workers/Audits.php +++ b/src/Appwrite/Platform/Workers/Audits.php @@ -91,7 +91,7 @@ class Audits extends Action // Create event data $eventData = [ - 'userId' => $user->getInternalId(), + 'userId' => $user->getSequence(), 'event' => $event, 'resource' => $resource, 'userAgent' => $userAgent, @@ -108,13 +108,13 @@ class Audits extends Action 'timestamp' => date("Y-m-d H:i:s", $message->getTimestamp()), ]; - if (isset($this->logs[$project->getInternalId()])) { - $this->logs[$project->getInternalId()]['logs'][] = $eventData; + if (isset($this->logs[$project->getSequence()])) { + $this->logs[$project->getSequence()]['logs'][] = $eventData; } else { - $this->logs[$project->getInternalId()] = [ + $this->logs[$project->getSequence()] = [ 'project' => new Document([ '$id' => $project->getId(), - '$internalId' => $project->getInternalId(), + '$sequence' => $project->getSequence(), 'database' => $project->getAttribute('database'), ]), 'logs' => [$eventData] @@ -130,7 +130,7 @@ class Audits extends Action if ($shouldProcessBatch) { try { - foreach ($this->logs as $internalId => $projectLogs) { + foreach ($this->logs as $sequence => $projectLogs) { $dbForProject = $getProjectDB($projectLogs['project']); Console::log('Processing batch with ' . count($projectLogs['logs']) . ' events'); @@ -139,7 +139,7 @@ class Audits extends Action $audit->logBatch($projectLogs['logs']); Console::success('Audit logs processed successfully'); - unset($this->logs[$internalId]); + unset($this->logs[$sequence]); } } catch (Throwable $e) { Console::error('Error processing audit logs: ' . $e->getMessage()); diff --git a/src/Appwrite/Platform/Workers/Builds.php b/src/Appwrite/Platform/Workers/Builds.php index 59d9abacb8..0a012fe314 100644 --- a/src/Appwrite/Platform/Workers/Builds.php +++ b/src/Appwrite/Platform/Workers/Builds.php @@ -180,7 +180,7 @@ class Builds extends Action '$id' => $buildId, '$permissions' => [], 'startTime' => $startTime, - 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->getSequence(), 'deploymentId' => $deployment->getId(), 'status' => 'processing', 'path' => '', @@ -194,7 +194,7 @@ class Builds extends Action ])); $deployment->setAttribute('buildId', $build->getId()); - $deployment->setAttribute('buildInternalId', $build->getInternalId()); + $deployment->setAttribute('buildInternalId', $build->getSequence()); $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); } elseif ($build->getAttribute('status') === 'canceled') { Console::info('Build has been canceled'); @@ -644,7 +644,7 @@ class Builds extends Action /** Set auto deploy */ if ($deployment->getAttribute('activate') === true) { - $function->setAttribute('deploymentInternalId', $deployment->getInternalId()); + $function->setAttribute('deploymentInternalId', $deployment->getSequence()); $function->setAttribute('deployment', $deployment->getId()); $function->setAttribute('live', true); $function = $dbForProject->updateDocument('functions', $function->getId(), $function); @@ -700,14 +700,14 @@ class Builds extends Action $queueForStatsUsage ->addMetric(METRIC_BUILDS_SUCCESS, 1) // per project ->addMetric(METRIC_BUILDS_COMPUTE_SUCCESS, (int)$build->getAttribute('duration', 0) * 1000) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_SUCCESS), 1) // per function - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE_SUCCESS), (int)$build->getAttribute('duration', 0) * 1000); + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_SUCCESS), 1) // per function + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_COMPUTE_SUCCESS), (int)$build->getAttribute('duration', 0) * 1000); } elseif ($build->getAttribute('status') === 'failed') { $queueForStatsUsage ->addMetric(METRIC_BUILDS_FAILED, 1) // per project ->addMetric(METRIC_BUILDS_COMPUTE_FAILED, (int)$build->getAttribute('duration', 0) * 1000) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_FAILED), 1) // per function - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE_FAILED), (int)$build->getAttribute('duration', 0) * 1000); + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_FAILED), 1) // per function + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_COMPUTE_FAILED), (int)$build->getAttribute('duration', 0) * 1000); } $queueForStatsUsage @@ -715,10 +715,10 @@ class Builds extends Action ->addMetric(METRIC_BUILDS_STORAGE, $build->getAttribute('size', 0)) ->addMetric(METRIC_BUILDS_COMPUTE, (int)$build->getAttribute('duration', 0) * 1000) ->addMetric(METRIC_BUILDS_MB_SECONDS, (int)(($spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT) * $build->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT))) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS), 1) // per function - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE), $build->getAttribute('size', 0)) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int)$build->getAttribute('duration', 0) * 1000) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS), (int)(($spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT) * $build->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT))) + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS), 1) // per function + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_STORAGE), $build->getAttribute('size', 0)) + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_COMPUTE), (int)$build->getAttribute('duration', 0) * 1000) + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_BUILDS_MB_SECONDS), (int)(($spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT) * $build->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT))) ->setProject($project) ->trigger(); } diff --git a/src/Appwrite/Platform/Workers/Certificates.php b/src/Appwrite/Platform/Workers/Certificates.php index 093e6fda5a..47ac4d62d4 100644 --- a/src/Appwrite/Platform/Workers/Certificates.php +++ b/src/Appwrite/Platform/Workers/Certificates.php @@ -221,7 +221,7 @@ class Certificates extends Action $certificate = new Document(\array_merge($certificateDocument->getArrayCopy(), $certificate->getArrayCopy())); $certificate = $dbForPlatform->updateDocument('certificates', $certificate->getId(), $certificate); } else { - $certificate->removeAttribute('$internalId'); + $certificate->removeAttribute('$sequence'); $certificate = $dbForPlatform->createDocument('certificates', $certificate); } diff --git a/src/Appwrite/Platform/Workers/Databases.php b/src/Appwrite/Platform/Workers/Databases.php index 1b3311b756..3881f2b928 100644 --- a/src/Appwrite/Platform/Workers/Databases.php +++ b/src/Appwrite/Platform/Workers/Databases.php @@ -140,15 +140,15 @@ class Databases extends Action try { switch ($type) { case Database::VAR_RELATIONSHIP: - $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); + $relatedCollection = $dbForProject->getDocument('database_' . $database->getSequence(), $options['relatedCollection']); if ($relatedCollection->isEmpty()) { throw new DatabaseException('Collection not found'); } if ( !$dbForProject->createRelationship( - collection: 'database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), - relatedCollection: 'database_' . $database->getInternalId() . '_collection_' . $relatedCollection->getInternalId(), + collection: 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + relatedCollection: 'database_' . $database->getSequence() . '_collection_' . $relatedCollection->getSequence(), type: $options['relationType'], twoWay: $options['twoWay'], id: $key, @@ -160,12 +160,12 @@ class Databases extends Action } if ($options['twoWay']) { - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $options['twoWayKey']); $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'available')); } break; default: - if (!$dbForProject->createAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) { + if (!$dbForProject->createAttribute('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $key, $type, $size, $required, $default, $signed, $array, $format, $formatOptions, $filters)) { throw new Exception('Failed to create Attribute'); } } @@ -200,10 +200,10 @@ class Databases extends Action $this->trigger($database, $collection, $project, $event, $queueForRealtime, $attribute); if (! $relatedCollection->isEmpty()) { - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $relatedCollection->getId()); } - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); } } @@ -250,18 +250,18 @@ class Databases extends Action try { if ($type === Database::VAR_RELATIONSHIP) { if ($options['twoWay']) { - $relatedCollection = $dbForProject->getDocument('database_' . $database->getInternalId(), $options['relatedCollection']); + $relatedCollection = $dbForProject->getDocument('database_' . $database->getSequence(), $options['relatedCollection']); if ($relatedCollection->isEmpty()) { throw new DatabaseException('Collection not found'); } - $relatedAttribute = $dbForProject->getDocument('attributes', $database->getInternalId() . '_' . $relatedCollection->getInternalId() . '_' . $options['twoWayKey']); + $relatedAttribute = $dbForProject->getDocument('attributes', $database->getSequence() . '_' . $relatedCollection->getSequence() . '_' . $options['twoWayKey']); } - if (!$dbForProject->deleteRelationship('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { + if (!$dbForProject->deleteRelationship('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $key)) { $dbForProject->updateDocument('attributes', $relatedAttribute->getId(), $relatedAttribute->setAttribute('status', 'stuck')); throw new DatabaseException('Failed to delete Relationship'); } - } elseif (!$dbForProject->deleteAttribute('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { + } elseif (!$dbForProject->deleteAttribute('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $key)) { throw new DatabaseException('Failed to delete Attribute'); } @@ -358,10 +358,10 @@ class Databases extends Action } } } finally { - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); if (! $relatedCollection->isEmpty()) { - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $relatedCollection->getId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $relatedCollection->getId()); } } } @@ -401,7 +401,7 @@ class Databases extends Action $project = $dbForPlatform->getDocument('projects', $projectId); try { - if (!$dbForProject->createIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key, $type, $attributes, $lengths, $orders)) { + if (!$dbForProject->createIndex('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $key, $type, $attributes, $lengths, $orders)) { throw new DatabaseException('Failed to create Index'); } $dbForProject->updateDocument('indexes', $index->getId(), $index->setAttribute('status', 'available')); @@ -419,7 +419,7 @@ class Databases extends Action throw $e; } finally { $this->trigger($database, $collection, $project, $event, $queueForRealtime, null, $index); - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collectionId); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collectionId); } } @@ -454,7 +454,7 @@ class Databases extends Action $project = $dbForPlatform->getDocument('projects', $projectId); try { - if ($status !== 'failed' && !$dbForProject->deleteIndex('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId(), $key)) { + if ($status !== 'failed' && !$dbForProject->deleteIndex('database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), $key)) { throw new DatabaseException('Failed to delete index'); } $dbForProject->deleteDocument('indexes', $index->getId()); @@ -475,7 +475,7 @@ class Databases extends Action } finally { $this->trigger($database, $collection, $project, $event, $queueForRealtime, null, $index); - $dbForProject->purgeCachedDocument('database_' . $database->getInternalId(), $collection->getId()); + $dbForProject->purgeCachedDocument('database_' . $database->getSequence(), $collection->getId()); } } @@ -488,11 +488,11 @@ class Databases extends Action */ protected function deleteDatabase(Document $database, Document $project, $dbForProject): void { - $this->deleteByGroup('database_' . $database->getInternalId(), [], $dbForProject, function ($collection) use ($database, $project, $dbForProject) { + $this->deleteByGroup('database_' . $database->getSequence(), [], $dbForProject, function ($collection) use ($database, $project, $dbForProject) { $this->deleteCollection($database, $collection, $project, $dbForProject); }); - $dbForProject->deleteCollection('database_' . $database->getInternalId()); + $dbForProject->deleteCollection('database_' . $database->getSequence()); } /** @@ -515,10 +515,10 @@ class Databases extends Action } $collectionId = $collection->getId(); - $collectionInternalId = $collection->getInternalId(); - $databaseInternalId = $database->getInternalId(); + $collectionInternalId = $collection->getSequence(); + $databaseInternalId = $database->getSequence(); - $dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $collection->getInternalId()); + $dbForProject->deleteCollection('database_' . $databaseInternalId . '_collection_' . $collection->getSequence()); /** * Related collections relating to current collection diff --git a/src/Appwrite/Platform/Workers/Deletes.php b/src/Appwrite/Platform/Workers/Deletes.php index 606686c168..c0729896b2 100644 --- a/src/Appwrite/Platform/Workers/Deletes.php +++ b/src/Appwrite/Platform/Workers/Deletes.php @@ -33,7 +33,7 @@ use Utopia\System\System; class Deletes extends Action { - protected array $selects = ['$internalId', '$id', '$collection', '$permissions', '$updatedAt']; + protected array $selects = ['$sequence', '$id', '$collection', '$permissions', '$updatedAt']; public static function getName(): string { @@ -257,7 +257,7 @@ class Deletes extends Action $this->deleteByGroup( 'subscribers', [ - Query::equal('topicInternalId', [$topic->getInternalId()]), + Query::equal('topicInternalId', [$topic->getSequence()]), Query::orderAsc(), ], $getProjectDB($project) @@ -278,7 +278,7 @@ class Deletes extends Action private function deleteSessionTargets(Document $project, callable $getProjectDB, Document $session): void { - Targets::delete($getProjectDB($project), Query::equal('sessionInternalId', [$session->getInternalId()])); + Targets::delete($getProjectDB($project), Query::equal('sessionInternalId', [$session->getSequence()])); } /** @@ -414,7 +414,7 @@ class Deletes extends Action public function deleteMemberships(callable $getProjectDB, Document $document, Document $project): void { $dbForProject = $getProjectDB($project); - $teamInternalId = $document->getInternalId(); + $teamInternalId = $document->getSequence(); // Delete Memberships $this->deleteByGroup( @@ -446,7 +446,7 @@ class Deletes extends Action { $projects = $dbForPlatform->find('projects', [ - Query::equal('teamInternalId', [$document->getInternalId()]), + Query::equal('teamInternalId', [$document->getSequence()]), Query::equal('region', [System::getEnv('_APP_REGION', 'default')]) ]); @@ -476,7 +476,7 @@ class Deletes extends Action */ private function deleteProject(Database $dbForPlatform, callable $getProjectDB, Device $deviceForFiles, Device $deviceForFunctions, Device $deviceForBuilds, Device $deviceForCache, CertificatesAdapter $certificates, Document $document): void { - $projectInternalId = $document->getInternalId(); + $projectInternalId = $document->getSequence(); $projectId = $document->getId(); try { @@ -615,7 +615,7 @@ class Deletes extends Action private function deleteUser(callable $getProjectDB, Document $document, Document $project): void { $userId = $document->getId(); - $userInternalId = $document->getInternalId(); + $userInternalId = $document->getSequence(); $dbForProject = $getProjectDB($project); // Delete all sessions of this user from the sessions table and update the sessions field of the user record @@ -749,14 +749,14 @@ class Deletes extends Action $projectId = $project->getId(); $dbForProject = $getProjectDB($project); $functionId = $document->getId(); - $functionInternalId = $document->getInternalId(); + $functionInternalId = $document->getSequence(); /** * Delete rules */ Console::info("Deleting rules for function " . $functionId); $this->deleteByGroup('rules', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), Query::equal('resourceInternalId', [$functionInternalId]), Query::equal('resourceType', ['function']), Query::orderAsc() @@ -784,7 +784,7 @@ class Deletes extends Action Query::equal('resourceInternalId', [$functionInternalId]), Query::orderAsc() ], $dbForProject, function (Document $document) use ($deviceForFunctions, &$deploymentInternalIds) { - $deploymentInternalIds[] = $document->getInternalId(); + $deploymentInternalIds[] = $document->getSequence(); $this->deleteDeploymentFiles($deviceForFunctions, $document); }); @@ -817,7 +817,7 @@ class Deletes extends Action */ Console::info("Deleting VCS repositories and comments linked to function " . $functionId); $this->deleteByGroup('repositories', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), Query::equal('resourceInternalId', [$functionInternalId]), Query::equal('resourceType', ['function']), Query::orderAsc() @@ -916,7 +916,7 @@ class Deletes extends Action $projectId = $project->getId(); $dbForProject = $getProjectDB($project); $deploymentId = $document->getId(); - $deploymentInternalId = $document->getInternalId(); + $deploymentInternalId = $document->getSequence(); /** * Delete deployment files @@ -1052,7 +1052,7 @@ class Deletes extends Action { $dbForProject = $getProjectDB($project); - $dbForProject->deleteCollection('bucket_' . $document->getInternalId()); + $dbForProject->deleteCollection('bucket_' . $document->getSequence()); $deviceForFiles->deletePath($document->getId()); } @@ -1070,7 +1070,7 @@ class Deletes extends Action $dbForProject = $getProjectDB($project); $this->listByGroup('functions', [ - Query::equal('installationInternalId', [$document->getInternalId()]) + Query::equal('installationInternalId', [$document->getSequence()]) ], $dbForProject, function ($function) use ($dbForProject, $dbForPlatform) { $dbForPlatform->deleteDocument('repositories', $function->getAttribute('repositoryId')); @@ -1101,7 +1101,7 @@ class Deletes extends Action $this->listByGroup( 'deployments', [ - Query::equal('resourceInternalId', [$function->getInternalId()]), + Query::equal('resourceInternalId', [$function->getSequence()]), Query::equal('resourceType', ['functions']), ], $getProjectDB($project), diff --git a/src/Appwrite/Platform/Workers/Functions.php b/src/Appwrite/Platform/Workers/Functions.php index 4e1794c085..e8759b3c1c 100644 --- a/src/Appwrite/Platform/Workers/Functions.php +++ b/src/Appwrite/Platform/Workers/Functions.php @@ -269,7 +269,7 @@ class Functions extends Action $execution = new Document([ '$id' => $executionId, '$permissions' => $user->isEmpty() ? [] : [Permission::read(Role::user($user->getId()))], - 'functionInternalId' => $function->getInternalId(), + 'functionInternalId' => $function->getSequence(), 'functionId' => $function->getId(), 'deploymentInternalId' => '', 'deploymentId' => '', @@ -421,9 +421,9 @@ class Functions extends Action $execution = new Document([ '$id' => $executionId, '$permissions' => $user->isEmpty() ? [] : [Permission::read(Role::user($user->getId()))], - 'functionInternalId' => $function->getInternalId(), + 'functionInternalId' => $function->getSequence(), 'functionId' => $function->getId(), - 'deploymentInternalId' => $deployment->getInternalId(), + 'deploymentInternalId' => $deployment->getSequence(), 'deploymentId' => $deployment->getId(), 'trigger' => $trigger, 'status' => 'processing', @@ -572,11 +572,11 @@ class Functions extends Action $queueForStatsUsage ->setProject($project) ->addMetric(METRIC_EXECUTIONS, 1) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS), 1) + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_EXECUTIONS), 1) ->addMetric(METRIC_EXECUTIONS_COMPUTE, (int)($execution->getAttribute('duration') * 1000))// per project - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE), (int)($execution->getAttribute('duration') * 1000)) ->addMetric(METRIC_EXECUTIONS_MB_SECONDS, (int)(($spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT))) - ->addMetric(str_replace('{functionInternalId}', $function->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT))) + ->addMetric(str_replace('{functionInternalId}', $function->getSequence(), METRIC_FUNCTION_ID_EXECUTIONS_MB_SECONDS), (int)(($spec['memory'] ?? APP_FUNCTION_MEMORY_DEFAULT) * $execution->getAttribute('duration', 0) * ($spec['cpus'] ?? APP_FUNCTION_CPUS_DEFAULT))) ->trigger() ; } diff --git a/src/Appwrite/Platform/Workers/Messaging.php b/src/Appwrite/Platform/Workers/Messaging.php index c9eca2a1e0..8ba7312673 100644 --- a/src/Appwrite/Platform/Workers/Messaging.php +++ b/src/Appwrite/Platform/Workers/Messaging.php @@ -373,7 +373,7 @@ class Messaging extends Action throw new \Exception('Storage bucket with the requested ID could not be found'); } - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); if ($file->isEmpty()) { throw new \Exception('Storage file with the requested ID could not be found'); } @@ -558,7 +558,7 @@ class Messaging extends Action throw new \Exception('Storage bucket with the requested ID could not be found'); } - $file = $dbForProject->getDocument('bucket_' . $bucket->getInternalId(), $fileId); + $file = $dbForProject->getDocument('bucket_' . $bucket->getSequence(), $fileId); if ($file->isEmpty()) { throw new \Exception('Storage file with the requested ID could not be found'); } diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index d342875369..938c4040e9 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -351,7 +351,7 @@ class Migrations extends Action $this->updateMigrationDocument($migration, $projectDocument, $queueForRealtime); if ($migration->getAttribute('status', '') === 'failed') { - Console::error('Migration('.$migration->getInternalId().':'.$migration->getId().') failed, Project('.$this->project->getInternalId().':'.$this->project->getId().')'); + Console::error('Migration('.$migration->getSequence().':'.$migration->getId().') failed, Project('.$this->project->getSequence().':'.$this->project->getId().')'); if ($destination) { $destination->error(); diff --git a/src/Appwrite/Platform/Workers/StatsResources.php b/src/Appwrite/Platform/Workers/StatsResources.php index 0144020d38..0259f72fab 100644 --- a/src/Appwrite/Platform/Workers/StatsResources.php +++ b/src/Appwrite/Platform/Workers/StatsResources.php @@ -80,7 +80,7 @@ class StatsResources extends Action $this->countForProject($dbForPlatform, $getLogsDB, $getProjectDB, $project); $endTime = microtime(true); $executionTime = $endTime - $startTime; - Console::info('Project: ' . $project->getId() . '(' . $project->getInternalId() . ') aggregated in ' . $executionTime .' seconds'); + Console::info('Project: ' . $project->getId() . '(' . $project->getSequence() . ') aggregated in ' . $executionTime .' seconds'); } protected function countForProject(Database $dbForPlatform, callable $getLogsDB, callable $getProjectDB, Document $project): void @@ -105,17 +105,17 @@ class StatsResources extends Action $region = $project->getAttribute('region'); $platforms = $dbForPlatform->count('platforms', [ - Query::equal('projectInternalId', [$project->getInternalId()]) + Query::equal('projectInternalId', [$project->getSequence()]) ]); $webhooks = $dbForPlatform->count('webhooks', [ - Query::equal('projectInternalId', [$project->getInternalId()]) + Query::equal('projectInternalId', [$project->getSequence()]) ]); $keys = $dbForPlatform->count('keys', [ - Query::equal('projectInternalId', [$project->getInternalId()]) + Query::equal('projectInternalId', [$project->getSequence()]) ]); $domains = $dbForPlatform->count('rules', [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), Query::equal('owner', ['']), ]); @@ -216,13 +216,13 @@ class StatsResources extends Action $totalFiles = 0; $totalStorage = 0; $this->foreachDocument($dbForProject, 'buckets', [], function ($bucket) use ($dbForProject, $dbForLogs, $region, &$totalFiles, &$totalStorage) { - $files = $dbForProject->count('bucket_' . $bucket->getInternalId()); + $files = $dbForProject->count('bucket_' . $bucket->getSequence()); - $metric = str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES); + $metric = str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES); $this->createStatsDocuments($region, $metric, $files); - $storage = $dbForProject->sum('bucket_' . $bucket->getInternalId(), 'sizeActual'); - $metric = str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE); + $storage = $dbForProject->sum('bucket_' . $bucket->getSequence(), 'sizeActual'); + $metric = str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_STORAGE); $this->createStatsDocuments($region, $metric, $storage); $totalStorage += $storage; @@ -241,10 +241,10 @@ class StatsResources extends Action $totalImageTransformations = 0; $last30Days = (new \DateTime())->sub(\DateInterval::createFromDateString('30 days'))->format('Y-m-d 00:00:00'); $this->foreachDocument($dbForProject, 'buckets', [], function ($bucket) use ($dbForProject, $last30Days, $region, &$totalImageTransformations) { - $imageTransformations = $dbForProject->count('bucket_' . $bucket->getInternalId(), [ + $imageTransformations = $dbForProject->count('bucket_' . $bucket->getSequence(), [ Query::greaterThanEqual('transformedAt', $last30Days), ]); - $metric = str_replace('{bucketInternalId}', $bucket->getInternalId(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED); + $metric = str_replace('{bucketInternalId}', $bucket->getSequence(), METRIC_BUCKET_ID_FILES_IMAGES_TRANSFORMED); $this->createStatsDocuments($region, $metric, $imageTransformations); $totalImageTransformations += $imageTransformations; }); @@ -260,9 +260,9 @@ class StatsResources extends Action $totalDatabaseStorage = 0; $this->foreachDocument($dbForProject, 'databases', [], function ($database) use ($dbForProject, $region, &$totalCollections, &$totalDocuments, &$totalDatabaseStorage) { - $collections = $dbForProject->count('database_' . $database->getInternalId()); + $collections = $dbForProject->count('database_' . $database->getSequence()); - $metric = str_replace('{databaseInternalId}', $database->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS); + $metric = str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_COLLECTIONS); $this->createStatsDocuments($region, $metric, $collections); [$documents, $storage] = $this->countForCollections($dbForProject, $database, $region); @@ -280,23 +280,23 @@ class StatsResources extends Action { $databaseDocuments = 0; $databaseStorage = 0; - $this->foreachDocument($dbForProject, 'database_' . $database->getInternalId(), [], function ($collection) use ($dbForProject, $database, $region, &$databaseStorage, &$databaseDocuments) { - $documents = $dbForProject->count('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); - $metric = str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS); + $this->foreachDocument($dbForProject, 'database_' . $database->getSequence(), [], function ($collection) use ($dbForProject, $database, $region, &$databaseStorage, &$databaseDocuments) { + $documents = $dbForProject->count('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); + $metric = str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getSequence(), $collection->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS); $this->createStatsDocuments($region, $metric, $documents); $databaseDocuments += $documents; - $collectionStorage = $dbForProject->getSizeOfCollection('database_' . $database->getInternalId() . '_collection_' . $collection->getInternalId()); - $metric = str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getInternalId(), $collection->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE); + $collectionStorage = $dbForProject->getSizeOfCollection('database_' . $database->getSequence() . '_collection_' . $collection->getSequence()); + $metric = str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$database->getSequence(), $collection->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_STORAGE); $this->createStatsDocuments($region, $metric, $collectionStorage); $databaseStorage += $collectionStorage; }); - $metric = str_replace(['{databaseInternalId}'], [$database->getInternalId()], METRIC_DATABASE_ID_DOCUMENTS); + $metric = str_replace(['{databaseInternalId}'], [$database->getSequence()], METRIC_DATABASE_ID_DOCUMENTS); $this->createStatsDocuments($region, $metric, $databaseDocuments); - $metric = str_replace(['{databaseInternalId}'], [$database->getInternalId()], METRIC_DATABASE_ID_STORAGE); + $metric = str_replace(['{databaseInternalId}'], [$database->getSequence()], METRIC_DATABASE_ID_STORAGE); $this->createStatsDocuments($region, $metric, $databaseStorage); return [$databaseDocuments, $databaseStorage]; @@ -317,34 +317,34 @@ class StatsResources extends Action $this->foreachDocument($dbForProject, 'functions', [], function (Document $function) use ($dbForProject, $dbForLogs, $region) { $functionDeploymentsStorage = $dbForProject->sum('deployments', 'size', [ - Query::equal('resourceInternalId', [$function->getInternalId()]), + Query::equal('resourceInternalId', [$function->getSequence()]), Query::equal('resourceType', [RESOURCE_TYPE_FUNCTIONS]), ]); - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), $functionDeploymentsStorage); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS_STORAGE), $functionDeploymentsStorage); $functionDeployments = $dbForProject->count('deployments', [ - Query::equal('resourceInternalId', [$function->getInternalId()]), + Query::equal('resourceInternalId', [$function->getSequence()]), Query::equal('resourceType', [RESOURCE_TYPE_FUNCTIONS]), ]); - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getInternalId()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), $functionDeployments); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getSequence()], METRIC_RESOURCE_TYPE_ID_DEPLOYMENTS), $functionDeployments); /** * As deployments and builds have 1-1 relationship, * the count for one should match the other */ - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS), $functionDeployments); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS), $functionDeployments); $functionBuildsStorage = 0; $this->foreachDocument($dbForProject, 'deployments', [ - Query::equal('resourceInternalId', [$function->getInternalId()]), + Query::equal('resourceInternalId', [$function->getSequence()]), Query::equal('resourceType', [RESOURCE_TYPE_FUNCTIONS]), ], function (Document $deployment) use ($dbForProject, &$functionBuildsStorage): void { $build = $dbForProject->getDocument('builds', $deployment->getAttribute('buildId', '')); $functionBuildsStorage += $build->getAttribute('size', 0); }); - $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getInternalId()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $functionBuildsStorage); + $this->createStatsDocuments($region, str_replace(['{resourceType}','{resourceInternalId}'], [RESOURCE_TYPE_FUNCTIONS,$function->getSequence()], METRIC_RESOURCE_TYPE_ID_BUILDS_STORAGE), $functionBuildsStorage); }); } @@ -372,6 +372,6 @@ class StatsResources extends Action $this->documents ); $this->documents = []; - Console::success('Stats written to logs db for project: ' . $project->getId() . '(' . $project->getInternalId() . ')'); + Console::success('Stats written to logs db for project: ' . $project->getId() . '(' . $project->getSequence() . ')'); } } diff --git a/src/Appwrite/Platform/Workers/StatsUsage.php b/src/Appwrite/Platform/Workers/StatsUsage.php index 60fab5d2ea..38d88d3647 100644 --- a/src/Appwrite/Platform/Workers/StatsUsage.php +++ b/src/Appwrite/Platform/Workers/StatsUsage.php @@ -145,7 +145,7 @@ class StatsUsage extends Action $aggregationInterval = (int) System::getEnv('_APP_USAGE_AGGREGATION_INTERVAL', '20'); $project = new Document($payload['project'] ?? []); - $projectId = $project->getInternalId(); + $projectId = $project->getSequence(); foreach ($payload['reduce'] ?? [] as $document) { if (empty($document)) { continue; @@ -211,8 +211,8 @@ class StatsUsage extends Action } break; case $document->getCollection() === 'databases': // databases - $collections = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_COLLECTIONS))); - $documents = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getInternalId(), METRIC_DATABASE_ID_DOCUMENTS))); + $collections = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getSequence(), METRIC_DATABASE_ID_COLLECTIONS))); + $documents = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{databaseInternalId}', $document->getSequence(), METRIC_DATABASE_ID_DOCUMENTS))); if (!empty($collections['value'])) { $metrics[] = [ 'key' => METRIC_COLLECTIONS, @@ -230,7 +230,7 @@ class StatsUsage extends Action case str_starts_with($document->getCollection(), 'database_') && !str_contains($document->getCollection(), 'collection'): //collections $parts = explode('_', $document->getCollection()); $databaseInternalId = $parts[1] ?? 0; - $documents = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $document->getInternalId()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS))); + $documents = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{databaseInternalId}', '{collectionInternalId}'], [$databaseInternalId, $document->getSequence()], METRIC_DATABASE_ID_COLLECTION_ID_DOCUMENTS))); if (!empty($documents['value'])) { $metrics[] = [ @@ -245,8 +245,8 @@ class StatsUsage extends Action break; case $document->getCollection() === 'buckets': - $files = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES))); - $storage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getInternalId(), METRIC_BUCKET_ID_FILES_STORAGE))); + $files = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getSequence(), METRIC_BUCKET_ID_FILES))); + $storage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{bucketInternalId}', $document->getSequence(), METRIC_BUCKET_ID_FILES_STORAGE))); if (!empty($files['value'])) { $metrics[] = [ @@ -264,13 +264,13 @@ class StatsUsage extends Action break; case $document->getCollection() === 'functions': - $deployments = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS))); - $deploymentsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getInternalId()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE))); - $builds = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS))); - $buildsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_STORAGE))); - $buildsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_BUILDS_COMPUTE))); - $executions = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS))); - $executionsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getInternalId(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE))); + $deployments = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getSequence()], METRIC_FUNCTION_ID_DEPLOYMENTS))); + $deploymentsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace(['{resourceType}', '{resourceInternalId}'], ['functions', $document->getSequence()], METRIC_FUNCTION_ID_DEPLOYMENTS_STORAGE))); + $builds = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getSequence(), METRIC_FUNCTION_ID_BUILDS))); + $buildsStorage = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getSequence(), METRIC_FUNCTION_ID_BUILDS_STORAGE))); + $buildsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getSequence(), METRIC_FUNCTION_ID_BUILDS_COMPUTE))); + $executions = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getSequence(), METRIC_FUNCTION_ID_EXECUTIONS))); + $executionsCompute = $dbForProject->getDocument('stats', md5(self::INFINITY_PERIOD . str_replace('{functionInternalId}', $document->getSequence(), METRIC_FUNCTION_ID_EXECUTIONS_COMPUTE))); if (!empty($deployments['value'])) { $metrics[] = [ @@ -325,7 +325,7 @@ class StatsUsage extends Action break; } } catch (Throwable $e) { - Console::error("[reducer] " . " {DateTime::now()} " . " {$project->getInternalId()} " . " {$e->getMessage()}"); + Console::error("[reducer] " . " {DateTime::now()} " . " {$project->getSequence()} " . " {$e->getMessage()}"); } } @@ -344,7 +344,7 @@ class StatsUsage extends Action continue; } - Console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); + Console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getSequence(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); try { foreach ($stats['keys'] ?? [] as $key => $value) { @@ -370,23 +370,23 @@ class StatsUsage extends Action ]); - $this->projects[$project->getInternalId()]['project'] = new Document([ + $this->projects[$project->getSequence()]['project'] = new Document([ '$id' => $project->getId(), - '$internalId' => $project->getInternalId(), + '$sequence' => $project->getSequence(), 'database' => $project->getAttribute('database'), ]); - $this->projects[$project->getInternalId()]['stats'][] = $document; + $this->projects[$project->getSequence()]['stats'][] = $document; $this->prepareForLogsDB($project, $document); } } } catch (Exception $e) { - Console::error('[' . DateTime::now() . '] project [' . $project->getInternalId() . '] database [' . $project['database'] . '] ' . ' ' . $e->getMessage()); + Console::error('[' . DateTime::now() . '] project [' . $project->getSequence() . '] database [' . $project['database'] . '] ' . ' ' . $e->getMessage()); } } - foreach ($this->projects as $internalId => $projectStats) { - if (empty($internalId)) { + foreach ($this->projects as $sequence => $projectStats) { + if (empty($sequence)) { continue; } try { @@ -395,7 +395,7 @@ class StatsUsage extends Action $dbForProject->createOrUpdateDocumentsWithIncrease('stats', 'value', $projectStats['stats']); Console::success('Batch successfully written to DB'); - unset($this->projects[$internalId]); + unset($this->projects[$sequence]); } catch (Throwable $e) { Console::error('Error processing stats: ' . $e->getMessage()); } @@ -419,7 +419,7 @@ class StatsUsage extends Action } } $documentClone = clone $stat; - $documentClone->setAttribute('$tenant', (int) $project->getInternalId()); + $documentClone->setAttribute('$tenant', (int) $project->getSequence()); $this->statDocuments[] = $documentClone; } diff --git a/src/Appwrite/Platform/Workers/StatsUsageDump.php b/src/Appwrite/Platform/Workers/StatsUsageDump.php index 77ec3f13e6..7c2da8fd4d 100644 --- a/src/Appwrite/Platform/Workers/StatsUsageDump.php +++ b/src/Appwrite/Platform/Workers/StatsUsageDump.php @@ -126,7 +126,7 @@ class StatsUsageDump extends Action continue; } - Console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); + Console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getSequence(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); try { /** @var Database $dbForProject */ @@ -169,7 +169,7 @@ class StatsUsageDump extends Action } } } catch (\Exception $e) { - Console::error('[' . DateTime::now() . '] project [' . $project->getInternalId() . '] database [' . $project['database'] . '] ' . ' ' . $e->getMessage()); + Console::error('[' . DateTime::now() . '] project [' . $project->getSequence() . '] database [' . $project['database'] . '] ' . ' ' . $e->getMessage()); } } } diff --git a/src/Appwrite/Platform/Workers/Webhooks.php b/src/Appwrite/Platform/Workers/Webhooks.php index 44e8bd3118..be2e24798c 100644 --- a/src/Appwrite/Platform/Workers/Webhooks.php +++ b/src/Appwrite/Platform/Workers/Webhooks.php @@ -172,7 +172,7 @@ class Webhooks extends Action $this->errors[] = $logs; $queueForStatsUsage ->addMetric(METRIC_WEBHOOKS_FAILED, 1) - ->addMetric(str_replace('{webhookInternalId}', $webhook->getInternalId(), METRIC_WEBHOOK_ID_FAILED), 1) + ->addMetric(str_replace('{webhookInternalId}', $webhook->getSequence(), METRIC_WEBHOOK_ID_FAILED), 1) ; @@ -182,7 +182,7 @@ class Webhooks extends Action $dbForPlatform->purgeCachedDocument('projects', $project->getId()); $queueForStatsUsage ->addMetric(METRIC_WEBHOOKS_SENT, 1) - ->addMetric(str_replace('{webhookInternalId}', $webhook->getInternalId(), METRIC_WEBHOOK_ID_SENT), 1) + ->addMetric(str_replace('{webhookInternalId}', $webhook->getSequence(), METRIC_WEBHOOK_ID_SENT), 1) ; } diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php index e8eafba5a0..20e7d5cb93 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php @@ -71,8 +71,8 @@ class Base extends Queries 'array' => false, ]); - $internalId = new Document([ - 'key' => '$internalId', + $sequence = new Document([ + 'key' => '$sequence', 'type' => Database::VAR_STRING, 'array' => false, ]); @@ -82,7 +82,7 @@ class Base extends Queries new Offset(), new Cursor(), new Filter($attributes, APP_DATABASE_QUERY_MAX_VALUES), - new Order([...$attributes, $internalId]), + new Order([...$attributes, $sequence]), ]; parent::__construct($validators); diff --git a/src/Appwrite/Utopia/Response/Model/Document.php b/src/Appwrite/Utopia/Response/Model/Document.php index 41a10cee89..c4f7eb3044 100644 --- a/src/Appwrite/Utopia/Response/Model/Document.php +++ b/src/Appwrite/Utopia/Response/Model/Document.php @@ -71,7 +71,7 @@ class Document extends Any public function filter(DatabaseDocument $document): DatabaseDocument { - $document->removeAttribute('$internalId'); + $document->removeAttribute('$sequence'); $document->removeAttribute('$collection'); $document->removeAttribute('$tenant'); diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 9aed3684de..9c7e19c76c 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -2003,9 +2003,9 @@ trait DatabasesBase $this->assertEquals(1944, $documents['body']['documents'][0]['releaseYear']); $this->assertEquals(2017, $documents['body']['documents'][1]['releaseYear']); $this->assertEquals(2019, $documents['body']['documents'][2]['releaseYear']); - $this->assertFalse(array_key_exists('$internalId', $documents['body']['documents'][0])); - $this->assertFalse(array_key_exists('$internalId', $documents['body']['documents'][1])); - $this->assertFalse(array_key_exists('$internalId', $documents['body']['documents'][2])); + $this->assertFalse(array_key_exists('$sequence', $documents['body']['documents'][0])); + $this->assertFalse(array_key_exists('$sequence', $documents['body']['documents'][1])); + $this->assertFalse(array_key_exists('$sequence', $documents['body']['documents'][2])); $this->assertCount(3, $documents['body']['documents']); foreach ($documents['body']['documents'] as $document) { @@ -2098,7 +2098,7 @@ trait DatabasesBase $this->assertEquals($response['body']['releaseYear'], $document['releaseYear']); $this->assertEquals($response['body']['$permissions'], $document['$permissions']); $this->assertEquals($response['body']['birthDay'], $document['birthDay']); - $this->assertFalse(array_key_exists('$internalId', $response['body'])); + $this->assertFalse(array_key_exists('$sequence', $response['body'])); $this->assertFalse(array_key_exists('$tenant', $response['body'])); } } @@ -4361,8 +4361,8 @@ trait DatabasesBase $this->assertArrayNotHasKey('$collection', $person1['body']); $this->assertArrayNotHasKey('$collection', $person1['body']['library']); - $this->assertArrayNotHasKey('$internalId', $person1['body']); - $this->assertArrayNotHasKey('$internalId', $person1['body']['library']); + $this->assertArrayNotHasKey('$sequence', $person1['body']); + $this->assertArrayNotHasKey('$sequence', $person1['body']['library']); $documents = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $person['body']['$id'] . '/documents', array_merge([ 'content-type' => 'application/json', diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index e66207b215..b1b0a8462c 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -674,7 +674,6 @@ class DatabasesCustomServerTest extends Scope /** * Test for creating encrypted attributes */ - $attributesPath = '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'] . '/attributes'; $firstName = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([ diff --git a/tests/resources/sites/static/code.tar.gz b/tests/resources/sites/static/code.tar.gz new file mode 100644 index 0000000000000000000000000000000000000000..cdc8981ce694314b641302275ef7604a1287cb90 GIT binary patch literal 349 zcmV-j0iymNiwFP!000001MSpJPlGTR2XM~&6qU2%WxRQSC1z^8>0ur`R(LX+bcL|G z>9@BXn#>v937y&hcPW%VP=c3_gLMd6Zi?F8{^I$}n?B+Xe_^KM1Da3AJ3;|q89km5@! z+_j)h+jQDxWur7H6WxeP*F{BZQPOz3bIybkT5vgDm0VI0dcnt~w9t~KwtZPM&Xz#7jNkAK+mB$LU`GPbN`{ v{{Ia}+yArvvt%t_9PIwjS@b>t0000000000000000GymRx5W-U04M+eMiH$^ literal 0 HcmV?d00001 From f09bda97f89ac37b4b71fe29679ad14910c19638 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 26 May 2025 17:45:12 +1200 Subject: [PATCH 108/219] Update lock --- composer.json | 4 +- composer.lock | 100 +++++++++++++++++++++++++------------------------- 2 files changed, 52 insertions(+), 52 deletions(-) diff --git a/composer.json b/composer.json index cc5a174a24..af7f2ca8ce 100644 --- a/composer.json +++ b/composer.json @@ -51,7 +51,7 @@ "utopia-php/cache": "0.13.*", "utopia-php/cli": "0.15.*", "utopia-php/config": "0.2.*", - "utopia-php/database": "0.69.*", + "utopia-php/database": "0.71.*", "utopia-php/domains": "0.5.*", "utopia-php/dsn": "0.2.1", "utopia-php/framework": "0.33.*", @@ -60,7 +60,7 @@ "utopia-php/locale": "0.4.*", "utopia-php/logger": "0.6.*", "utopia-php/messaging": "0.17.*", - "utopia-php/migration": "0.9.*", + "utopia-php/migration": "0.10.*", "utopia-php/orchestration": "0.9.*", "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", diff --git a/composer.lock b/composer.lock index 57d627d493..a8cba31c4b 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "63feb1a7cf4cfa2cc7fa0870236e61ea", + "content-hash": "c0326e442e6920411bf4e7634da0abad", "packages": [ { "name": "adhocore/jwt", @@ -1238,16 +1238,16 @@ }, { "name": "open-telemetry/exporter-otlp", - "version": "1.3.0", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/exporter-otlp.git", - "reference": "19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c" + "reference": "8b3ca1f86d01429c73b407bf1a2075d9c187001e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c", - "reference": "19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c", + "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/8b3ca1f86d01429c73b407bf1a2075d9c187001e", + "reference": "8b3ca1f86d01429c73b407bf1a2075d9c187001e", "shasum": "" }, "require": { @@ -1298,7 +1298,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-12T00:36:35+00:00" + "time": "2025-05-21T12:02:20+00:00" }, { "name": "open-telemetry/gen-otlp-protobuf", @@ -1365,16 +1365,16 @@ }, { "name": "open-telemetry/sdk", - "version": "1.4.0", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/sdk.git", - "reference": "939d3a28395c249a763676458140dad44b3a8011" + "reference": "cd0d7367599717fc29e04eb8838ec061e6c2c657" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/939d3a28395c249a763676458140dad44b3a8011", - "reference": "939d3a28395c249a763676458140dad44b3a8011", + "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/cd0d7367599717fc29e04eb8838ec061e6c2c657", + "reference": "cd0d7367599717fc29e04eb8838ec061e6c2c657", "shasum": "" }, "require": { @@ -1451,7 +1451,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-07T12:32:21+00:00" + "time": "2025-05-22T02:33:34+00:00" }, { "name": "open-telemetry/sem-conv", @@ -2486,16 +2486,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { @@ -2508,7 +2508,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -2533,7 +2533,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" }, "funding": [ { @@ -2549,7 +2549,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/http-client", @@ -2648,16 +2648,16 @@ }, { "name": "symfony/http-client-contracts", - "version": "v3.5.2", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645" + "reference": "75d7043853a42837e68111812f4d964b01e5101c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/ee8d807ab20fcb51267fdace50fbe3494c31e645", - "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/75d7043853a42837e68111812f4d964b01e5101c", + "reference": "75d7043853a42837e68111812f4d964b01e5101c", "shasum": "" }, "require": { @@ -2670,7 +2670,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -2706,7 +2706,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.2" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.6.0" }, "funding": [ { @@ -2722,7 +2722,7 @@ "type": "tidelift" } ], - "time": "2024-12-07T08:49:48+00:00" + "time": "2025-04-29T11:18:49+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -2883,16 +2883,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", "shasum": "" }, "require": { @@ -2910,7 +2910,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -2946,7 +2946,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" }, "funding": [ { @@ -2962,7 +2962,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2025-04-25T09:37:31+00:00" }, { "name": "tbachert/spi", @@ -3499,16 +3499,16 @@ }, { "name": "utopia-php/database", - "version": "0.69.5", + "version": "0.71.0", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "4abe53609dfc23b2ea82884d12b149df6a8af2f5" + "reference": "cf463c0a5c64a4168fe56266ace4ae835d61c920" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/4abe53609dfc23b2ea82884d12b149df6a8af2f5", - "reference": "4abe53609dfc23b2ea82884d12b149df6a8af2f5", + "url": "https://api.github.com/repos/utopia-php/database/zipball/cf463c0a5c64a4168fe56266ace4ae835d61c920", + "reference": "cf463c0a5c64a4168fe56266ace4ae835d61c920", "shasum": "" }, "require": { @@ -3549,9 +3549,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.69.5" + "source": "https://github.com/utopia-php/database/tree/0.71.0" }, - "time": "2025-05-17T08:01:51+00:00" + "time": "2025-05-23T07:32:59+00:00" }, { "name": "utopia-php/domains", @@ -3953,16 +3953,16 @@ }, { "name": "utopia-php/migration", - "version": "0.9.3", + "version": "0.10.0", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "e518d39eb550fde36bc5cf06c9bd7b2faf5dbedd" + "reference": "0b0e94c4b5243c5566b9634b07ba2ec5f7990914" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/e518d39eb550fde36bc5cf06c9bd7b2faf5dbedd", - "reference": "e518d39eb550fde36bc5cf06c9bd7b2faf5dbedd", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/0b0e94c4b5243c5566b9634b07ba2ec5f7990914", + "reference": "0b0e94c4b5243c5566b9634b07ba2ec5f7990914", "shasum": "" }, "require": { @@ -4003,9 +4003,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.9.3" + "source": "https://github.com/utopia-php/migration/tree/0.10.0" }, - "time": "2025-05-01T05:41:26+00:00" + "time": "2025-05-23T07:40:24+00:00" }, { "name": "utopia-php/orchestration", @@ -4771,16 +4771,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.40.18", + "version": "0.40.19", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "38de4b9c58112d7e83eb75955994c8412a401093" + "reference": "05b53cf30c59fe5934d57207fefbc8ae8feb5dbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/38de4b9c58112d7e83eb75955994c8412a401093", - "reference": "38de4b9c58112d7e83eb75955994c8412a401093", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/05b53cf30c59fe5934d57207fefbc8ae8feb5dbf", + "reference": "05b53cf30c59fe5934d57207fefbc8ae8feb5dbf", "shasum": "" }, "require": { @@ -4816,9 +4816,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.40.18" + "source": "https://github.com/appwrite/sdk-generator/tree/0.40.19" }, - "time": "2025-05-21T14:14:47+00:00" + "time": "2025-05-24T22:49:50+00:00" }, { "name": "doctrine/annotations", From 856a9a714b4923f79cffe7b235bf842829cb167c Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 26 May 2025 11:29:46 +0530 Subject: [PATCH 109/219] fix: memberships patch and delete logic. --- app/controllers/api/teams.php | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index cc930eca90..7e0d440bd3 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -1096,9 +1096,12 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') max: 2 ); + // Is the role change being requested by the user on their own membership? + $isCurrentUserAnOwner = $user->getInternalId() === $membership->getAttribute('userInternalId'); + // Prevent role change if there's only one owner left, - // the requester is that owner, and the new `$roles` no longer include 'owner'! - if ($ownersCount === 1 && $isOwner && !\in_array('owner', $roles)) { + // the requester is that owner, and the new `$roles` no longer include 'owner' + if ($ownersCount === 1 && $isOwner && $isCurrentUserAnOwner && !\in_array('owner', $roles)) { throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'There must be at least one owner in the organization.'); } } @@ -1314,11 +1317,12 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') )) ->param('teamId', '', new UID(), 'Team ID.') ->param('membershipId', '', new UID(), 'Membership ID.') + ->inject('user') ->inject('project') ->inject('response') ->inject('dbForProject') ->inject('queueForEvents') - ->action(function (string $teamId, string $membershipId, Document $project, Response $response, Database $dbForProject, Event $queueForEvents) { + ->action(function (string $teamId, string $membershipId, Document $user, Document $project, Response $response, Database $dbForProject, Event $queueForEvents) { $membership = $dbForProject->getDocument('memberships', $membershipId); @@ -1326,9 +1330,9 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') throw new Exception(Exception::TEAM_INVITE_NOT_FOUND); } - $user = $dbForProject->getDocument('users', $membership->getAttribute('userId')); + $profile = $dbForProject->getDocument('users', $membership->getAttribute('userId')); - if ($user->isEmpty()) { + if ($profile->isEmpty()) { throw new Exception(Exception::USER_NOT_FOUND); } @@ -1354,7 +1358,10 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') max: 2 ); - if ($ownersCount === 1) { + // Is the deletion being requested by the user on their own membership? + $isCurrentUserAnOwner = $user->getInternalId() === $membership->getAttribute('userInternalId'); + + if ($ownersCount === 1 && $isCurrentUserAnOwner) { /* Prevent removal if the user is the only owner. */ throw new Exception( Exception::GENERAL_ARGUMENT_INVALID, @@ -1378,8 +1385,8 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') } $queueForEvents - ->setParam('userId', $user->getId()) ->setParam('teamId', $team->getId()) + ->setParam('userId', $profile->getId()) ->setParam('membershipId', $membership->getId()) ->setPayload($response->output($membership, Response::MODEL_MEMBERSHIP)) ; From d5999fde53f79c4b68ba99dbf73484e99e331bfd Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 26 May 2025 18:03:03 +1200 Subject: [PATCH 110/219] Ignore plan blocked test for cl --- tests/e2e/Services/Databases/DatabasesCustomServerTest.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index b1b0a8462c..7e2b7a5f8a 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -641,10 +641,10 @@ class DatabasesCustomServerTest extends Scope /** * @depends testListCollections + * @group cl-ignore */ public function testCreateEncryptedAttribute(array $data): void { - $databaseId = $data['databaseId']; /** @@ -685,6 +685,7 @@ class DatabasesCustomServerTest extends Scope 'size' => 256, 'required' => true, ]); + // checking size test $lastName = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([ 'content-type' => 'application/json', @@ -709,12 +710,15 @@ class DatabasesCustomServerTest extends Scope 'encrypt' => true ]); $this->assertTrue($lastName['body']['encrypt']); + sleep(1); + $response = $this->client->call(Client::METHOD_GET, $attributesPath . '/lastName', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ])); + $this->assertTrue($response['body']['encrypt']); /** From 96bef81ebc2ac062fbe3bd2bde8be5775fe2cf1e Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 26 May 2025 11:33:58 +0530 Subject: [PATCH 111/219] fix: tests! --- tests/e2e/Services/Teams/TeamsBaseClient.php | 83 +++--------- .../Services/Teams/TeamsConsoleClientTest.php | 125 +++++++++++++++--- 2 files changed, 119 insertions(+), 89 deletions(-) diff --git a/tests/e2e/Services/Teams/TeamsBaseClient.php b/tests/e2e/Services/Teams/TeamsBaseClient.php index 2aacf4abc1..9b19572d7b 100644 --- a/tests/e2e/Services/Teams/TeamsBaseClient.php +++ b/tests/e2e/Services/Teams/TeamsBaseClient.php @@ -10,17 +10,6 @@ use Utopia\Database\Validator\Datetime as DatetimeValidator; trait TeamsBaseClient { - /** - * Checks if the current project is the Console project. - * - * This is necessary because the last admin of an org - * cannot be removed, which affects certain test conditions. - */ - private function isConsoleProject(): bool - { - return $this->getProject()['$id'] === 'console'; - } - /** * @depends testCreateTeam */ @@ -71,11 +60,7 @@ trait TeamsBaseClient ]); $this->assertEquals(200, $response['headers']['status-code']); - if ($this->isConsoleProject()) { - $this->assertCount(1, $response['body']['memberships']); - } else { - $this->assertCount(0, $response['body']['memberships']); - } + $this->assertCount(0, $response['body']['memberships']); $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', @@ -99,11 +84,7 @@ trait TeamsBaseClient ]); $this->assertEquals(200, $response['headers']['status-code']); - if ($this->isConsoleProject()) { - $this->assertCount(1, $response['body']['memberships']); - } else { - $this->assertCount(0, $response['body']['memberships']); - } + $this->assertCount(0, $response['body']['memberships']); $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', @@ -392,11 +373,7 @@ trait TeamsBaseClient $this->assertEquals(200, $memberships['headers']['status-code']); $this->assertIsInt($memberships['body']['total']); $this->assertNotEmpty($memberships['body']['memberships']); - if ($this->isConsoleProject()) { - $this->assertCount(4, $memberships['body']['memberships']); - } else { - $this->assertCount(3, $memberships['body']['memberships']); - } + $this->assertCount(3, $memberships['body']['memberships']); $response = $this->client->call(Client::METHOD_GET, '/teams/' . $data['teamUid'] . '/memberships', array_merge([ 'content-type' => 'application/json', @@ -410,11 +387,7 @@ trait TeamsBaseClient $this->assertEquals(200, $response['headers']['status-code']); $this->assertIsInt($response['body']['total']); $this->assertNotEmpty($response['body']['memberships']); - if ($this->isConsoleProject()) { - $this->assertCount(3, $response['body']['memberships']); - } else { - $this->assertCount(2, $response['body']['memberships']); - } + $this->assertCount(2, $response['body']['memberships']); $this->assertEquals($memberships['body']['memberships'][1]['$id'], $response['body']['memberships'][0]['$id']); } @@ -737,8 +710,8 @@ trait TeamsBaseClient } /** - * @depends testUpdateTeamMembershipRoles - */ + * @depends testUpdateTeamMembershipRoles + */ public function testDeleteTeamMembership($data): array { $teamUid = $data['teamUid'] ?? ''; @@ -751,11 +724,7 @@ trait TeamsBaseClient ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - if ($this->isConsoleProject()) { - $this->assertCount(5, $response['body']['memberships']); - } else { - $this->assertCount(4, $response['body']['memberships']); - } + $this->assertEquals(4, $response['body']['total']); $ownerMembershipUid = $response['body']['memberships'][0]['$id']; @@ -785,18 +754,14 @@ trait TeamsBaseClient 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]); - if ($this->isConsoleProject()) { - $this->assertEquals(400, $response['headers']['status-code']); - } else { - $this->assertEquals(401, $response['headers']['status-code']); - } + $this->assertEquals(401, $response['headers']['status-code']); /** * Test for SUCCESS */ /** - * Test for when a user other than the owner tries to delete an owner's membership. + * Test for when a user other than the owner tries to delete their membership */ $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/' . $membershipUid, [ 'origin' => 'http://localhost', @@ -805,13 +770,8 @@ trait TeamsBaseClient 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]); - if ($this->isConsoleProject()) { - $this->assertEquals(400, $response['headers']['status-code']); - $this->assertNotEmpty($response['body']); - } else { - $this->assertEquals(204, $response['headers']['status-code']); - $this->assertEmpty($response['body']); - } + $this->assertEquals(204, $response['headers']['status-code']); + $this->assertEmpty($response['body']); $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', @@ -819,11 +779,7 @@ trait TeamsBaseClient ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - if ($this->isConsoleProject()) { - $this->assertEquals(5, $response['body']['total']); - } else { - $this->assertEquals(3, $response['body']['total']); - } + $this->assertEquals(3, $response['body']['total']); /** * Test for when the owner tries to delete their membership @@ -834,13 +790,8 @@ trait TeamsBaseClient 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - if ($this->isConsoleProject()) { - $this->assertEquals(400, $response['headers']['status-code']); - $this->assertNotEmpty($response['body']); - } else { - $this->assertEquals(204, $response['headers']['status-code']); - $this->assertEmpty($response['body']); - } + $this->assertEquals(204, $response['headers']['status-code']); + $this->assertEmpty($response['body']); $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $ownerMembershipUid, array_merge([ 'origin' => 'http://localhost', @@ -848,11 +799,7 @@ trait TeamsBaseClient 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); - if ($this->isConsoleProject()) { - $this->assertEquals(200, $response['headers']['status-code']); - } else { - $this->assertEquals(404, $response['headers']['status-code']); - } + $this->assertEquals(404, $response['headers']['status-code']); return []; } diff --git a/tests/e2e/Services/Teams/TeamsConsoleClientTest.php b/tests/e2e/Services/Teams/TeamsConsoleClientTest.php index 3798019884..f414123788 100644 --- a/tests/e2e/Services/Teams/TeamsConsoleClientTest.php +++ b/tests/e2e/Services/Teams/TeamsConsoleClientTest.php @@ -41,7 +41,7 @@ class TeamsConsoleClientTest extends Scope /** * Test for SUCCESS */ - $response = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ + $developer = $this->client->call(Client::METHOD_POST, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ @@ -51,7 +51,8 @@ class TeamsConsoleClientTest extends Scope 'url' => 'http://localhost:5000/join-us#title' ]); - $this->assertEquals(201, $response['headers']['status-code']); + $developerUserId = $developer['body']['$id']; + $this->assertEquals(201, $developer['headers']['status-code']); $response = $this->client->call(Client::METHOD_GET, '/users', array_merge([ 'content-type' => 'application/json', @@ -66,7 +67,7 @@ class TeamsConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); - $ownerMembershipUid = $response['body']['memberships'][1]['$id']; + $ownerMembershipUid = $response['body']['memberships'][0]['$id']; $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/' . $ownerMembershipUid, array_merge([ 'origin' => 'http://localhost', @@ -77,6 +78,16 @@ class TeamsConsoleClientTest extends Scope $this->assertEquals(400, $response['headers']['status-code']); $this->assertEquals('There must be at least one owner in the organization.', $response['body']['message']); + // Remove the excess developer member to reduce the membership count in `TeamsBaseClient` tests. + // This is necessary because the only owner cannot be removed in the console project / top level team / organization. + $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/' . $developerUserId, array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(204, $response['headers']['status-code']); + return $data; } @@ -87,21 +98,6 @@ class TeamsConsoleClientTest extends Scope $membershipUid = $data['membershipUid'] ?? ''; $session = $data['session'] ?? ''; - /** - * Test for FAILURE - */ - $roles = ['developer']; - $response = $this->client->call(Client::METHOD_PATCH, '/teams/' . $teamUid . '/memberships/' . $membershipUid, array_merge([ - 'origin' => 'http://localhost', - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders()), [ - 'roles' => $roles - ]); - - $this->assertEquals(400, $response['headers']['status-code']); - $this->assertEquals('There must be at least one owner in the organization.', $response['body']['message']); - /** * Test for unknown team */ @@ -110,7 +106,7 @@ class TeamsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'roles' => $roles + 'roles' => ['developer'] ]); $this->assertEquals(404, $response['headers']['status-code']); @@ -123,7 +119,7 @@ class TeamsConsoleClientTest extends Scope 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'roles' => $roles + 'roles' => ['developer'] ]); $this->assertEquals(404, $response['headers']['status-code']); @@ -138,7 +134,7 @@ class TeamsConsoleClientTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ], [ - 'roles' => $roles + 'roles' => ['developer'] ]); $this->assertEquals(401, $response['headers']['status-code']); @@ -146,4 +142,91 @@ class TeamsConsoleClientTest extends Scope return $data; } + + /** + * @depends testUpdateTeamMembershipRoles + */ + public function testDeleteTeamMembership($data): array + { + $teamUid = $data['teamUid'] ?? ''; + $membershipUid = $data['membershipUid'] ?? ''; + $session = $data['session'] ?? ''; + + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(3, $response['body']['total']); + + $ownerMembershipUid = $response['body']['memberships'][0]['$id']; + + /** + * Test deleting a membership that does not exists + */ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/dne', [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ]); + + $this->assertEquals(404, $response['headers']['status-code']); + + /** + * Test deleting another user's membership + */ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/' . $ownerMembershipUid, [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ]); + + $this->assertEquals(401, $response['headers']['status-code']); + $this->assertEquals('The current user is not authorized to perform the requested action.', $response['body']['message']); + + /** + * Test for when a user other than the owner tries to delete their membership + */ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/' . $membershipUid, [ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, + ]); + + $this->assertEquals(400, $response['headers']['status-code']); + + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(3, $response['body']['total']); + + /** + * Test for when the owner tries to delete their membership + */ + $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/' . $ownerMembershipUid, array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(400, $response['headers']['status-code']); + $this->assertEquals('There must be at least one owner in the organization.', $response['body']['message']); + + $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $ownerMembershipUid, array_merge([ + 'origin' => 'http://localhost', + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + + $this->assertEquals(200, $response['headers']['status-code']); + + return []; + } } From 64baf1071d5bd7137c0bd159a64c630c53dd8cff Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 26 May 2025 11:38:22 +0530 Subject: [PATCH 112/219] fix: wrong variable passed to cache purge. --- app/controllers/api/teams.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index 7e0d440bd3..5cac3dc9ea 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -1378,7 +1378,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed to remove membership from DB'); } - $dbForProject->purgeCachedDocument('users', $user->getId()); + $dbForProject->purgeCachedDocument('users', $profile->getId()); if ($membership->getAttribute('confirm')) { // Count only confirmed members Authorization::skip(fn () => $dbForProject->decreaseDocumentAttribute('teams', $team->getId(), 'total', 1, 0)); From 554d8365a6df06cfcf65410a32a0714564cf2983 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 26 May 2025 18:10:08 +1200 Subject: [PATCH 113/219] Format --- tests/e2e/Services/Databases/DatabasesCustomServerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 7e2b7a5f8a..993624a1fe 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -718,7 +718,7 @@ class DatabasesCustomServerTest extends Scope 'x-appwrite-project' => $this->getProject()['$id'], 'x-appwrite-key' => $this->getProject()['apiKey'], ])); - + $this->assertTrue($response['body']['encrypt']); /** From 3adbe8a8f51030947ed09604ac9be30e4d3ebb67 Mon Sep 17 00:00:00 2001 From: Darshan Date: Mon, 26 May 2025 11:41:58 +0530 Subject: [PATCH 114/219] revert: minor change. --- tests/e2e/Services/Teams/TeamsBaseClient.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/Services/Teams/TeamsBaseClient.php b/tests/e2e/Services/Teams/TeamsBaseClient.php index 9b19572d7b..3fcd9c043d 100644 --- a/tests/e2e/Services/Teams/TeamsBaseClient.php +++ b/tests/e2e/Services/Teams/TeamsBaseClient.php @@ -710,8 +710,8 @@ trait TeamsBaseClient } /** - * @depends testUpdateTeamMembershipRoles - */ + * @depends testUpdateTeamMembershipRoles + */ public function testDeleteTeamMembership($data): array { $teamUid = $data['teamUid'] ?? ''; From b7d0c127a3bf571d97b2ff68c0abdb289febe18d Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 26 May 2025 21:37:21 +1200 Subject: [PATCH 115/219] Revert "Merge pull request #9878 from ArnabChatterjee20k/dat-532" This reverts commit a366feba803c7082259b8d72e28a103793194352, reversing changes made to 484988fcd7d730d6ac710b06840a5c5fe357ae3f. --- app/controllers/api/databases.php | 6 ------ app/init/constants.php | 1 - .../Services/Databases/DatabasesCustomServerTest.php | 12 ------------ 3 files changed, 19 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 4860f7a967..18b0d87053 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1352,12 +1352,6 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string if ($encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string attributes are not available on your plan. Please upgrade to create encrypted string attributes.'); } - if ($encrypt && $size < APP_DATABASE_ENCRYPT_SIZE_MIN) { - throw new Exception( - Exception::GENERAL_BAD_REQUEST, - "Size too small. Encrypted strings require a minimum size of " . APP_DATABASE_ENCRYPT_SIZE_MIN . " characters." - ); - } // Ensure attribute default is within required size $validator = new Text($size, 0); if (!is_null($default) && !$validator->isValid($default)) { diff --git a/app/init/constants.php b/app/init/constants.php index ebf79086a7..99881a4381 100644 --- a/app/init/constants.php +++ b/app/init/constants.php @@ -51,7 +51,6 @@ const APP_DATABASE_TIMEOUT_MILLISECONDS_API = 15 * 1000; // 15 seconds const APP_DATABASE_TIMEOUT_MILLISECONDS_WORKER = 300 * 1000; // 5 minutes const APP_DATABASE_TIMEOUT_MILLISECONDS_TASK = 300 * 1000; // 5 minutes const APP_DATABASE_QUERY_MAX_VALUES = 500; -const APP_DATABASE_ENCRYPT_SIZE_MIN = 150; const APP_STORAGE_UPLOADS = '/storage/uploads'; const APP_STORAGE_SITES = '/storage/sites'; const APP_STORAGE_FUNCTIONS = '/storage/functions'; diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index e66207b215..c0d8763aa7 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -686,18 +686,6 @@ class DatabasesCustomServerTest extends Scope 'size' => 256, 'required' => true, ]); - // checking size test - $lastName = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] - ]), [ - 'key' => 'lastName', - 'size' => 149, - 'required' => true, - 'encrypt' => true - ]); - $this->assertEquals("Size too small. Encrypted strings require a minimum size of " . APP_DATABASE_ENCRYPT_SIZE_MIN . " characters.", $lastName['body']['message']); $lastName = $this->client->call(Client::METHOD_POST, $attributesPath . '/string', array_merge([ 'content-type' => 'application/json', From ab97b7cc54becbcc48b1d1fdccef57a26ee484c8 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 23 May 2025 15:07:17 +0000 Subject: [PATCH 116/219] Merge pull request #9877 from appwrite/revert-9871-feat-sync Revert "Feat sync encrypt updates" --- app/controllers/api/databases.php | 19 +++--------- app/init/database/filters.php | 21 ++++---------- .../Utopia/Response/Model/AttributeString.php | 7 ----- .../e2e/Services/Databases/DatabasesBase.php | 2 +- .../Databases/DatabasesCustomServerTest.php | 29 ++----------------- 5 files changed, 13 insertions(+), 65 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 18b0d87053..277bfae16a 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1347,11 +1347,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string ->inject('dbForProject') ->inject('queueForDatabase') ->inject('queueForEvents') - ->inject('plan') - ->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, array $plan) { - if ($encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) { - throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string attributes are not available on your plan. Please upgrade to create encrypted string attributes.'); - } + ->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents) { // Ensure attribute default is within required size $validator = new Text($size, 0); if (!is_null($default) && !$validator->isValid($default)) { @@ -1372,7 +1368,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string 'array' => $array, 'filters' => $filters, ]), $response, $dbForProject, $queueForDatabase, $queueForEvents); - $attribute->setAttribute('encrypt', $encrypt); + $response ->setStatusCode(Response::STATUS_CODE_ACCEPTED) ->dynamic($attribute, Response::MODEL_ATTRIBUTE_STRING); @@ -2051,13 +2047,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes') throw new Exception(Exception::GENERAL_QUERY_INVALID); } - foreach ($attributes as $attribute) { - if ($attribute->getAttribute('type') === Database::VAR_STRING) { - $filters = $attribute->getAttribute('filters', []); - $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); - } - } - $response->dynamic(new Document([ 'attributes' => $attributes, 'total' => $total, @@ -2122,7 +2111,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') $type = $attribute->getAttribute('type'); $format = $attribute->getAttribute('format'); $options = $attribute->getAttribute('options', []); - $filters = $attribute->getAttribute('filters', []); + foreach ($options as $key => $option) { $attribute->setAttribute($key, $option); } @@ -2142,7 +2131,7 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/attributes/:key') }, default => Response::MODEL_ATTRIBUTE, }; - $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); + $response->dynamic($attribute, $model); }); diff --git a/app/init/database/filters.php b/app/init/database/filters.php index c470329706..f110fe1554 100644 --- a/app/init/database/filters.php +++ b/app/init/database/filters.php @@ -77,21 +77,12 @@ Database::addFilter( ]); foreach ($attributes as $attribute) { - $attributeType = $attribute->getAttribute('type'); - - switch ($attributeType) { - case Database::VAR_RELATIONSHIP: - $options = $attribute->getAttribute('options'); - foreach ($options as $key => $value) { - $attribute->setAttribute($key, $value); - } - $attribute->removeAttribute('options'); - break; - - case Database::VAR_STRING: - $filters = $attribute->getAttribute('filters', []); - $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); - break; + if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { + $options = $attribute->getAttribute('options'); + foreach ($options as $key => $value) { + $attribute->setAttribute($key, $value); + } + $attribute->removeAttribute('options'); } } diff --git a/src/Appwrite/Utopia/Response/Model/AttributeString.php b/src/Appwrite/Utopia/Response/Model/AttributeString.php index fded48fddc..12bb42009d 100644 --- a/src/Appwrite/Utopia/Response/Model/AttributeString.php +++ b/src/Appwrite/Utopia/Response/Model/AttributeString.php @@ -24,13 +24,6 @@ class AttributeString extends Attribute 'required' => false, 'example' => 'default', ]) - ->addRule('encrypt', [ - 'type' => self::TYPE_BOOLEAN, - 'description' => 'Defines whether this attribute is encrypted or not.', - 'default' => false, - 'required' => false, - 'example' => false, - ]) ; } diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 9aed3684de..7c0060ecaa 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -298,7 +298,7 @@ trait DatabasesBase $this->assertEquals($title['body']['type'], 'string'); $this->assertEquals($title['body']['size'], 256); $this->assertEquals($title['body']['required'], true); - $this->assertFalse($title['body']['encrypt']); + $this->assertEquals(202, $description['headers']['status-code']); $this->assertEquals($description['body']['key'], 'description'); $this->assertEquals($description['body']['type'], 'string'); diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index c0d8763aa7..829960b54f 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -695,16 +695,9 @@ class DatabasesCustomServerTest extends Scope 'key' => 'lastName', 'size' => 256, 'required' => true, - 'encrypt' => true + 'encrypt' => true, ]); - $this->assertTrue($lastName['body']['encrypt']); - sleep(1); - $response = $this->client->call(Client::METHOD_GET, $attributesPath . '/lastName', array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'], - ])); - $this->assertTrue($response['body']['encrypt']); + /** * Check status of every attribute @@ -748,24 +741,6 @@ class DatabasesCustomServerTest extends Scope $this->assertEquals(200, $document['headers']['status-code']); $this->assertEquals('Jonah', $document['body']['firstName']); $this->assertEquals('Jameson', $document['body']['lastName']); - - - $actors = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $actors['body']['$id'], array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - 'x-appwrite-key' => $this->getProject()['apiKey'] - ]), []); - $attributes = $actors['body']['attributes']; - foreach ($attributes as $attribute) { - $this->assertArrayHasKey('encrypt', $attribute); - if ($attribute['key'] === 'firstName') { - $this->assertFalse($attribute['encrypt']); - } - if ($attribute['key'] === 'lastName') { - $this->assertTrue($attribute['encrypt']); - } - } - } public function testDeleteAttribute(): array From c7c9e057ab18480cec777b8100651217574675b1 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 26 May 2025 22:00:39 +1200 Subject: [PATCH 117/219] Update generator --- composer.json | 2 +- composer.lock | 60 +++++++++++++++++++++++++-------------------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/composer.json b/composer.json index 7e445cd36b..328791c56f 100644 --- a/composer.json +++ b/composer.json @@ -86,7 +86,7 @@ }, "require-dev": { "ext-fileinfo": "*", - "appwrite/sdk-generator": "0.40.*", + "appwrite/sdk-generator": "0.41.*", "phpunit/phpunit": "9.*", "swoole/ide-helper": "5.1.2", "phpstan/phpstan": "1.8.*", diff --git a/composer.lock b/composer.lock index ef067116d0..f5b3f796c8 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9f5de64d73e2ef73d796fa64f2baf232", + "content-hash": "a4b3f30b815230a17c33310f62ffb18d", "packages": [ { "name": "adhocore/jwt", @@ -2486,16 +2486,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { @@ -2508,7 +2508,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -2533,7 +2533,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" }, "funding": [ { @@ -2549,7 +2549,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/http-client", @@ -2648,16 +2648,16 @@ }, { "name": "symfony/http-client-contracts", - "version": "v3.5.2", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645" + "reference": "75d7043853a42837e68111812f4d964b01e5101c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/ee8d807ab20fcb51267fdace50fbe3494c31e645", - "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/75d7043853a42837e68111812f4d964b01e5101c", + "reference": "75d7043853a42837e68111812f4d964b01e5101c", "shasum": "" }, "require": { @@ -2670,7 +2670,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -2706,7 +2706,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.2" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.6.0" }, "funding": [ { @@ -2722,7 +2722,7 @@ "type": "tidelift" } ], - "time": "2024-12-07T08:49:48+00:00" + "time": "2025-04-29T11:18:49+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -2883,16 +2883,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", "shasum": "" }, "require": { @@ -2910,7 +2910,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -2946,7 +2946,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" }, "funding": [ { @@ -2962,7 +2962,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2025-04-25T09:37:31+00:00" }, { "name": "tbachert/spi", @@ -4816,16 +4816,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.40.19", + "version": "0.41.0", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "05b53cf30c59fe5934d57207fefbc8ae8feb5dbf" + "reference": "96316272a3cee1a3abf5b9f05ae49ebbff03725e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/05b53cf30c59fe5934d57207fefbc8ae8feb5dbf", - "reference": "05b53cf30c59fe5934d57207fefbc8ae8feb5dbf", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/96316272a3cee1a3abf5b9f05ae49ebbff03725e", + "reference": "96316272a3cee1a3abf5b9f05ae49ebbff03725e", "shasum": "" }, "require": { @@ -4861,9 +4861,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.40.19" + "source": "https://github.com/appwrite/sdk-generator/tree/0.41.0" }, - "time": "2025-05-24T22:49:50+00:00" + "time": "2025-05-26T09:47:45+00:00" }, { "name": "doctrine/annotations", @@ -8242,7 +8242,7 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": [], + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { @@ -8266,5 +8266,5 @@ "platform-overrides": { "php": "8.3" }, - "plugin-api-version": "2.3.0" + "plugin-api-version": "2.6.0" } From 2a5ecb2547c8adce3e3d421c6b20271117df10a8 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 26 May 2025 22:25:12 +1200 Subject: [PATCH 118/219] Release cli --- app/config/platforms.php | 2 +- app/config/specs/open-api3-1.7.x-client.json | 2 +- app/config/specs/open-api3-1.7.x-console.json | 30 +++++++++++++++-- app/config/specs/open-api3-1.7.x-server.json | 30 +++++++++++++++-- app/config/specs/open-api3-latest-client.json | 25 +-------------- .../specs/open-api3-latest-console.json | 13 +++----- app/config/specs/open-api3-latest-server.json | 13 +++----- app/config/specs/swagger2-1.7.x-client.json | 2 +- app/config/specs/swagger2-1.7.x-console.json | 32 +++++++++++++++++-- app/config/specs/swagger2-1.7.x-server.json | 32 +++++++++++++++++-- app/config/specs/swagger2-latest-client.json | 25 +-------------- app/config/specs/swagger2-latest-console.json | 15 ++++----- app/config/specs/swagger2-latest-server.json | 15 ++++----- app/controllers/api/databases.php | 2 +- .../examples/databases/upsert-document.md | 6 ++++ .../examples/databases/upsert-documents.md | 2 +- 16 files changed, 149 insertions(+), 97 deletions(-) create mode 100644 docs/examples/1.7.x/console-cli/examples/databases/upsert-document.md diff --git a/app/config/platforms.php b/app/config/platforms.php index 358edd0cf8..7d481d508e 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -217,7 +217,7 @@ return [ [ 'key' => 'cli', 'name' => 'Command Line', - 'version' => '6.2.3', + 'version' => '7.0.0', 'url' => 'https://github.com/appwrite/sdk-for-cli', 'package' => 'https://www.npmjs.com/package/appwrite-cli', 'enabled' => true, diff --git a/app/config/specs/open-api3-1.7.x-client.json b/app/config/specs/open-api3-1.7.x-client.json index abeab8a56f..bbb78c6c66 100644 --- a/app/config/specs/open-api3-1.7.x-client.json +++ b/app/config/specs/open-api3-1.7.x-client.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.7.0", + "version": "1.7.4", "title": "Appwrite", "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", diff --git a/app/config/specs/open-api3-1.7.x-console.json b/app/config/specs/open-api3-1.7.x-console.json index 19ce78915c..90ef137fc2 100644 --- a/app/config/specs/open-api3-1.7.x-console.json +++ b/app/config/specs/open-api3-1.7.x-console.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.7.0", + "version": "1.7.4", "title": "Appwrite", "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -8049,6 +8049,29 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/components\/schemas\/documentList" + } + ], + "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -8204,7 +8227,10 @@ "type": "object" } } - } + }, + "required": [ + "documents" + ] } } } diff --git a/app/config/specs/open-api3-1.7.x-server.json b/app/config/specs/open-api3-1.7.x-server.json index db615d642c..1ae9328864 100644 --- a/app/config/specs/open-api3-1.7.x-server.json +++ b/app/config/specs/open-api3-1.7.x-server.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.7.0", + "version": "1.7.4", "title": "Appwrite", "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -7530,6 +7530,29 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/components\/schemas\/documentList" + } + ], + "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -7688,7 +7711,10 @@ "type": "object" } } - } + }, + "required": [ + "documents" + ] } } } diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index e87a892063..bbb78c6c66 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.7.3", + "version": "1.7.4", "title": "Appwrite", "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -4490,29 +4490,6 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." - }, - { - "name": "createDocuments", - "auth": { - "Key": [] - }, - "parameters": [ - "databaseId", - "collectionId", - "documents" - ], - "required": [ - "databaseId", - "collectionId", - "documents" - ], - "responses": [ - { - "code": 201, - "model": "#\/components\/schemas\/documentList" - } - ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index ad500a8811..90ef137fc2 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.7.3", + "version": "1.7.4", "title": "Appwrite", "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -8227,7 +8227,10 @@ "type": "object" } } - } + }, + "required": [ + "documents" + ] } } } @@ -36587,12 +36590,6 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "default", "nullable": true - }, - "encrypt": { - "type": "boolean", - "description": "Defines whether this attribute is encrypted or not.", - "x-example": false, - "nullable": true } }, "required": [ diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 8ac05cb97b..1ae9328864 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -1,7 +1,7 @@ { "openapi": "3.0.0", "info": { - "version": "1.7.3", + "version": "1.7.4", "title": "Appwrite", "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -7711,7 +7711,10 @@ "type": "object" } } - } + }, + "required": [ + "documents" + ] } } } @@ -26555,12 +26558,6 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "default", "nullable": true - }, - "encrypt": { - "type": "boolean", - "description": "Defines whether this attribute is encrypted or not.", - "x-example": false, - "nullable": true } }, "required": [ diff --git a/app/config/specs/swagger2-1.7.x-client.json b/app/config/specs/swagger2-1.7.x-client.json index 5c1b764e1e..92132151b4 100644 --- a/app/config/specs/swagger2-1.7.x-client.json +++ b/app/config/specs/swagger2-1.7.x-client.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.7.0", + "version": "1.7.4", "title": "Appwrite", "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", diff --git a/app/config/specs/swagger2-1.7.x-console.json b/app/config/specs/swagger2-1.7.x-console.json index 96705f3e61..e53a0dfb0b 100644 --- a/app/config/specs/swagger2-1.7.x-console.json +++ b/app/config/specs/swagger2-1.7.x-console.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.7.0", + "version": "1.7.4", "title": "Appwrite", "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -8178,6 +8178,29 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/definitions\/documentList" + } + ], + "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -8323,13 +8346,16 @@ "documents": { "type": "array", "description": "Array of document data as JSON objects. May contain partial documents.", - "default": [], + "default": null, "x-example": null, "items": { "type": "object" } } - } + }, + "required": [ + "documents" + ] } } ] diff --git a/app/config/specs/swagger2-1.7.x-server.json b/app/config/specs/swagger2-1.7.x-server.json index c033008417..083290bcc0 100644 --- a/app/config/specs/swagger2-1.7.x-server.json +++ b/app/config/specs/swagger2-1.7.x-server.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.7.0", + "version": "1.7.4", "title": "Appwrite", "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -7649,6 +7649,29 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/definitions\/documentList" + } + ], + "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { @@ -7797,13 +7820,16 @@ "documents": { "type": "array", "description": "Array of document data as JSON objects. May contain partial documents.", - "default": [], + "default": null, "x-example": null, "items": { "type": "object" } } - } + }, + "required": [ + "documents" + ] } } ] diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index 972b4a34da..92132151b4 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.7.3", + "version": "1.7.4", "title": "Appwrite", "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -4636,29 +4636,6 @@ } ], "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." - }, - { - "name": "createDocuments", - "auth": { - "Key": [] - }, - "parameters": [ - "databaseId", - "collectionId", - "documents" - ], - "required": [ - "databaseId", - "collectionId", - "documents" - ], - "responses": [ - { - "code": 201, - "model": "#\/definitions\/documentList" - } - ], - "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." } ], "auth": { diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index a52f09d691..e53a0dfb0b 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.7.3", + "version": "1.7.4", "title": "Appwrite", "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -8346,13 +8346,16 @@ "documents": { "type": "array", "description": "Array of document data as JSON objects. May contain partial documents.", - "default": [], + "default": null, "x-example": null, "items": { "type": "object" } } - } + }, + "required": [ + "documents" + ] } } ] @@ -36816,12 +36819,6 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "default", "x-nullable": true - }, - "encrypt": { - "type": "boolean", - "description": "Defines whether this attribute is encrypted or not.", - "x-example": false, - "x-nullable": true } }, "required": [ diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index a37c972aae..083290bcc0 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -1,7 +1,7 @@ { "swagger": "2.0", "info": { - "version": "1.7.3", + "version": "1.7.4", "title": "Appwrite", "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", "termsOfService": "https:\/\/appwrite.io\/policy\/terms", @@ -7820,13 +7820,16 @@ "documents": { "type": "array", "description": "Array of document data as JSON objects. May contain partial documents.", - "default": [], + "default": null, "x-example": null, "items": { "type": "object" } } - } + }, + "required": [ + "documents" + ] } } ] @@ -26851,12 +26854,6 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "default", "x-nullable": true - }, - "encrypt": { - "type": "boolean", - "description": "Defines whether this attribute is encrypted or not.", - "x-example": false, - "x-nullable": true } }, "required": [ diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 277bfae16a..dcf547b688 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4581,7 +4581,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents') )) ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') - ->param('documents', [], fn (array $plan) => new ArrayList(new JSON(), $plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH), 'Array of document data as JSON objects. May contain partial documents.', true, ['plan']) + ->param('documents', [], fn (array $plan) => new ArrayList(new JSON(), $plan['databasesBatchSize'] ?? APP_LIMIT_DATABASE_BATCH), 'Array of document data as JSON objects. May contain partial documents.', false, ['plan']) ->inject('response') ->inject('dbForProject') ->inject('queueForStatsUsage') diff --git a/docs/examples/1.7.x/console-cli/examples/databases/upsert-document.md b/docs/examples/1.7.x/console-cli/examples/databases/upsert-document.md new file mode 100644 index 0000000000..40932014ba --- /dev/null +++ b/docs/examples/1.7.x/console-cli/examples/databases/upsert-document.md @@ -0,0 +1,6 @@ +appwrite databases upsertDocument \ + --databaseId \ + --collectionId \ + --documentId \ + --data '{ "key": "value" }' \ + diff --git a/docs/examples/1.7.x/console-cli/examples/databases/upsert-documents.md b/docs/examples/1.7.x/console-cli/examples/databases/upsert-documents.md index 3d0bd165d5..cb1677b14c 100644 --- a/docs/examples/1.7.x/console-cli/examples/databases/upsert-documents.md +++ b/docs/examples/1.7.x/console-cli/examples/databases/upsert-documents.md @@ -1,4 +1,4 @@ appwrite databases upsertDocuments \ --databaseId \ --collectionId \ - + --documents one two three From 44e16ce98dc1193ef2677802420f3575b6f1284e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Mon, 26 May 2025 12:56:23 +0200 Subject: [PATCH 119/219] Fix commit URLs max length --- app/controllers/api/vcs.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 571c7ddca7..a986d1004b 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -324,7 +324,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId // VCS commit preview if (!empty($providerCommitHash)) { - $domain = "commit-{$providerCommitHash}-{$resource->getId()}-{$project->getId()}.{$sitesDomain}"; + $domain = "commit-{$providerCommitHash}.{$sitesDomain}"; $ruleId = md5($domain); try { Authorization::skip( From f6dd9b0d33b0628ff76f679a5b9717e131c57d87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Mon, 26 May 2025 16:24:27 +0200 Subject: [PATCH 120/219] Fix how we update rules on active deployment --- .../Http/Functions/Deployment/Update.php | 9 +-------- .../Modules/Functions/Workers/Builds.php | 20 +++---------------- .../Sites/Http/Sites/Deployment/Update.php | 9 +-------- 3 files changed, 5 insertions(+), 33 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php index 6de71cfae6..e63d3d3cd6 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -89,8 +89,6 @@ class Update extends Base throw new Exception(Exception::BUILD_NOT_READY); } - $oldDeploymentInternalId = $function->getAttribute('deploymentInternalId', ''); - $function = $dbForProject->updateDocument('functions', $function->getId(), new Document(array_merge($function->getArrayCopy(), [ 'deploymentInternalId' => $deployment->getInternalId(), 'deploymentId' => $deployment->getId(), @@ -110,14 +108,9 @@ class Update extends Base Query::equal("type", ["deployment"]), Query::equal("deploymentResourceType", ["function"]), Query::equal("deploymentResourceInternalId", [$function->getInternalId()]), + Query::equal("deploymentVcsProviderBranch", [""]), ]; - if (empty($oldDeploymentInternalId)) { - $queries[] = Query::equal("deploymentInternalId", [""]); - } else { - $queries[] = Query::equal("deploymentInternalId", [$oldDeploymentInternalId]); - } - $this->listRules($project, $queries, $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 0ecf1d3f73..fd366841e3 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -1075,8 +1075,6 @@ class Builds extends Action $resource->setAttribute('live', true); switch ($resource->getCollection()) { case 'functions': - $oldDeploymentInternalId = $resource->getAttribute('deploymentInternalId', ''); - $resource->setAttribute('deploymentId', $deployment->getId()); $resource->setAttribute('deploymentInternalId', $deployment->getInternalId()); $resource->setAttribute('deploymentCreatedAt', $deployment->getCreatedAt()); @@ -1088,14 +1086,9 @@ class Builds extends Action Query::equal("deploymentResourceInternalId", [$resource->getInternalId()]), Query::equal('deploymentResourceType', ['function']), Query::equal('trigger', ['manual']), + Query::equal('deploymentVcsProviderBranch', ['']), ]; - if (empty($oldDeploymentInternalId)) { - $queries[] = Query::equal("deploymentInternalId", [""]); - } else { - $queries[] = Query::equal("deploymentInternalId", [$oldDeploymentInternalId]); - } - $rulesUpdated = false; $this->listRules($project, $queries, $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment, &$rulesUpdated) { $rulesUpdated = true; @@ -1106,8 +1099,6 @@ class Builds extends Action }); break; case 'sites': - $oldDeploymentInternalId = $resource->getAttribute('deploymentInternalId', ''); - $resource->setAttribute('deploymentId', $deployment->getId()); $resource->setAttribute('deploymentInternalId', $deployment->getInternalId()); $resource->setAttribute('deploymentScreenshotDark', $deployment->getAttribute('screenshotDark', '')); @@ -1120,14 +1111,9 @@ class Builds extends Action Query::equal("deploymentResourceInternalId", [$resource->getInternalId()]), Query::equal('deploymentResourceType', ['site']), Query::equal('trigger', ['manual']), + Query::equal('deploymentVcsProviderBranch', ['']), ]; - if (empty($oldDeploymentInternalId)) { - $queries[] = Query::equal("deploymentInternalId", [""]); - } else { - $queries[] = Query::equal("deploymentInternalId", [$oldDeploymentInternalId]); - } - $this->listRules($project, $queries, $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) @@ -1144,7 +1130,7 @@ class Builds extends Action $branchName = $deployment->getAttribute('providerBranch'); if (!empty($branchName)) { $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); - $domain = "branch-{$branchName}-{$resource->getId()}-{$project->getId()}.{$sitesDomain}"; + $domain = "branch-{$branchName}.{$sitesDomain}"; $ruleId = md5($domain); try { diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php index 7f1681c0f1..7a8fb68499 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -86,8 +86,6 @@ class Update extends Base throw new Exception(Exception::BUILD_NOT_READY); } - $oldDeploymentInternalId = $site->getAttribute('deploymentInternalId', ''); - $site = $dbForProject->updateDocument('sites', $site->getId(), new Document(array_merge($site->getArrayCopy(), [ 'deploymentInternalId' => $deployment->getInternalId(), 'deploymentId' => $deployment->getId(), @@ -101,14 +99,9 @@ class Update extends Base Query::equal("type", ["deployment"]), Query::equal("deploymentResourceType", ["site"]), Query::equal("deploymentResourceInternalId", [$site->getInternalId()]), + Query::equal("deploymentVcsProviderBranch", [""]), ]; - if (empty($oldDeploymentInternalId)) { - $queries[] = Query::equal("deploymentInternalId", [""]); - } else { - $queries[] = Query::equal("deploymentInternalId", [$oldDeploymentInternalId]); - } - $this->listRules($project, $queries, $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) From 51f6751b9441b5b781baf8f15329a553294d9fc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Mon, 26 May 2025 16:39:23 +0200 Subject: [PATCH 121/219] Revert --- src/Appwrite/Platform/Modules/Functions/Workers/Builds.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index fd366841e3..b5bd2ee8e6 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -1130,7 +1130,7 @@ class Builds extends Action $branchName = $deployment->getAttribute('providerBranch'); if (!empty($branchName)) { $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); - $domain = "branch-{$branchName}.{$sitesDomain}"; + $domain = "branch-{$branchName}-{$resource->getId()}-{$project->getId()}.{$sitesDomain}"; $ruleId = md5($domain); try { From 4fafb47508ae085e523b30f0c9ce330053e47e56 Mon Sep 17 00:00:00 2001 From: Fabian Gruber Date: Mon, 26 May 2025 17:42:54 +0200 Subject: [PATCH 122/219] Bring back telemetry for storage. This reverts commit 6906a97c224b9b7b923b1b8862ec0acd712d7125. --- app/init/resources.php | 45 ++++++++++++++++++++++-------------------- app/worker.php | 38 ++++++++++++++++++----------------- composer.lock | 12 +++++------ 3 files changed, 50 insertions(+), 45 deletions(-) diff --git a/app/init/resources.php b/app/init/resources.php index c75df2a362..6ca0522b6c 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -52,6 +52,7 @@ use Utopia\Storage\Device\S3; use Utopia\Storage\Device\Wasabi; use Utopia\Storage\Storage; use Utopia\System\System; +use Utopia\Telemetry\Adapter as Telemetry; use Utopia\Telemetry\Adapter\None as NoTelemetry; use Utopia\Validator\Hostname; use Utopia\Validator\WhiteList; @@ -454,7 +455,7 @@ App::setResource('getLogsDB', function (Group $pools, Cache $cache) { App::setResource('telemetry', fn () => new NoTelemetry()); -App::setResource('cache', function (Group $pools) { +App::setResource('cache', function (Group $pools, Telemetry $telemetry) { $list = Config::getParam('pools-cache', []); $adapters = []; @@ -462,8 +463,10 @@ App::setResource('cache', function (Group $pools) { $adapters[] = new CachePool($pools->get($value)); } - return new Cache(new Sharding($adapters)); -}, ['pools']); + $cache = new Cache(new Sharding($adapters)); + $cache->setTelemetry($telemetry); + return $cache; +}, ['pools', 'telemetry']); App::setResource('redis', function () { $host = System::getEnv('_APP_REDIS_HOST', 'localhost'); @@ -486,24 +489,24 @@ App::setResource('timelimit', function (\Redis $redis) { }; }, ['redis']); -App::setResource('deviceForLocal', function () { - return new Local(); -}); -App::setResource('deviceForFiles', function ($project) { - return getDevice(APP_STORAGE_UPLOADS . '/app-' . $project->getId()); -}, ['project']); -App::setResource('deviceForSites', function ($project) { - return getDevice(APP_STORAGE_SITES . '/app-' . $project->getId()); -}, ['project']); -App::setResource('deviceForImports', function ($project) { - return getDevice(APP_STORAGE_IMPORTS . '/app-' . $project->getId()); -}, ['project']); -App::setResource('deviceForFunctions', function ($project) { - return getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId()); -}, ['project']); -App::setResource('deviceForBuilds', function ($project) { - return getDevice(APP_STORAGE_BUILDS . '/app-' . $project->getId()); -}, ['project']); +App::setResource('deviceForLocal', function (Telemetry $telemetry) { + return new Device\Telemetry($telemetry, new Local()); +}, ['telemetry']); +App::setResource('deviceForFiles', function ($project, Telemetry $telemetry) { + return new Device\Telemetry($telemetry, getDevice(APP_STORAGE_UPLOADS . '/app-' . $project->getId())); +}, ['project', 'telemetry']); +App::setResource('deviceForSites', function ($project, Telemetry $telemetry) { + return new Device\Telemetry($telemetry, getDevice(APP_STORAGE_SITES . '/app-' . $project->getId())); +}, ['project', 'telemetry']); +App::setResource('deviceForImports', function ($project, Telemetry $telemetry) { + return new Device\Telemetry($telemetry, getDevice(APP_STORAGE_IMPORTS . '/app-' . $project->getId())); +}, ['project', 'telemetry']); +App::setResource('deviceForFunctions', function ($project, Telemetry $telemetry) { + return new Device\Telemetry($telemetry, getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId())); +}, ['project', 'telemetry']); +App::setResource('deviceForBuilds', function ($project, Telemetry $telemetry) { + return new Device\Telemetry($telemetry, getDevice(APP_STORAGE_BUILDS . '/app-' . $project->getId())); +}, ['project', 'telemetry']); function getDevice(string $root, string $connection = ''): Device { diff --git a/app/worker.php b/app/worker.php index 597e8a9943..c92c48936f 100644 --- a/app/worker.php +++ b/app/worker.php @@ -40,7 +40,9 @@ use Utopia\Queue\Message; use Utopia\Queue\Publisher; use Utopia\Queue\Server; use Utopia\Registry\Registry; +use Utopia\Storage\Device\Telemetry as TelemetryDevice; use Utopia\System\System; +use Utopia\Telemetry\Adapter as Telemetry; use Utopia\Telemetry\Adapter\None as NoTelemetry; Authorization::disable(); @@ -311,29 +313,29 @@ Server::setResource('pools', function (Registry $register) { Server::setResource('telemetry', fn () => new NoTelemetry()); -Server::setResource('deviceForSites', function (Document $project) { - return getDevice(APP_STORAGE_SITES . '/app-' . $project->getId()); -}, ['project']); +Server::setResource('deviceForSites', function (Document $project, Telemetry $telemetry) { + return new TelemetryDevice($telemetry, getDevice(APP_STORAGE_SITES . '/app-' . $project->getId())); +}, ['project', 'telemetry']); -Server::setResource('deviceForImports', function (Document $project) { - return getDevice(APP_STORAGE_IMPORTS . '/app-' . $project->getId()); -}, ['project']); +Server::setResource('deviceForImports', function (Document $project, Telemetry $telemetry) { + return new TelemetryDevice($telemetry, getDevice(APP_STORAGE_IMPORTS . '/app-' . $project->getId())); +}, ['project', 'telemetry']); -Server::setResource('deviceForFunctions', function (Document $project) { - return getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId()); -}, ['project']); +Server::setResource('deviceForFunctions', function (Document $project, Telemetry $telemetry) { + return new TelemetryDevice($telemetry, getDevice(APP_STORAGE_FUNCTIONS . '/app-' . $project->getId())); +}, ['project', 'telemetry']); -Server::setResource('deviceForFiles', function (Document $project) { - return getDevice(APP_STORAGE_UPLOADS . '/app-' . $project->getId()); -}, ['project']); +Server::setResource('deviceForFiles', function (Document $project, Telemetry $telemetry) { + return new TelemetryDevice($telemetry, getDevice(APP_STORAGE_UPLOADS . '/app-' . $project->getId())); +}, ['project', 'telemetry']); -Server::setResource('deviceForBuilds', function (Document $project) { - return getDevice(APP_STORAGE_BUILDS . '/app-' . $project->getId()); -}, ['project']); +Server::setResource('deviceForBuilds', function (Document $project, Telemetry $telemetry) { + return new TelemetryDevice($telemetry, getDevice(APP_STORAGE_BUILDS . '/app-' . $project->getId())); +}, ['project', 'telemetry']); -Server::setResource('deviceForCache', function (Document $project) { - return getDevice(APP_STORAGE_CACHE . '/app-' . $project->getId()); -}, ['project']); +Server::setResource('deviceForCache', function (Document $project, Telemetry $telemetry) { + return new TelemetryDevice($telemetry, getDevice(APP_STORAGE_CACHE . '/app-' . $project->getId())); +}, ['project', 'telemetry']); Server::setResource( 'isResourceBlocked', diff --git a/composer.lock b/composer.lock index 875f012fc9..0ffe052061 100644 --- a/composer.lock +++ b/composer.lock @@ -4378,16 +4378,16 @@ }, { "name": "utopia-php/storage", - "version": "0.18.12", + "version": "0.18.13", "source": { "type": "git", "url": "https://github.com/utopia-php/storage.git", - "reference": "9a2556c39b5f4d9f8e79111fd34ec889b7bb1e97" + "reference": "3d8ce53ae042173bf230445e996056c5f65ded22" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/storage/zipball/9a2556c39b5f4d9f8e79111fd34ec889b7bb1e97", - "reference": "9a2556c39b5f4d9f8e79111fd34ec889b7bb1e97", + "url": "https://api.github.com/repos/utopia-php/storage/zipball/3d8ce53ae042173bf230445e996056c5f65ded22", + "reference": "3d8ce53ae042173bf230445e996056c5f65ded22", "shasum": "" }, "require": { @@ -4430,9 +4430,9 @@ ], "support": { "issues": "https://github.com/utopia-php/storage/issues", - "source": "https://github.com/utopia-php/storage/tree/0.18.12" + "source": "https://github.com/utopia-php/storage/tree/0.18.13" }, - "time": "2025-05-15T07:55:58+00:00" + "time": "2025-05-26T13:10:35+00:00" }, { "name": "utopia-php/swoole", From deffe25c305cf35dcd97e306aeac6129a6e55819 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Mon, 26 May 2025 17:54:06 +0200 Subject: [PATCH 123/219] Fix queries not updating well --- .../Modules/Functions/Http/Functions/Deployment/Update.php | 2 +- .../Platform/Modules/Sites/Http/Sites/Deployment/Update.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php index e63d3d3cd6..d97bb92b73 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -104,7 +104,7 @@ class Update extends Base Authorization::skip(fn () => $dbForPlatform->updateDocument('schedules', $schedule->getId(), $schedule)); $queries = [ - Query::equal('trigger', 'manual'), + Query::equal('trigger', ['manual']), Query::equal("type", ["deployment"]), Query::equal("deploymentResourceType", ["function"]), Query::equal("deploymentResourceInternalId", [$function->getInternalId()]), diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php index 7a8fb68499..aa36b52c5a 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -95,7 +95,7 @@ class Update extends Base ]))); $queries = [ - Query::equal('trigger', 'manual'), + Query::equal('trigger', ['manual']), Query::equal("type", ["deployment"]), Query::equal("deploymentResourceType", ["site"]), Query::equal("deploymentResourceInternalId", [$site->getInternalId()]), From 35585fe8644aeded5496a18a4d0a2a1bd4b2a4d8 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 27 May 2025 13:06:40 +1200 Subject: [PATCH 124/219] Update lock --- composer.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/composer.lock b/composer.lock index a8cba31c4b..2f55d5d894 100644 --- a/composer.lock +++ b/composer.lock @@ -3953,16 +3953,16 @@ }, { "name": "utopia-php/migration", - "version": "0.10.0", + "version": "0.10.1", "source": { "type": "git", "url": "https://github.com/utopia-php/migration.git", - "reference": "0b0e94c4b5243c5566b9634b07ba2ec5f7990914" + "reference": "ea1c585df7ec5f346f061a11581fc9a91679966f" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/migration/zipball/0b0e94c4b5243c5566b9634b07ba2ec5f7990914", - "reference": "0b0e94c4b5243c5566b9634b07ba2ec5f7990914", + "url": "https://api.github.com/repos/utopia-php/migration/zipball/ea1c585df7ec5f346f061a11581fc9a91679966f", + "reference": "ea1c585df7ec5f346f061a11581fc9a91679966f", "shasum": "" }, "require": { @@ -4003,9 +4003,9 @@ ], "support": { "issues": "https://github.com/utopia-php/migration/issues", - "source": "https://github.com/utopia-php/migration/tree/0.10.0" + "source": "https://github.com/utopia-php/migration/tree/0.10.1" }, - "time": "2025-05-23T07:40:24+00:00" + "time": "2025-05-26T15:29:19+00:00" }, { "name": "utopia-php/orchestration", @@ -4332,16 +4332,16 @@ }, { "name": "utopia-php/storage", - "version": "0.18.12", + "version": "0.18.13", "source": { "type": "git", "url": "https://github.com/utopia-php/storage.git", - "reference": "9a2556c39b5f4d9f8e79111fd34ec889b7bb1e97" + "reference": "3d8ce53ae042173bf230445e996056c5f65ded22" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/storage/zipball/9a2556c39b5f4d9f8e79111fd34ec889b7bb1e97", - "reference": "9a2556c39b5f4d9f8e79111fd34ec889b7bb1e97", + "url": "https://api.github.com/repos/utopia-php/storage/zipball/3d8ce53ae042173bf230445e996056c5f65ded22", + "reference": "3d8ce53ae042173bf230445e996056c5f65ded22", "shasum": "" }, "require": { @@ -4384,9 +4384,9 @@ ], "support": { "issues": "https://github.com/utopia-php/storage/issues", - "source": "https://github.com/utopia-php/storage/tree/0.18.12" + "source": "https://github.com/utopia-php/storage/tree/0.18.13" }, - "time": "2025-05-15T07:55:58+00:00" + "time": "2025-05-26T13:10:35+00:00" }, { "name": "utopia-php/swoole", From 2d293171792b6fdbe4c82e394761444214f28f89 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 27 May 2025 13:38:26 +1200 Subject: [PATCH 125/219] Update lock --- composer.lock | 164 +++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 134 insertions(+), 30 deletions(-) diff --git a/composer.lock b/composer.lock index 2f55d5d894..bfaebeeba6 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "c0326e442e6920411bf4e7634da0abad", + "content-hash": "34142c56876c7ee1e2a798616b8ff114", "packages": [ { "name": "adhocore/jwt", @@ -157,16 +157,16 @@ }, { "name": "appwrite/php-runtimes", - "version": "0.16.5", + "version": "0.19.0", "source": { "type": "git", "url": "https://github.com/appwrite/runtimes.git", - "reference": "1e430646fdf847a7caf3c611dcf3d6d5a28c3fd9" + "reference": "8d21483efc19b9d977e323188989ee67a188464b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/runtimes/zipball/1e430646fdf847a7caf3c611dcf3d6d5a28c3fd9", - "reference": "1e430646fdf847a7caf3c611dcf3d6d5a28c3fd9", + "url": "https://api.github.com/repos/appwrite/runtimes/zipball/8d21483efc19b9d977e323188989ee67a188464b", + "reference": "8d21483efc19b9d977e323188989ee67a188464b", "shasum": "" }, "require": { @@ -206,9 +206,9 @@ ], "support": { "issues": "https://github.com/appwrite/runtimes/issues", - "source": "https://github.com/appwrite/runtimes/tree/0.16.5" + "source": "https://github.com/appwrite/runtimes/tree/0.19.0" }, - "time": "2024-11-25T15:17:06+00:00" + "time": "2025-03-25T22:37:51+00:00" }, { "name": "beberlei/assert", @@ -3554,25 +3554,71 @@ "time": "2025-05-23T07:32:59+00:00" }, { - "name": "utopia-php/domains", - "version": "0.5.0", + "name": "utopia-php/detector", + "version": "0.1.5", "source": { "type": "git", - "url": "https://github.com/utopia-php/domains.git", - "reference": "bf07f60326f8389f378ddf6fcde86217e5cfe18c" + "url": "https://github.com/utopia-php/detector.git", + "reference": "b5d6ba51352485b524589bc0ee8d07a9efafe718" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/domains/zipball/bf07f60326f8389f378ddf6fcde86217e5cfe18c", - "reference": "bf07f60326f8389f378ddf6fcde86217e5cfe18c", + "url": "https://api.github.com/repos/utopia-php/detector/zipball/b5d6ba51352485b524589bc0ee8d07a9efafe718", + "reference": "b5d6ba51352485b524589bc0ee8d07a9efafe718", + "shasum": "" + }, + "require": { + "php": ">=8.0" + }, + "require-dev": { + "laravel/pint": "1.2.*", + "phpstan/phpstan": "1.8.*", + "phpunit/phpunit": "^9.4" + }, + "type": "library", + "autoload": { + "psr-4": { + "Utopia\\Detector\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "A simple library for fast and reliable environment identification.", + "keywords": [ + "detector", + "framework", + "php", + "utopia" + ], + "support": { + "issues": "https://github.com/utopia-php/detector/issues", + "source": "https://github.com/utopia-php/detector/tree/0.1.5" + }, + "time": "2025-05-19T11:01:28+00:00" + }, + { + "name": "utopia-php/domains", + "version": "0.8.0", + "source": { + "type": "git", + "url": "https://github.com/utopia-php/domains.git", + "reference": "650463d2a1525273eb03223c48da9fb1a768bbf7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/utopia-php/domains/zipball/650463d2a1525273eb03223c48da9fb1a768bbf7", + "reference": "650463d2a1525273eb03223c48da9fb1a768bbf7", "shasum": "" }, "require": { "php": ">=8.0", - "utopia-php/framework": "0.*.*" + "utopia-php/framework": "0.33.*" }, "require-dev": { "laravel/pint": "1.2.*", + "phpstan/phpstan": "1.9.x-dev", "phpunit/phpunit": "^9.3" }, "type": "library", @@ -3609,9 +3655,9 @@ ], "support": { "issues": "https://github.com/utopia-php/domains/issues", - "source": "https://github.com/utopia-php/domains/tree/0.5.0" + "source": "https://github.com/utopia-php/domains/tree/0.8.0" }, - "time": "2024-01-03T22:04:27+00:00" + "time": "2025-05-16T10:03:59+00:00" }, { "name": "utopia-php/dsn", @@ -4547,16 +4593,16 @@ }, { "name": "utopia-php/vcs", - "version": "0.9.5", + "version": "0.10.2", "source": { "type": "git", "url": "https://github.com/utopia-php/vcs.git", - "reference": "055956545ca7ab4e8688df5de1df3e2833859793" + "reference": "1f9823ebcb8fd098607de0074f18f48e28985012" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/vcs/zipball/055956545ca7ab4e8688df5de1df3e2833859793", - "reference": "055956545ca7ab4e8688df5de1df3e2833859793", + "url": "https://api.github.com/repos/utopia-php/vcs/zipball/1f9823ebcb8fd098607de0074f18f48e28985012", + "reference": "1f9823ebcb8fd098607de0074f18f48e28985012", "shasum": "" }, "require": { @@ -4574,8 +4620,7 @@ "type": "library", "autoload": { "psr-4": { - "Utopia\\VCS\\": "src/VCS", - "Utopia\\Detector\\": "src/Detector" + "Utopia\\VCS\\": "src/VCS" } }, "notification-url": "https://packagist.org/downloads/", @@ -4591,9 +4636,9 @@ ], "support": { "issues": "https://github.com/utopia-php/vcs/issues", - "source": "https://github.com/utopia-php/vcs/tree/0.9.5" + "source": "https://github.com/utopia-php/vcs/tree/0.10.2" }, - "time": "2025-04-17T04:38:49+00:00" + "time": "2025-04-17T04:35:25+00:00" }, { "name": "utopia-php/websocket", @@ -4771,16 +4816,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.40.19", + "version": "0.41.0", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "05b53cf30c59fe5934d57207fefbc8ae8feb5dbf" + "reference": "96316272a3cee1a3abf5b9f05ae49ebbff03725e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/05b53cf30c59fe5934d57207fefbc8ae8feb5dbf", - "reference": "05b53cf30c59fe5934d57207fefbc8ae8feb5dbf", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/96316272a3cee1a3abf5b9f05ae49ebbff03725e", + "reference": "96316272a3cee1a3abf5b9f05ae49ebbff03725e", "shasum": "" }, "require": { @@ -4816,9 +4861,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.40.19" + "source": "https://github.com/appwrite/sdk-generator/tree/0.41.0" }, - "time": "2025-05-24T22:49:50+00:00" + "time": "2025-05-26T09:47:45+00:00" }, { "name": "doctrine/annotations", @@ -5618,6 +5663,65 @@ ], "time": "2025-03-12T08:01:40+00:00" }, + { + "name": "phpstan/phpstan", + "version": "1.8.11", + "source": { + "type": "git", + "url": "https://github.com/phpstan/phpstan.git", + "reference": "46e223dd68a620da18855c23046ddb00940b4014" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpstan/phpstan/zipball/46e223dd68a620da18855c23046ddb00940b4014", + "reference": "46e223dd68a620da18855c23046ddb00940b4014", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0" + }, + "conflict": { + "phpstan/phpstan-shim": "*" + }, + "bin": [ + "phpstan", + "phpstan.phar" + ], + "type": "library", + "autoload": { + "files": [ + "bootstrap.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "description": "PHPStan - PHP Static Analysis Tool", + "keywords": [ + "dev", + "static analysis" + ], + "support": { + "issues": "https://github.com/phpstan/phpstan/issues", + "source": "https://github.com/phpstan/phpstan/tree/1.8.11" + }, + "funding": [ + { + "url": "https://github.com/ondrejmirtes", + "type": "github" + }, + { + "url": "https://github.com/phpstan", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpstan/phpstan", + "type": "tidelift" + } + ], + "time": "2022-10-24T15:45:13+00:00" + }, { "name": "phpunit/php-code-coverage", "version": "9.2.32", From dd25072cdf39e13892267cc87657248430b811d9 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 23 May 2025 09:03:42 +0000 Subject: [PATCH 126/219] Merge pull request #9868 from ArnabChatterjee20k/dat-532 added encrypt property in the attribute string response model # Conflicts: # tests/e2e/Services/Databases/DatabasesCustomServerTest.php --- app/init/database/filters.php | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/app/init/database/filters.php b/app/init/database/filters.php index 73ff7dc221..98a37ec4ad 100644 --- a/app/init/database/filters.php +++ b/app/init/database/filters.php @@ -77,12 +77,21 @@ Database::addFilter( ]); foreach ($attributes as $attribute) { - if ($attribute->getAttribute('type') === Database::VAR_RELATIONSHIP) { - $options = $attribute->getAttribute('options'); - foreach ($options as $key => $value) { - $attribute->setAttribute($key, $value); - } - $attribute->removeAttribute('options'); + $attributeType = $attribute->getAttribute('type'); + + switch ($attributeType) { + case Database::VAR_RELATIONSHIP: + $options = $attribute->getAttribute('options'); + foreach ($options as $key => $value) { + $attribute->setAttribute($key, $value); + } + $attribute->removeAttribute('options'); + break; + + case Database::VAR_STRING: + $filters = $attribute->getAttribute('filters', []); + $attribute->setAttribute('encrypt', in_array('encrypt', $filters)); + break; } } From 8e8402fbd87ce7da019692735d55b3adb5dbb700 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 27 May 2025 16:54:58 +1200 Subject: [PATCH 127/219] Coderabbit --- .coderabbit.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.coderabbit.yaml b/.coderabbit.yaml index ec2953a161..822c470cd8 100644 --- a/.coderabbit.yaml +++ b/.coderabbit.yaml @@ -8,4 +8,5 @@ reviews: base_branches: - main - 1.6.x - - 1.7.x \ No newline at end of file + - 1.7.x + - 1.8.x \ No newline at end of file From 968b6302d0c54b50a7d143eccf8d0f8b1e19f1dc Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 27 May 2025 07:36:28 +0000 Subject: [PATCH 128/219] Feat: add flutter 3.32 and dart 3.8 --- .env | 2 +- app/config/template-runtimes.php | 4 ++-- app/views/install/compose.phtml | 2 +- docker-compose.yml | 2 +- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.env b/.env index d7aa8b8d9e..b7dd9e24f3 100644 --- a/.env +++ b/.env @@ -85,7 +85,7 @@ _APP_COMPUTE_RUNTIMES_NETWORK=runtimes _APP_EXECUTOR_SECRET=your-secret-key _APP_EXECUTOR_HOST=http://exc1/v1 _APP_FUNCTIONS_RUNTIMES=php-8.0,node-18.0,python-3.9,ruby-3.1 -_APP_SITES_RUNTIMES=static-1,node-22,flutter-3.29 +_APP_SITES_RUNTIMES=static-1,node-22,flutter-3.32 _APP_MAINTENANCE_INTERVAL=86400 _APP_MAINTENANCE_START_TIME=12:00 _APP_MAINTENANCE_RETENTION_CACHE=2592000 diff --git a/app/config/template-runtimes.php b/app/config/template-runtimes.php index 8f1c0198c2..d1bb1a5b6a 100644 --- a/app/config/template-runtimes.php +++ b/app/config/template-runtimes.php @@ -14,7 +14,7 @@ return [ ], 'DART' => [ 'name' => 'dart', - 'versions' => ['3.5', '3.3', '3.1', '3.0', '2.19', '2.18', '2.17', '2.16'] + 'versions' => ['3.8', '3.5', '3.3', '3.1', '3.0', '2.19', '2.18', '2.17', '2.16'] ], 'GO' => [ 'name' => 'go', @@ -38,6 +38,6 @@ return [ ], 'FLUTTER' => [ 'name' => 'flutter', - 'versions' => ['3.24'] + 'versions' => ['3.32', '3.24'] ], ]; diff --git a/app/views/install/compose.phtml b/app/views/install/compose.phtml index 7a25898647..2d8f2b35ab 100644 --- a/app/views/install/compose.phtml +++ b/app/views/install/compose.phtml @@ -864,7 +864,7 @@ $image = $this->getParam('image', ''); <<: *x-logging restart: unless-stopped stop_signal: SIGINT - image: openruntimes/executor:0.7.14 + image: openruntimes/executor:0.7.20 networks: - appwrite - runtimes diff --git a/docker-compose.yml b/docker-compose.yml index 18dc0aa7b7..cefd082c2f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -951,7 +951,7 @@ services: hostname: exc1 <<: *x-logging stop_signal: SIGINT - image: openruntimes/executor:0.7.16 + image: openruntimes/executor:0.7.20 restart: unless-stopped networks: - appwrite From 8a09a4b4153547cd74a42f30e118d8202c7c7b95 Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Tue, 27 May 2025 08:21:31 +0000 Subject: [PATCH 129/219] fix linter --- composer.json | 8 +-- composer.lock | 172 ++++++++++++++++++++++++++------------------------ 2 files changed, 93 insertions(+), 87 deletions(-) diff --git a/composer.json b/composer.json index a5feb2fddc..f377a44910 100644 --- a/composer.json +++ b/composer.json @@ -74,10 +74,10 @@ "utopia-php/vcs": "0.9.*", "utopia-php/websocket": "0.3.*", "matomo/device-detector": "6.1.*", - "dragonmantank/cron-expression": "3.3.2", - "phpmailer/phpmailer": "6.9.1", - "chillerlan/php-qrcode": "4.3.4", - "adhocore/jwt": "1.1.2", + "dragonmantank/cron-expression": "^3.3.2", + "phpmailer/phpmailer": "^6.9.1", + "chillerlan/php-qrcode": "^4.3.4", + "adhocore/jwt": "^1.1.2", "spomky-labs/otphp": "^10.0", "webonyx/graphql-php": "14.11.*", "league/csv": "9.14.*" diff --git a/composer.lock b/composer.lock index 8eb130cfca..f5eef2b00f 100644 --- a/composer.lock +++ b/composer.lock @@ -4,27 +4,27 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "63feb1a7cf4cfa2cc7fa0870236e61ea", + "content-hash": "da423b25b2bd26a7e8768bbf0b172044", "packages": [ { "name": "adhocore/jwt", - "version": "1.1.2", + "version": "1.1.3", "source": { "type": "git", "url": "https://github.com/adhocore/php-jwt.git", - "reference": "6c434af7170090bb7a8880d2bc220a2254ba7899" + "reference": "ad417603d9d45578b6af2089ad5b78f101c82367" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/adhocore/php-jwt/zipball/6c434af7170090bb7a8880d2bc220a2254ba7899", - "reference": "6c434af7170090bb7a8880d2bc220a2254ba7899", + "url": "https://api.github.com/repos/adhocore/php-jwt/zipball/ad417603d9d45578b6af2089ad5b78f101c82367", + "reference": "ad417603d9d45578b6af2089ad5b78f101c82367", "shasum": "" }, "require": { "php": "^7.0 || ^8.0" }, "require-dev": { - "phpunit/phpunit": "^6.5 || ^7.5" + "phpunit/phpunit": "^7.5 || ^8.5" }, "type": "library", "autoload": { @@ -53,15 +53,19 @@ ], "support": { "issues": "https://github.com/adhocore/php-jwt/issues", - "source": "https://github.com/adhocore/php-jwt/tree/1.1.2" + "source": "https://github.com/adhocore/php-jwt/tree/1.1.3" }, "funding": [ { "url": "https://paypal.me/ji10", "type": "custom" + }, + { + "url": "https://github.com/adhocore", + "type": "github" } ], - "time": "2021-02-20T09:56:44+00:00" + "time": "2025-02-18T01:00:50+00:00" }, { "name": "appwrite/appwrite", @@ -339,31 +343,34 @@ }, { "name": "chillerlan/php-qrcode", - "version": "4.3.4", + "version": "4.4.2", "source": { "type": "git", "url": "https://github.com/chillerlan/php-qrcode.git", - "reference": "2ca4bf5ae048af1981d1023ee42a0a2a9d51e51d" + "reference": "345ed8e4ffb56e6b3fcd9f42e3970b9026fa6ce4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/2ca4bf5ae048af1981d1023ee42a0a2a9d51e51d", - "reference": "2ca4bf5ae048af1981d1023ee42a0a2a9d51e51d", + "url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/345ed8e4ffb56e6b3fcd9f42e3970b9026fa6ce4", + "reference": "345ed8e4ffb56e6b3fcd9f42e3970b9026fa6ce4", "shasum": "" }, "require": { - "chillerlan/php-settings-container": "^2.1.4", + "chillerlan/php-settings-container": "^2.1.6 || ^3.2.1", "ext-mbstring": "*", "php": "^7.4 || ^8.0" }, "require-dev": { - "phan/phan": "^5.3", - "phpunit/phpunit": "^9.5", - "setasign/fpdf": "^1.8.2" + "phan/phan": "^5.4.5", + "phpmd/phpmd": "^2.15", + "phpunit/phpunit": "^9.6", + "setasign/fpdf": "^1.8.2", + "squizlabs/php_codesniffer": "^3.11" }, "suggest": { "chillerlan/php-authenticator": "Yet another Google authenticator! Also creates URIs for mobile apps.", - "setasign/fpdf": "Required to use the QR FPDF output." + "setasign/fpdf": "Required to use the QR FPDF output.", + "simple-icons/simple-icons": "SVG icons that you can use to embed as logos in the QR Code" }, "type": "library", "autoload": { @@ -390,7 +397,7 @@ "homepage": "https://github.com/chillerlan/php-qrcode/graphs/contributors" } ], - "description": "A QR code generator. PHP 7.4+", + "description": "A QR code generator with a user friendly API. PHP 7.4+", "homepage": "https://github.com/chillerlan/php-qrcode", "keywords": [ "phpqrcode", @@ -401,43 +408,39 @@ ], "support": { "issues": "https://github.com/chillerlan/php-qrcode/issues", - "source": "https://github.com/chillerlan/php-qrcode/tree/4.3.4" + "source": "https://github.com/chillerlan/php-qrcode/tree/4.4.2" }, "funding": [ - { - "url": "https://www.paypal.com/donate?hosted_button_id=WLYUNAT9ZTJZ4", - "type": "custom" - }, { "url": "https://ko-fi.com/codemasher", "type": "ko_fi" } ], - "time": "2022-07-25T09:12:45+00:00" + "time": "2024-11-15T15:36:24+00:00" }, { "name": "chillerlan/php-settings-container", - "version": "2.1.6", + "version": "3.2.1", "source": { "type": "git", "url": "https://github.com/chillerlan/php-settings-container.git", - "reference": "5553558bd381fce5108c6d0343c12e488cfec6bb" + "reference": "95ed3e9676a1d47cab2e3174d19b43f5dbf52681" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/5553558bd381fce5108c6d0343c12e488cfec6bb", - "reference": "5553558bd381fce5108c6d0343c12e488cfec6bb", + "url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/95ed3e9676a1d47cab2e3174d19b43f5dbf52681", + "reference": "95ed3e9676a1d47cab2e3174d19b43f5dbf52681", "shasum": "" }, "require": { "ext-json": "*", - "php": "^7.4 || ^8.0" + "php": "^8.1" }, "require-dev": { "phpmd/phpmd": "^2.15", "phpstan/phpstan": "^1.11", "phpstan/phpstan-deprecation-rules": "^1.2", - "phpunit/phpunit": "^9.6", + "phpunit/phpunit": "^10.5", "squizlabs/php_codesniffer": "^3.10" }, "type": "library", @@ -457,10 +460,9 @@ "homepage": "https://github.com/codemasher" } ], - "description": "A container class for immutable settings objects. Not a DI container. PHP 7.4+", + "description": "A container class for immutable settings objects. Not a DI container.", "homepage": "https://github.com/chillerlan/php-settings-container", "keywords": [ - "PHP7", "Settings", "configuration", "container", @@ -480,7 +482,7 @@ "type": "ko_fi" } ], - "time": "2024-07-17T01:04:28+00:00" + "time": "2024-07-16T11:13:48+00:00" }, { "name": "composer/semver", @@ -565,16 +567,16 @@ }, { "name": "dragonmantank/cron-expression", - "version": "v3.3.2", + "version": "v3.4.0", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8" + "reference": "8c784d071debd117328803d86b2097615b457500" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/782ca5968ab8b954773518e9e49a6f892a34b2a8", - "reference": "782ca5968ab8b954773518e9e49a6f892a34b2a8", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500", + "reference": "8c784d071debd117328803d86b2097615b457500", "shasum": "" }, "require": { @@ -587,10 +589,14 @@ "require-dev": { "phpstan/extension-installer": "^1.0", "phpstan/phpstan": "^1.0", - "phpstan/phpstan-webmozart-assert": "^1.0", "phpunit/phpunit": "^7.0|^8.0|^9.0" }, "type": "library", + "extra": { + "branch-alias": { + "dev-master": "3.x-dev" + } + }, "autoload": { "psr-4": { "Cron\\": "src/Cron/" @@ -614,7 +620,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.2" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0" }, "funding": [ { @@ -622,7 +628,7 @@ "type": "github" } ], - "time": "2022-09-10T18:51:20+00:00" + "time": "2024-10-09T13:47:03+00:00" }, { "name": "giggsey/libphonenumber-for-php-lite", @@ -1238,16 +1244,16 @@ }, { "name": "open-telemetry/exporter-otlp", - "version": "1.3.0", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/exporter-otlp.git", - "reference": "19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c" + "reference": "8b3ca1f86d01429c73b407bf1a2075d9c187001e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c", - "reference": "19adf03d2b0f91f9e9b1c7f93db6c755c737cf6c", + "url": "https://api.github.com/repos/opentelemetry-php/exporter-otlp/zipball/8b3ca1f86d01429c73b407bf1a2075d9c187001e", + "reference": "8b3ca1f86d01429c73b407bf1a2075d9c187001e", "shasum": "" }, "require": { @@ -1298,7 +1304,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-12T00:36:35+00:00" + "time": "2025-05-21T12:02:20+00:00" }, { "name": "open-telemetry/gen-otlp-protobuf", @@ -1365,16 +1371,16 @@ }, { "name": "open-telemetry/sdk", - "version": "1.4.0", + "version": "1.5.0", "source": { "type": "git", "url": "https://github.com/opentelemetry-php/sdk.git", - "reference": "939d3a28395c249a763676458140dad44b3a8011" + "reference": "cd0d7367599717fc29e04eb8838ec061e6c2c657" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/939d3a28395c249a763676458140dad44b3a8011", - "reference": "939d3a28395c249a763676458140dad44b3a8011", + "url": "https://api.github.com/repos/opentelemetry-php/sdk/zipball/cd0d7367599717fc29e04eb8838ec061e6c2c657", + "reference": "cd0d7367599717fc29e04eb8838ec061e6c2c657", "shasum": "" }, "require": { @@ -1451,7 +1457,7 @@ "issues": "https://github.com/open-telemetry/opentelemetry-php/issues", "source": "https://github.com/open-telemetry/opentelemetry-php" }, - "time": "2025-05-07T12:32:21+00:00" + "time": "2025-05-22T02:33:34+00:00" }, { "name": "open-telemetry/sem-conv", @@ -2486,16 +2492,16 @@ }, { "name": "symfony/deprecation-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/deprecation-contracts.git", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6" + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", - "reference": "74c71c939a79f7d5bf3c1ce9f5ea37ba0114c6f6", + "url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/63afe740e99a13ba87ec199bb07bbdee937a5b62", + "reference": "63afe740e99a13ba87ec199bb07bbdee937a5b62", "shasum": "" }, "require": { @@ -2508,7 +2514,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -2533,7 +2539,7 @@ "description": "A generic function and convention to trigger deprecation notices", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/deprecation-contracts/tree/v3.6.0" }, "funding": [ { @@ -2549,7 +2555,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2024-09-25T14:21:43+00:00" }, { "name": "symfony/http-client", @@ -2648,16 +2654,16 @@ }, { "name": "symfony/http-client-contracts", - "version": "v3.5.2", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client-contracts.git", - "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645" + "reference": "75d7043853a42837e68111812f4d964b01e5101c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/ee8d807ab20fcb51267fdace50fbe3494c31e645", - "reference": "ee8d807ab20fcb51267fdace50fbe3494c31e645", + "url": "https://api.github.com/repos/symfony/http-client-contracts/zipball/75d7043853a42837e68111812f4d964b01e5101c", + "reference": "75d7043853a42837e68111812f4d964b01e5101c", "shasum": "" }, "require": { @@ -2670,7 +2676,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -2706,7 +2712,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/http-client-contracts/tree/v3.5.2" + "source": "https://github.com/symfony/http-client-contracts/tree/v3.6.0" }, "funding": [ { @@ -2722,7 +2728,7 @@ "type": "tidelift" } ], - "time": "2024-12-07T08:49:48+00:00" + "time": "2025-04-29T11:18:49+00:00" }, { "name": "symfony/polyfill-mbstring", @@ -2883,16 +2889,16 @@ }, { "name": "symfony/service-contracts", - "version": "v3.5.1", + "version": "v3.6.0", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0" + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/e53260aabf78fb3d63f8d79d69ece59f80d5eda0", - "reference": "e53260aabf78fb3d63f8d79d69ece59f80d5eda0", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/f021b05a130d35510bd6b25fe9053c2a8a15d5d4", + "reference": "f021b05a130d35510bd6b25fe9053c2a8a15d5d4", "shasum": "" }, "require": { @@ -2910,7 +2916,7 @@ "name": "symfony/contracts" }, "branch-alias": { - "dev-main": "3.5-dev" + "dev-main": "3.6-dev" } }, "autoload": { @@ -2946,7 +2952,7 @@ "standards" ], "support": { - "source": "https://github.com/symfony/service-contracts/tree/v3.5.1" + "source": "https://github.com/symfony/service-contracts/tree/v3.6.0" }, "funding": [ { @@ -2962,7 +2968,7 @@ "type": "tidelift" } ], - "time": "2024-09-25T14:20:29+00:00" + "time": "2025-04-25T09:37:31+00:00" }, { "name": "tbachert/spi", @@ -4332,16 +4338,16 @@ }, { "name": "utopia-php/storage", - "version": "0.18.12", + "version": "0.18.13", "source": { "type": "git", "url": "https://github.com/utopia-php/storage.git", - "reference": "9a2556c39b5f4d9f8e79111fd34ec889b7bb1e97" + "reference": "3d8ce53ae042173bf230445e996056c5f65ded22" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/storage/zipball/9a2556c39b5f4d9f8e79111fd34ec889b7bb1e97", - "reference": "9a2556c39b5f4d9f8e79111fd34ec889b7bb1e97", + "url": "https://api.github.com/repos/utopia-php/storage/zipball/3d8ce53ae042173bf230445e996056c5f65ded22", + "reference": "3d8ce53ae042173bf230445e996056c5f65ded22", "shasum": "" }, "require": { @@ -4384,9 +4390,9 @@ ], "support": { "issues": "https://github.com/utopia-php/storage/issues", - "source": "https://github.com/utopia-php/storage/tree/0.18.12" + "source": "https://github.com/utopia-php/storage/tree/0.18.13" }, - "time": "2025-05-15T07:55:58+00:00" + "time": "2025-05-26T13:10:35+00:00" }, { "name": "utopia-php/swoole", @@ -4771,16 +4777,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.40.18", + "version": "0.40.19", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "38de4b9c58112d7e83eb75955994c8412a401093" + "reference": "05b53cf30c59fe5934d57207fefbc8ae8feb5dbf" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/38de4b9c58112d7e83eb75955994c8412a401093", - "reference": "38de4b9c58112d7e83eb75955994c8412a401093", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/05b53cf30c59fe5934d57207fefbc8ae8feb5dbf", + "reference": "05b53cf30c59fe5934d57207fefbc8ae8feb5dbf", "shasum": "" }, "require": { @@ -4816,9 +4822,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.40.18" + "source": "https://github.com/appwrite/sdk-generator/tree/0.40.19" }, - "time": "2025-05-21T14:14:47+00:00" + "time": "2025-05-24T22:49:50+00:00" }, { "name": "doctrine/annotations", From 852c6fc3fe84e79fad7bbc6dc0e12309378780b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 27 May 2025 10:35:08 +0200 Subject: [PATCH 130/219] Fix rules non-updated --- src/Appwrite/Platform/Modules/Compute/Base.php | 2 +- .../Modules/Functions/Http/Functions/Deployment/Update.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php index 47529a142b..14acacb89a 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -251,7 +251,7 @@ class Base extends Action $queries[] = Query::cursorAfter($cursor); } - $results = $database->find('rules', $queries); + $results = Authorization::skip(fn () => $database->find('rules', $queries)); $total = \count($results); if ($total > 0) { diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php index d97bb92b73..c52be0d95f 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -115,7 +115,7 @@ class Update extends Base $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getInternalId()); - $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); + Authorization::skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); }); $queueForEvents From 64cea46183362172fd5f155f3f8e0e2699d253bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 27 May 2025 10:47:28 +0200 Subject: [PATCH 131/219] Permissiosn fix for sites --- .../Platform/Modules/Sites/Http/Sites/Deployment/Update.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php index aa36b52c5a..d28113c303 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -12,6 +12,7 @@ use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -106,7 +107,7 @@ class Update extends Base $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getInternalId()); - $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); + Authorization::skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); }); $queueForEvents From cedc4eb2df7cec743d261df84c05f0d311a44c42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 27 May 2025 11:06:08 +0200 Subject: [PATCH 132/219] Add logging --- src/Appwrite/Platform/Modules/Compute/Base.php | 5 +++++ .../Functions/Http/Functions/Deployment/Update.php | 9 +++++++++ 2 files changed, 14 insertions(+) diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php index 14acacb89a..d09daa29da 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -251,7 +251,9 @@ class Base extends Action $queries[] = Query::cursorAfter($cursor); } + \var_dump("Actual find"); $results = Authorization::skip(fn () => $database->find('rules', $queries)); + \var_dump($results); $total = \count($results); if ($total > 0) { @@ -263,8 +265,11 @@ class Base extends Action } foreach ($results as $document) { + \var_dump("In foreach"); if (is_callable($callback)) { + \var_dump("Callback start"); $callback($document); + \var_dump("Callback end"); } } } while (!\is_null($cursor)); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php index c52be0d95f..726c1dec2b 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -111,12 +111,21 @@ class Update extends Base Query::equal("deploymentVcsProviderBranch", [""]), ]; + \var_dump("About to set to deployment ID " . $deployment->getId()); + \var_dump("Project ID: " . $project->getId()); + \var_dump("Project internal ID: " . $project->getInternalId()); + \var_dump("Function internal ID: " . $function->getInternalId()); + $this->listRules($project, $queries, $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment) { + \var_dump("Updating rule" . $rule->getId()); $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getInternalId()); Authorization::skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); + \var_dump("Successfully updated " . $rule->getId()); }); + + \var_dump("Post update"); $queueForEvents ->setParam('functionId', $function->getId()) From 675179def889829556956f2f83f564cfa8a3d804 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 27 May 2025 11:41:46 +0200 Subject: [PATCH 133/219] Improve logs --- src/Appwrite/Platform/Modules/Compute/Base.php | 10 ++++------ .../Functions/Http/Functions/Deployment/Update.php | 9 --------- 2 files changed, 4 insertions(+), 15 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php index d09daa29da..46f82af661 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -240,8 +240,10 @@ class Base extends Action { $limit = 100; $cursor = null; - + do { + \var_dump("Project internal ID: " . $project->getInternalId()); + $queries = \array_merge([ Query::limit($limit), Query::equal("projectInternalId", [$project->getInternalId()]) @@ -251,9 +253,8 @@ class Base extends Action $queries[] = Query::cursorAfter($cursor); } - \var_dump("Actual find"); + \var_dump($queries); $results = Authorization::skip(fn () => $database->find('rules', $queries)); - \var_dump($results); $total = \count($results); if ($total > 0) { @@ -265,11 +266,8 @@ class Base extends Action } foreach ($results as $document) { - \var_dump("In foreach"); if (is_callable($callback)) { - \var_dump("Callback start"); $callback($document); - \var_dump("Callback end"); } } } while (!\is_null($cursor)); diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php index 726c1dec2b..f57ec8483c 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -110,22 +110,13 @@ class Update extends Base Query::equal("deploymentResourceInternalId", [$function->getInternalId()]), Query::equal("deploymentVcsProviderBranch", [""]), ]; - - \var_dump("About to set to deployment ID " . $deployment->getId()); - \var_dump("Project ID: " . $project->getId()); - \var_dump("Project internal ID: " . $project->getInternalId()); - \var_dump("Function internal ID: " . $function->getInternalId()); $this->listRules($project, $queries, $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment) { - \var_dump("Updating rule" . $rule->getId()); $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getInternalId()); Authorization::skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); - \var_dump("Successfully updated " . $rule->getId()); }); - - \var_dump("Post update"); $queueForEvents ->setParam('functionId', $function->getId()) From 501d29f696ab84dce85e9749aa07d94bc66ea409 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 27 May 2025 11:54:34 +0200 Subject: [PATCH 134/219] Implement a fix --- .../Platform/Modules/Compute/Base.php | 38 ------------- .../Http/Functions/Deployment/Update.php | 9 ++-- .../Modules/Functions/Workers/Builds.php | 53 +++++-------------- .../Sites/Http/Sites/Deployment/Update.php | 7 +-- 4 files changed, 21 insertions(+), 86 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Compute/Base.php b/src/Appwrite/Platform/Modules/Compute/Base.php index 46f82af661..0541df551a 100644 --- a/src/Appwrite/Platform/Modules/Compute/Base.php +++ b/src/Appwrite/Platform/Modules/Compute/Base.php @@ -4,7 +4,6 @@ namespace Appwrite\Platform\Modules\Compute; use Appwrite\Event\Build; use Appwrite\Extend\Exception; -use Appwrite\Query; use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Helpers\ID; @@ -235,41 +234,4 @@ class Base extends Action return $deployment; } - - protected function listRules(Document $project, array $queries, Database $database, callable $callback): void - { - $limit = 100; - $cursor = null; - - do { - \var_dump("Project internal ID: " . $project->getInternalId()); - - $queries = \array_merge([ - Query::limit($limit), - Query::equal("projectInternalId", [$project->getInternalId()]) - ], $queries); - - if ($cursor !== null) { - $queries[] = Query::cursorAfter($cursor); - } - - \var_dump($queries); - $results = Authorization::skip(fn () => $database->find('rules', $queries)); - - $total = \count($results); - if ($total > 0) { - $cursor = $results[$total - 1]; - } - - if ($total < $limit) { - $cursor = null; - } - - foreach ($results as $document) { - if (is_callable($callback)) { - $callback($document); - } - } - } while (!\is_null($cursor)); - } } diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php index f57ec8483c..e840441774 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -5,7 +5,6 @@ namespace Appwrite\Platform\Modules\Functions\Http\Functions\Deployment; use Appwrite\Event\Event; use Appwrite\Extend\Exception; use Appwrite\Platform\Modules\Compute\Base; -use Appwrite\Query; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; @@ -13,6 +12,7 @@ use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\DateTime; use Utopia\Database\Document; +use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -109,14 +109,15 @@ class Update extends Base Query::equal("deploymentResourceType", ["function"]), Query::equal("deploymentResourceInternalId", [$function->getInternalId()]), Query::equal("deploymentVcsProviderBranch", [""]), + Query::equal("projectInternalId", [$project->getInternalId()]) ]; - - $this->listRules($project, $queries, $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment) { + + Authorization::skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getInternalId()); Authorization::skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); - }); + }, $queries)); $queueForEvents ->setParam('functionId', $function->getId()) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index b5bd2ee8e6..b05da8485b 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -1087,16 +1087,17 @@ class Builds extends Action Query::equal('deploymentResourceType', ['function']), Query::equal('trigger', ['manual']), Query::equal('deploymentVcsProviderBranch', ['']), + Query::equal("projectInternalId", [$project->getInternalId()]) ]; $rulesUpdated = false; - $this->listRules($project, $queries, $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment, &$rulesUpdated) { + $dbForPlatform->forEach('rules', function (Document $rule) use ($dbForPlatform, $deployment, &$rulesUpdated) { $rulesUpdated = true; $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getInternalId()); $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); - }); + }, $queries); break; case 'sites': $resource->setAttribute('deploymentId', $deployment->getId()); @@ -1112,14 +1113,15 @@ class Builds extends Action Query::equal('deploymentResourceType', ['site']), Query::equal('trigger', ['manual']), Query::equal('deploymentVcsProviderBranch', ['']), + Query::equal("projectInternalId", [$project->getInternalId()]) ]; - $this->listRules($project, $queries, $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment) { + $dbForPlatform->forEach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getInternalId()); $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); - }); + }, $queries); break; } @@ -1161,19 +1163,22 @@ class Builds extends Action $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); } - $this->listRules($project, [ + $queries = [ Query::equal("projectInternalId", [$project->getInternalId()]), Query::equal("type", ["deployment"]), Query::equal("deploymentResourceInternalId", [$resource->getInternalId()]), Query::equal('deploymentResourceType', ['site']), Query::equal("deploymentVcsProviderBranch", [$branchName]), Query::equal("trigger", ['manual']), - ], $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment) { + Query::equal("projectInternalId", [$project->getInternalId()]) + ]; + + $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getInternalId()); $dbForPlatform->updateDocument('rules', $rule->getId(), $rule); - }); + }, $queries); } } @@ -1476,38 +1481,4 @@ class Builds extends Action } } } - - protected function listRules(Document $project, array $queries, Database $database, callable $callback): void - { - $limit = 100; - $cursor = null; - - do { - $queries = \array_merge([ - Query::limit($limit), - Query::equal("projectInternalId", [$project->getInternalId()]) - ], $queries); - - if ($cursor !== null) { - $queries[] = Query::cursorAfter($cursor); - } - - $results = $database->find('rules', $queries); - - $total = \count($results); - if ($total > 0) { - $cursor = $results[$total - 1]; - } - - if ($total < $limit) { - $cursor = null; - } - - foreach ($results as $document) { - if (is_callable($callback)) { - $callback($document); - } - } - } while (!\is_null($cursor)); - } } diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php index d28113c303..a54d0c7889 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -5,13 +5,13 @@ namespace Appwrite\Platform\Modules\Sites\Http\Sites\Deployment; use Appwrite\Event\Event; use Appwrite\Extend\Exception; use Appwrite\Platform\Modules\Compute\Base; -use Appwrite\Query; use Appwrite\SDK\AuthType; use Appwrite\SDK\Method; use Appwrite\SDK\Response as SDKResponse; use Appwrite\Utopia\Response; use Utopia\Database\Database; use Utopia\Database\Document; +use Utopia\Database\Query; use Utopia\Database\Validator\Authorization; use Utopia\Database\Validator\UID; use Utopia\Platform\Action; @@ -101,14 +101,15 @@ class Update extends Base Query::equal("deploymentResourceType", ["site"]), Query::equal("deploymentResourceInternalId", [$site->getInternalId()]), Query::equal("deploymentVcsProviderBranch", [""]), + Query::equal("projectInternalId", [$project->getInternalId()]) ]; - $this->listRules($project, $queries, $dbForPlatform, function (Document $rule) use ($dbForPlatform, $deployment) { + Authorization::skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { $rule = $rule ->setAttribute('deploymentId', $deployment->getId()) ->setAttribute('deploymentInternalId', $deployment->getInternalId()); Authorization::skip(fn () => $dbForPlatform->updateDocument('rules', $rule->getId(), $rule)); - }); + }, $queries)); $queueForEvents ->setParam('siteId', $site->getId()) From b7702340baa58605a83ff2ab5b867c02773a17da Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Wed, 28 May 2025 01:13:29 +1200 Subject: [PATCH 135/219] Fix allowed attributes list for user target list queries --- app/controllers/api/users.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/users.php b/app/controllers/api/users.php index 4b6e5abe6b..d7def69464 100644 --- a/app/controllers/api/users.php +++ b/app/controllers/api/users.php @@ -980,7 +980,7 @@ App::get('/v1/users/:userId/targets') ] )) ->param('userId', '', new UID(), 'User ID.') - ->param('queries', [], new Targets(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Users::ALLOWED_ATTRIBUTES), true) + ->param('queries', [], new Targets(), 'Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https://appwrite.io/docs/queries). Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' queries are allowed, each ' . APP_LIMIT_ARRAY_ELEMENT_SIZE . ' characters long. You may filter on the following attributes: ' . implode(', ', Targets::ALLOWED_ATTRIBUTES), true) ->inject('response') ->inject('dbForProject') ->action(function (string $userId, array $queries, Response $response, Database $dbForProject) { From 7e6f4befa58dcf83d86fc976eeeb7eec2e8bf170 Mon Sep 17 00:00:00 2001 From: Darshan Date: Tue, 27 May 2025 19:21:28 +0530 Subject: [PATCH 136/219] reset: stuff from main. --- app/cli.php | 3 +- app/controllers/api/storage.php | 60 +++++++++---------- src/Appwrite/Platform/Tasks/ScheduleBase.php | 10 ++-- .../Platform/Tasks/ScheduleFunctions.php | 2 +- .../Platform/Tasks/ScheduleMessages.php | 2 +- 5 files changed, 39 insertions(+), 38 deletions(-) diff --git a/app/cli.php b/app/cli.php index 7c2daf4500..9517347420 100644 --- a/app/cli.php +++ b/app/cli.php @@ -284,5 +284,6 @@ $cli $cli->shutdown()->action(fn () => Timer::clearAll()); -Runtime::enableCoroutine(SWOOLE_HOOK_ALL); +// Enable coroutines, but disable TCP hooks. These don't work until we use `\Utopia\Cache\Adapter\Pool` and `\Utopia\Database\Adapter\Pool`. +Runtime::enableCoroutine(SWOOLE_HOOK_ALL ^ SWOOLE_HOOK_TCP); run($cli->run(...)); diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index d2edf476f6..b3b8fb906a 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -1004,7 +1004,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $algorithm = $file->getAttribute('algorithm', Compression::NONE); $cipher = $file->getAttribute('openSSLCipher'); $mime = $file->getAttribute('mimeType'); - if (!\in_array($mime, $inputs) || $file->getAttribute('sizeActual') > (int) System::getEnv('_APP_STORAGE_PREVIEW_LIMIT', APP_STORAGE_READ_BUFFER)) { + if (!\in_array($mime, $inputs) || $file->getAttribute('sizeActual') > (int) System::getEnv('_APP_STORAGE_PREVIEW_LIMIT', 20000000)) { if (!\in_array($mime, $inputs)) { $path = (\array_key_exists($mime, $fileLogos)) ? $fileLogos[$mime] : $fileLogos['default']; } else { @@ -1178,6 +1178,13 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in ' . $path); } + $response + ->setContentType($file->getAttribute('mimeType')) + ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days + ->addHeader('X-Peak', \memory_get_peak_usage()) + ->addHeader('Content-Disposition', 'attachment; filename="' . $file->getAttribute('name', '') . '"') + ; + $size = $file->getAttribute('sizeOriginal', 0); $rangeHeader = $request->getHeader('range'); @@ -1186,7 +1193,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') $end = $request->getRangeEnd(); $unit = $request->getRangeUnit(); - if ($end === null || $end - $start > APP_STORAGE_READ_BUFFER) { + if ($end === null) { $end = min(($start + MAX_OUTPUT_CHUNK_SIZE - 1), ($size - 1)); } @@ -1201,13 +1208,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') ->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT); } - $response - ->setContentType($file->getAttribute('mimeType')) - ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days - ->addHeader('X-Peak', \memory_get_peak_usage()) - ->addHeader('Content-Disposition', 'attachment; filename="' . $file->getAttribute('name', '') . '"') - ; - $source = ''; if (!empty($file->getAttribute('openSSLCipher'))) { // Decrypt $source = $deviceForFiles->read($path); @@ -1345,6 +1345,15 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') $contentType = $file->getAttribute('mimeType'); } + $response + ->setContentType($contentType) + ->addHeader('Content-Security-Policy', 'script-src none;') + ->addHeader('X-Content-Type-Options', 'nosniff') + ->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"') + ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days + ->addHeader('X-Peak', \memory_get_peak_usage()) + ; + $size = $file->getAttribute('sizeOriginal', 0); $rangeHeader = $request->getHeader('range'); @@ -1353,8 +1362,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') $end = $request->getRangeEnd(); $unit = $request->getRangeUnit(); - if ($end === null || $end - $start > APP_STORAGE_READ_BUFFER) { - $end = min(($start + APP_STORAGE_READ_BUFFER - 1), ($size - 1)); + if ($end === null) { + $end = min(($start + 2000000 - 1), ($size - 1)); } if ($unit != 'bytes' || $start >= $end || $end >= $size) { @@ -1368,15 +1377,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') ->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT); } - $response - ->setContentType($contentType) - ->addHeader('Content-Security-Policy', 'script-src none;') - ->addHeader('X-Content-Type-Options', 'nosniff') - ->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"') - ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days - ->addHeader('X-Peak', \memory_get_peak_usage()) - ; - $source = ''; if (!empty($file->getAttribute('openSSLCipher'))) { // Decrypt $source = $deviceForFiles->read($path); @@ -1498,6 +1498,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') $contentType = $file->getAttribute('mimeType'); } + $response + ->setContentType($contentType) + ->addHeader('Content-Security-Policy', 'script-src none;') + ->addHeader('X-Content-Type-Options', 'nosniff') + ->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"') + ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days + ->addHeader('X-Peak', \memory_get_peak_usage()); + $size = $file->getAttribute('sizeOriginal', 0); $rangeHeader = $request->getHeader('range'); @@ -1506,8 +1514,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') $end = $request->getRangeEnd(); $unit = $request->getRangeUnit(); - if ($end === null || $end - $start > APP_STORAGE_READ_BUFFER) { - $end = min(($start + APP_STORAGE_READ_BUFFER - 1), ($size - 1)); + if ($end === null) { + $end = min(($start + 2000000 - 1), ($size - 1)); } if ($unit != 'bytes' || $start >= $end || $end >= $size) { @@ -1521,14 +1529,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') ->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT); } - $response - ->setContentType($contentType) - ->addHeader('Content-Security-Policy', 'script-src none;') - ->addHeader('X-Content-Type-Options', 'nosniff') - ->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"') - ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days - ->addHeader('X-Peak', \memory_get_peak_usage()); - $source = ''; if (!empty($file->getAttribute('openSSLCipher'))) { // Decrypt $source = $deviceForFiles->read($path); diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index 28c77c1832..286ffe45cb 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -79,16 +79,16 @@ abstract class ScheduleBase extends Action // start with "0" to load all active documents. $lastSyncUpdate = "0"; - $this->collectSchedules($dbForPlatform, $getProjectDB, $lastSyncUpdate); + $this->collectSchedules($pools, $dbForPlatform, $getProjectDB, $lastSyncUpdate); Console::success("Starting timers at " . DateTime::now()); /** * The timer synchronize $schedules copy with database collection. */ - Timer::tick(static::UPDATE_TIMER * 1000, function () use ($dbForPlatform, $getProjectDB, &$lastSyncUpdate) { + Timer::tick(static::UPDATE_TIMER * 1000, function () use ($pools, $dbForPlatform, $getProjectDB, &$lastSyncUpdate) { $time = DateTime::now(); Console::log("Sync tick: Running at $time"); - $this->collectSchedules($dbForPlatform, $getProjectDB, $lastSyncUpdate); + $this->collectSchedules($pools, $dbForPlatform, $getProjectDB, $lastSyncUpdate); }); while (true) { @@ -103,7 +103,7 @@ abstract class ScheduleBase extends Action } } - private function collectSchedules(Database $dbForPlatform, callable $getProjectDB, string &$lastSyncUpdate): void + private function collectSchedules(Group $pools, Database $dbForPlatform, callable $getProjectDB, string &$lastSyncUpdate): void { // If we haven't synced yet, load all active schedules $initialLoad = $lastSyncUpdate === "0"; @@ -115,7 +115,7 @@ abstract class ScheduleBase extends Action * @throws Exception * @var Document $schedule */ - $getSchedule = function (Document $schedule) use ($dbForPlatform, $getProjectDB): array { + $getSchedule = function (Document $schedule) use ($pools, $dbForPlatform, $getProjectDB): array { $project = $dbForPlatform->getDocument('projects', $schedule->getAttribute('projectId')); $resource = $getProjectDB($project)->getDocument( diff --git a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php index 7812b27832..19e068107a 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php @@ -76,7 +76,7 @@ class ScheduleFunctions extends ScheduleBase } foreach ($delayedExecutions as $delay => $schedules) { - \go(function () use ($delay, $schedules, $dbForPlatform) { + \go(function () use ($delay, $schedules, $pools, $dbForPlatform) { \sleep($delay); // in seconds foreach ($schedules as $delayConfig) { diff --git a/src/Appwrite/Platform/Tasks/ScheduleMessages.php b/src/Appwrite/Platform/Tasks/ScheduleMessages.php index d23e3de575..5e65f7a8a6 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleMessages.php +++ b/src/Appwrite/Platform/Tasks/ScheduleMessages.php @@ -40,7 +40,7 @@ class ScheduleMessages extends ScheduleBase continue; } - \go(function () use ($schedule, $scheduledAt, $dbForPlatform) { + \go(function () use ($schedule, $scheduledAt, $pools, $dbForPlatform) { $queueForMessaging = new Messaging($this->publisher); $this->updateProjectAccess($schedule['project'], $dbForPlatform); From 320bf69208e743b9a9e3ac03f7da65f30bc0a49b Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Wed, 28 May 2025 12:50:47 +0530 Subject: [PATCH 137/219] Shorten commit url --- app/controllers/api/vcs.php | 8 ++++++- composer.lock | 24 +++++++++---------- .../Modules/Functions/Workers/Builds.php | 8 ++++++- 3 files changed, 26 insertions(+), 14 deletions(-) diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index a986d1004b..2529425bd1 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -293,7 +293,13 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId // VCS branch preview if (!empty($providerBranch)) { - $domain = "branch-{$providerBranch}-{$resource->getId()}-{$project->getId()}.{$sitesDomain}"; + $branchPrefix = substr($providerBranch, 0, 16); + if (strlen($providerBranch) > 16) { + $remainingChars = substr($providerBranch, 16); + $branchPrefix .= substr(hash('sha256', $remainingChars), 0, 7); + } + $resourceProjectHash = substr(hash('sha256', $resource->getId() . $project->getId()), 0, 7); + $domain = "branch-{$branchPrefix}{$resourceProjectHash}.{$sitesDomain}"; $ruleId = md5($domain); try { Authorization::skip( diff --git a/composer.lock b/composer.lock index f5b3f796c8..7f1799ac73 100644 --- a/composer.lock +++ b/composer.lock @@ -157,16 +157,16 @@ }, { "name": "appwrite/php-runtimes", - "version": "0.19.0", + "version": "0.19.1", "source": { "type": "git", "url": "https://github.com/appwrite/runtimes.git", - "reference": "8d21483efc19b9d977e323188989ee67a188464b" + "reference": "7bd0cc3cb97de625d7b07230bd91b121f88e72ae" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/runtimes/zipball/8d21483efc19b9d977e323188989ee67a188464b", - "reference": "8d21483efc19b9d977e323188989ee67a188464b", + "url": "https://api.github.com/repos/appwrite/runtimes/zipball/7bd0cc3cb97de625d7b07230bd91b121f88e72ae", + "reference": "7bd0cc3cb97de625d7b07230bd91b121f88e72ae", "shasum": "" }, "require": { @@ -206,9 +206,9 @@ ], "support": { "issues": "https://github.com/appwrite/runtimes/issues", - "source": "https://github.com/appwrite/runtimes/tree/0.19.0" + "source": "https://github.com/appwrite/runtimes/tree/0.19.1" }, - "time": "2025-03-25T22:37:51+00:00" + "time": "2025-05-27T07:12:56+00:00" }, { "name": "beberlei/assert", @@ -4378,16 +4378,16 @@ }, { "name": "utopia-php/storage", - "version": "0.18.12", + "version": "0.18.13", "source": { "type": "git", "url": "https://github.com/utopia-php/storage.git", - "reference": "9a2556c39b5f4d9f8e79111fd34ec889b7bb1e97" + "reference": "3d8ce53ae042173bf230445e996056c5f65ded22" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/storage/zipball/9a2556c39b5f4d9f8e79111fd34ec889b7bb1e97", - "reference": "9a2556c39b5f4d9f8e79111fd34ec889b7bb1e97", + "url": "https://api.github.com/repos/utopia-php/storage/zipball/3d8ce53ae042173bf230445e996056c5f65ded22", + "reference": "3d8ce53ae042173bf230445e996056c5f65ded22", "shasum": "" }, "require": { @@ -4430,9 +4430,9 @@ ], "support": { "issues": "https://github.com/utopia-php/storage/issues", - "source": "https://github.com/utopia-php/storage/tree/0.18.12" + "source": "https://github.com/utopia-php/storage/tree/0.18.13" }, - "time": "2025-05-15T07:55:58+00:00" + "time": "2025-05-26T13:10:35+00:00" }, { "name": "utopia-php/swoole", diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index b05da8485b..40e1aa1547 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -1132,7 +1132,13 @@ class Builds extends Action $branchName = $deployment->getAttribute('providerBranch'); if (!empty($branchName)) { $sitesDomain = System::getEnv('_APP_DOMAIN_SITES', ''); - $domain = "branch-{$branchName}-{$resource->getId()}-{$project->getId()}.{$sitesDomain}"; + $branchPrefix = substr($branchName, 0, 16); + if (strlen($branchName) > 16) { + $remainingChars = substr($branchName, 16); + $branchPrefix .= substr(hash('sha256', $remainingChars), 0, 7); + } + $resourceProjectHash = substr(hash('sha256', $resource->getId() . $project->getId()), 0, 7); + $domain = "branch-{$branchPrefix}{$resourceProjectHash}.{$sitesDomain}"; $ruleId = md5($domain); try { From 66ac440f9da16c82c656df7b8c8b7824ac1d6d0b Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Wed, 28 May 2025 12:55:50 +0530 Subject: [PATCH 138/219] Add missing separator --- app/controllers/api/vcs.php | 2 +- src/Appwrite/Platform/Modules/Functions/Workers/Builds.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 2529425bd1..85c071151d 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -299,7 +299,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $branchPrefix .= substr(hash('sha256', $remainingChars), 0, 7); } $resourceProjectHash = substr(hash('sha256', $resource->getId() . $project->getId()), 0, 7); - $domain = "branch-{$branchPrefix}{$resourceProjectHash}.{$sitesDomain}"; + $domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}"; $ruleId = md5($domain); try { Authorization::skip( diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 40e1aa1547..b3d11d8b54 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -1138,7 +1138,7 @@ class Builds extends Action $branchPrefix .= substr(hash('sha256', $remainingChars), 0, 7); } $resourceProjectHash = substr(hash('sha256', $resource->getId() . $project->getId()), 0, 7); - $domain = "branch-{$branchPrefix}{$resourceProjectHash}.{$sitesDomain}"; + $domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}"; $ruleId = md5($domain); try { From aa07ba002787826bd9a3f193b94cc46d7bcd85cb Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Wed, 28 May 2025 14:01:55 +0530 Subject: [PATCH 139/219] Update app/controllers/api/vcs.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matej Bačo --- app/controllers/api/vcs.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 85c071151d..f80a51d497 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -296,7 +296,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId $branchPrefix = substr($providerBranch, 0, 16); if (strlen($providerBranch) > 16) { $remainingChars = substr($providerBranch, 16); - $branchPrefix .= substr(hash('sha256', $remainingChars), 0, 7); + $branchPrefix .= '-' . substr(hash('sha256', $remainingChars), 0, 7); } $resourceProjectHash = substr(hash('sha256', $resource->getId() . $project->getId()), 0, 7); $domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}"; From 707ef16f79caefd47c6d29ebaa4a94e6c98e5efc Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Wed, 28 May 2025 14:02:03 +0530 Subject: [PATCH 140/219] Update src/Appwrite/Platform/Modules/Functions/Workers/Builds.php MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Matej Bačo --- src/Appwrite/Platform/Modules/Functions/Workers/Builds.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index b3d11d8b54..de5543c9f3 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -1135,7 +1135,7 @@ class Builds extends Action $branchPrefix = substr($branchName, 0, 16); if (strlen($branchName) > 16) { $remainingChars = substr($branchName, 16); - $branchPrefix .= substr(hash('sha256', $remainingChars), 0, 7); + $branchPrefix .= '-' . substr(hash('sha256', $remainingChars), 0, 7); } $resourceProjectHash = substr(hash('sha256', $resource->getId() . $project->getId()), 0, 7); $domain = "branch-{$branchPrefix}-{$resourceProjectHash}.{$sitesDomain}"; From 814abddf937e773aafe04141ab7c849ee2c7310f Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Wed, 28 May 2025 14:10:12 +0530 Subject: [PATCH 141/219] Truncate commit hash to 16 chars --- app/controllers/api/vcs.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index f80a51d497..588ca417cf 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -330,7 +330,7 @@ $createGitDeployments = function (GitHub $github, string $providerInstallationId // VCS commit preview if (!empty($providerCommitHash)) { - $domain = "commit-{$providerCommitHash}.{$sitesDomain}"; + $domain = "commit-" . substr($providerCommitHash, 0, 16) . ".{$sitesDomain}"; $ruleId = md5($domain); try { Authorization::skip( From 0d46d4d6e9348980cb5ab17207e6ee6eca0dde63 Mon Sep 17 00:00:00 2001 From: fogelito Date: Wed, 28 May 2025 15:54:58 +0300 Subject: [PATCH 142/219] Remove roles index --- app/config/collections/common.php | 7 ------- src/Appwrite/Migration/Version/V22.php | 22 +++++++++++----------- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/app/config/collections/common.php b/app/config/collections/common.php index e77d5403d2..6de7eb224b 100644 --- a/app/config/collections/common.php +++ b/app/config/collections/common.php @@ -1439,13 +1439,6 @@ return [ 'lengths' => [], 'orders' => [Database::ORDER_ASC], ], - [ - '$id' => ID::custom('_key_roles'), - 'type' => Database::INDEX_KEY, - 'attributes' => ['roles'], - 'lengths' => [128], - 'orders' => [], - ], ], ], diff --git a/src/Appwrite/Migration/Version/V22.php b/src/Appwrite/Migration/Version/V22.php index 2a6a64ed48..33e18e2956 100644 --- a/src/Appwrite/Migration/Version/V22.php +++ b/src/Appwrite/Migration/Version/V22.php @@ -145,17 +145,17 @@ class V22 extends Migration $this->dbForProject->purgeCachedCollection($id); break; case 'memberships': - $indexes = [ - '_key_roles', - ]; - foreach ($indexes as $index) { - try { - $this->createIndexFromCollection($this->dbForProject, $id, $index); - } catch (Throwable $th) { - Console::warning("Failed to create index \"$index\" from {$id}: {$th->getMessage()}"); - } - } - $this->dbForProject->purgeCachedCollection($id); +// $indexes = [ +// '_key_roles', +// ]; +// foreach ($indexes as $index) { +// try { +// $this->createIndexFromCollection($this->dbForProject, $id, $index); +// } catch (Throwable $th) { +// Console::warning("Failed to create index \"$index\" from {$id}: {$th->getMessage()}"); +// } +// } +// $this->dbForProject->purgeCachedCollection($id); break; case 'migrations': $attributes = [ From 601b6760a5cef97cd423eea66f932e474c45b63d Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Thu, 29 May 2025 05:33:26 +0000 Subject: [PATCH 143/219] fix version pinning --- composer.json | 8 +++--- composer.lock | 68 +++++++++++++++++++++++++-------------------------- 2 files changed, 37 insertions(+), 39 deletions(-) diff --git a/composer.json b/composer.json index f24bfac20e..833f1a462b 100644 --- a/composer.json +++ b/composer.json @@ -76,10 +76,10 @@ "utopia-php/vcs": "0.10.*", "utopia-php/websocket": "0.3.*", "matomo/device-detector": "6.1.*", - "dragonmantank/cron-expression": "^3.3.2", - "phpmailer/phpmailer": "^6.9.1", - "chillerlan/php-qrcode": "^4.3.4", - "adhocore/jwt": "^1.1.2", + "dragonmantank/cron-expression": "3.3.*", + "phpmailer/phpmailer": "6.9.*", + "chillerlan/php-qrcode": "4.3.*", + "adhocore/jwt": "1.1.*", "spomky-labs/otphp": "^10.0", "webonyx/graphql-php": "14.11.*", "league/csv": "9.14.*" diff --git a/composer.lock b/composer.lock index 8c6de32697..7c838626b0 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "b7bac964db0e1b6d640eb743b8ac0d9b", + "content-hash": "de0a0fb794f826fcc412c788185b69f4", "packages": [ { "name": "adhocore/jwt", @@ -343,34 +343,31 @@ }, { "name": "chillerlan/php-qrcode", - "version": "4.4.2", + "version": "4.3.4", "source": { "type": "git", "url": "https://github.com/chillerlan/php-qrcode.git", - "reference": "345ed8e4ffb56e6b3fcd9f42e3970b9026fa6ce4" + "reference": "2ca4bf5ae048af1981d1023ee42a0a2a9d51e51d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/345ed8e4ffb56e6b3fcd9f42e3970b9026fa6ce4", - "reference": "345ed8e4ffb56e6b3fcd9f42e3970b9026fa6ce4", + "url": "https://api.github.com/repos/chillerlan/php-qrcode/zipball/2ca4bf5ae048af1981d1023ee42a0a2a9d51e51d", + "reference": "2ca4bf5ae048af1981d1023ee42a0a2a9d51e51d", "shasum": "" }, "require": { - "chillerlan/php-settings-container": "^2.1.6 || ^3.2.1", + "chillerlan/php-settings-container": "^2.1.4", "ext-mbstring": "*", "php": "^7.4 || ^8.0" }, "require-dev": { - "phan/phan": "^5.4.5", - "phpmd/phpmd": "^2.15", - "phpunit/phpunit": "^9.6", - "setasign/fpdf": "^1.8.2", - "squizlabs/php_codesniffer": "^3.11" + "phan/phan": "^5.3", + "phpunit/phpunit": "^9.5", + "setasign/fpdf": "^1.8.2" }, "suggest": { "chillerlan/php-authenticator": "Yet another Google authenticator! Also creates URIs for mobile apps.", - "setasign/fpdf": "Required to use the QR FPDF output.", - "simple-icons/simple-icons": "SVG icons that you can use to embed as logos in the QR Code" + "setasign/fpdf": "Required to use the QR FPDF output." }, "type": "library", "autoload": { @@ -397,7 +394,7 @@ "homepage": "https://github.com/chillerlan/php-qrcode/graphs/contributors" } ], - "description": "A QR code generator with a user friendly API. PHP 7.4+", + "description": "A QR code generator. PHP 7.4+", "homepage": "https://github.com/chillerlan/php-qrcode", "keywords": [ "phpqrcode", @@ -408,39 +405,43 @@ ], "support": { "issues": "https://github.com/chillerlan/php-qrcode/issues", - "source": "https://github.com/chillerlan/php-qrcode/tree/4.4.2" + "source": "https://github.com/chillerlan/php-qrcode/tree/4.3.4" }, "funding": [ + { + "url": "https://www.paypal.com/donate?hosted_button_id=WLYUNAT9ZTJZ4", + "type": "custom" + }, { "url": "https://ko-fi.com/codemasher", "type": "ko_fi" } ], - "time": "2024-11-15T15:36:24+00:00" + "time": "2022-07-25T09:12:45+00:00" }, { "name": "chillerlan/php-settings-container", - "version": "3.2.1", + "version": "2.1.6", "source": { "type": "git", "url": "https://github.com/chillerlan/php-settings-container.git", - "reference": "95ed3e9676a1d47cab2e3174d19b43f5dbf52681" + "reference": "5553558bd381fce5108c6d0343c12e488cfec6bb" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/95ed3e9676a1d47cab2e3174d19b43f5dbf52681", - "reference": "95ed3e9676a1d47cab2e3174d19b43f5dbf52681", + "url": "https://api.github.com/repos/chillerlan/php-settings-container/zipball/5553558bd381fce5108c6d0343c12e488cfec6bb", + "reference": "5553558bd381fce5108c6d0343c12e488cfec6bb", "shasum": "" }, "require": { "ext-json": "*", - "php": "^8.1" + "php": "^7.4 || ^8.0" }, "require-dev": { "phpmd/phpmd": "^2.15", "phpstan/phpstan": "^1.11", "phpstan/phpstan-deprecation-rules": "^1.2", - "phpunit/phpunit": "^10.5", + "phpunit/phpunit": "^9.6", "squizlabs/php_codesniffer": "^3.10" }, "type": "library", @@ -460,9 +461,10 @@ "homepage": "https://github.com/codemasher" } ], - "description": "A container class for immutable settings objects. Not a DI container.", + "description": "A container class for immutable settings objects. Not a DI container. PHP 7.4+", "homepage": "https://github.com/chillerlan/php-settings-container", "keywords": [ + "PHP7", "Settings", "configuration", "container", @@ -482,7 +484,7 @@ "type": "ko_fi" } ], - "time": "2024-07-16T11:13:48+00:00" + "time": "2024-07-17T01:04:28+00:00" }, { "name": "composer/semver", @@ -567,16 +569,16 @@ }, { "name": "dragonmantank/cron-expression", - "version": "v3.4.0", + "version": "v3.3.3", "source": { "type": "git", "url": "https://github.com/dragonmantank/cron-expression.git", - "reference": "8c784d071debd117328803d86b2097615b457500" + "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/8c784d071debd117328803d86b2097615b457500", - "reference": "8c784d071debd117328803d86b2097615b457500", + "url": "https://api.github.com/repos/dragonmantank/cron-expression/zipball/adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", + "reference": "adfb1f505deb6384dc8b39804c5065dd3c8c8c0a", "shasum": "" }, "require": { @@ -589,14 +591,10 @@ "require-dev": { "phpstan/extension-installer": "^1.0", "phpstan/phpstan": "^1.0", + "phpstan/phpstan-webmozart-assert": "^1.0", "phpunit/phpunit": "^7.0|^8.0|^9.0" }, "type": "library", - "extra": { - "branch-alias": { - "dev-master": "3.x-dev" - } - }, "autoload": { "psr-4": { "Cron\\": "src/Cron/" @@ -620,7 +618,7 @@ ], "support": { "issues": "https://github.com/dragonmantank/cron-expression/issues", - "source": "https://github.com/dragonmantank/cron-expression/tree/v3.4.0" + "source": "https://github.com/dragonmantank/cron-expression/tree/v3.3.3" }, "funding": [ { @@ -628,7 +626,7 @@ "type": "github" } ], - "time": "2024-10-09T13:47:03+00:00" + "time": "2023-08-10T19:36:49+00:00" }, { "name": "giggsey/libphonenumber-for-php-lite", From 7d284a9872bc124c868359a1219833deb1cf8c3f Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Thu, 29 May 2025 14:34:21 +0530 Subject: [PATCH 144/219] Remove powered by from error pages --- app/views/general/error.phtml | 4 ++-- tests/e2e/Services/Sites/SitesCustomServerTest.php | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/app/views/general/error.phtml b/app/views/general/error.phtml index de1c2b6541..9706c8ee94 100644 --- a/app/views/general/error.phtml +++ b/app/views/general/error.phtml @@ -512,7 +512,7 @@ switch ($type) {
-
+ \ No newline at end of file diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index d3b4922b87..3a70a21e37 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -1446,7 +1446,7 @@ class SitesCustomServerTest extends Scope $this->assertEquals(404, $response['headers']['status-code']); $this->assertStringContainsString("Page not found", $response['body']); // Title $this->assertStringContainsString("Go to homepage", $response['body']); // Button - $this->assertStringContainsString("Powered by", $response['body']); // Brand + // $this->assertStringContainsString("Powered by", $response['body']); // Brand $this->cleanupSite($siteId); } @@ -1502,7 +1502,7 @@ class SitesCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertStringContainsString("Customized 404 page", $response['body']); - $this->assertStringNotContainsString("Powered by", $response['body']); // Brand + // $this->assertStringNotContainsString("Powered by", $response['body']); // Brand $this->cleanupSite($siteId); } From c4510004ce15969edd951c7187a772182351a120 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Thu, 29 May 2025 14:46:25 +0530 Subject: [PATCH 145/219] update test --- tests/e2e/Services/Sites/SitesCustomServerTest.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index 3a70a21e37..8459e46c6f 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -1446,7 +1446,7 @@ class SitesCustomServerTest extends Scope $this->assertEquals(404, $response['headers']['status-code']); $this->assertStringContainsString("Page not found", $response['body']); // Title $this->assertStringContainsString("Go to homepage", $response['body']); // Button - // $this->assertStringContainsString("Powered by", $response['body']); // Brand + $this->assertStringNotContainsString("Powered by", $response['body']); // Brand $this->cleanupSite($siteId); } @@ -1502,7 +1502,7 @@ class SitesCustomServerTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); $this->assertStringContainsString("Customized 404 page", $response['body']); - // $this->assertStringNotContainsString("Powered by", $response['body']); // Brand + $this->assertStringNotContainsString("Powered by", $response['body']); //brand $this->cleanupSite($siteId); } From 823d8604bd8afb78604e2693fecf7539faa622c0 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Thu, 29 May 2025 22:39:12 +1200 Subject: [PATCH 146/219] Update database --- composer.lock | 91 ++++++++++++++++++++++++++------------------------- 1 file changed, 46 insertions(+), 45 deletions(-) diff --git a/composer.lock b/composer.lock index 7c838626b0..8ecfcf6a18 100644 --- a/composer.lock +++ b/composer.lock @@ -2557,16 +2557,16 @@ }, { "name": "symfony/http-client", - "version": "v7.2.4", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/http-client.git", - "reference": "78981a2ffef6437ed92d4d7e2a86a82f256c6dc6" + "reference": "57e4fb86314015a695a750ace358d07a7e37b8a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/http-client/zipball/78981a2ffef6437ed92d4d7e2a86a82f256c6dc6", - "reference": "78981a2ffef6437ed92d4d7e2a86a82f256c6dc6", + "url": "https://api.github.com/repos/symfony/http-client/zipball/57e4fb86314015a695a750ace358d07a7e37b8a9", + "reference": "57e4fb86314015a695a750ace358d07a7e37b8a9", "shasum": "" }, "require": { @@ -2632,7 +2632,7 @@ "http" ], "support": { - "source": "https://github.com/symfony/http-client/tree/v7.2.4" + "source": "https://github.com/symfony/http-client/tree/v7.3.0" }, "funding": [ { @@ -2648,7 +2648,7 @@ "type": "tidelift" } ], - "time": "2025-02-13T10:27:23+00:00" + "time": "2025-05-02T08:23:16+00:00" }, { "name": "symfony/http-client-contracts", @@ -3503,16 +3503,16 @@ }, { "name": "utopia-php/database", - "version": "0.69.5", + "version": "0.69.6", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "4abe53609dfc23b2ea82884d12b149df6a8af2f5" + "reference": "42bfc0d87de4ade26cfd9915aaad84912761466b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/4abe53609dfc23b2ea82884d12b149df6a8af2f5", - "reference": "4abe53609dfc23b2ea82884d12b149df6a8af2f5", + "url": "https://api.github.com/repos/utopia-php/database/zipball/42bfc0d87de4ade26cfd9915aaad84912761466b", + "reference": "42bfc0d87de4ade26cfd9915aaad84912761466b", "shasum": "" }, "require": { @@ -3553,9 +3553,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.69.5" + "source": "https://github.com/utopia-php/database/tree/0.69.6" }, - "time": "2025-05-17T08:01:51+00:00" + "time": "2025-05-29T10:36:03+00:00" }, { "name": "utopia-php/detector", @@ -7266,23 +7266,24 @@ }, { "name": "symfony/console", - "version": "v7.2.6", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218" + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/0e2e3f38c192e93e622e41ec37f4ca70cfedf218", - "reference": "0e2e3f38c192e93e622e41ec37f4ca70cfedf218", + "url": "https://api.github.com/repos/symfony/console/zipball/66c1440edf6f339fd82ed6c7caa76cb006211b44", + "reference": "66c1440edf6f339fd82ed6c7caa76cb006211b44", "shasum": "" }, "require": { "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", "symfony/polyfill-mbstring": "~1.0", "symfony/service-contracts": "^2.5|^3", - "symfony/string": "^6.4|^7.0" + "symfony/string": "^7.2" }, "conflict": { "symfony/dependency-injection": "<6.4", @@ -7339,7 +7340,7 @@ "terminal" ], "support": { - "source": "https://github.com/symfony/console/tree/v7.2.6" + "source": "https://github.com/symfony/console/tree/v7.3.0" }, "funding": [ { @@ -7355,11 +7356,11 @@ "type": "tidelift" } ], - "time": "2025-04-07T19:09:28+00:00" + "time": "2025-05-24T10:34:04+00:00" }, { "name": "symfony/filesystem", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/filesystem.git", @@ -7405,7 +7406,7 @@ "description": "Provides basic utilities for the filesystem", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/filesystem/tree/v7.2.0" + "source": "https://github.com/symfony/filesystem/tree/v7.3.0" }, "funding": [ { @@ -7425,16 +7426,16 @@ }, { "name": "symfony/finder", - "version": "v7.2.2", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/finder.git", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb" + "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/finder/zipball/87a71856f2f56e4100373e92529eed3171695cfb", - "reference": "87a71856f2f56e4100373e92529eed3171695cfb", + "url": "https://api.github.com/repos/symfony/finder/zipball/ec2344cf77a48253bbca6939aa3d2477773ea63d", + "reference": "ec2344cf77a48253bbca6939aa3d2477773ea63d", "shasum": "" }, "require": { @@ -7469,7 +7470,7 @@ "description": "Finds files and directories via an intuitive fluent interface", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/finder/tree/v7.2.2" + "source": "https://github.com/symfony/finder/tree/v7.3.0" }, "funding": [ { @@ -7485,20 +7486,20 @@ "type": "tidelift" } ], - "time": "2024-12-30T19:00:17+00:00" + "time": "2024-12-30T19:00:26+00:00" }, { "name": "symfony/options-resolver", - "version": "v7.2.0", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/options-resolver.git", - "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50" + "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/options-resolver/zipball/7da8fbac9dcfef75ffc212235d76b2754ce0cf50", - "reference": "7da8fbac9dcfef75ffc212235d76b2754ce0cf50", + "url": "https://api.github.com/repos/symfony/options-resolver/zipball/afb9a8038025e5dbc657378bfab9198d75f10fca", + "reference": "afb9a8038025e5dbc657378bfab9198d75f10fca", "shasum": "" }, "require": { @@ -7536,7 +7537,7 @@ "options" ], "support": { - "source": "https://github.com/symfony/options-resolver/tree/v7.2.0" + "source": "https://github.com/symfony/options-resolver/tree/v7.3.0" }, "funding": [ { @@ -7552,7 +7553,7 @@ "type": "tidelift" } ], - "time": "2024-11-20T11:17:29+00:00" + "time": "2025-04-04T13:12:05+00:00" }, { "name": "symfony/polyfill-ctype", @@ -7870,16 +7871,16 @@ }, { "name": "symfony/process", - "version": "v7.2.5", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/process.git", - "reference": "87b7c93e57df9d8e39a093d32587702380ff045d" + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/process/zipball/87b7c93e57df9d8e39a093d32587702380ff045d", - "reference": "87b7c93e57df9d8e39a093d32587702380ff045d", + "url": "https://api.github.com/repos/symfony/process/zipball/40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", + "reference": "40c295f2deb408d5e9d2d32b8ba1dd61e36f05af", "shasum": "" }, "require": { @@ -7911,7 +7912,7 @@ "description": "Executes commands in sub-processes", "homepage": "https://symfony.com", "support": { - "source": "https://github.com/symfony/process/tree/v7.2.5" + "source": "https://github.com/symfony/process/tree/v7.3.0" }, "funding": [ { @@ -7927,20 +7928,20 @@ "type": "tidelift" } ], - "time": "2025-03-13T12:21:46+00:00" + "time": "2025-04-17T09:11:12+00:00" }, { "name": "symfony/string", - "version": "v7.2.6", + "version": "v7.3.0", "source": { "type": "git", "url": "https://github.com/symfony/string.git", - "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931" + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/string/zipball/a214fe7d62bd4df2a76447c67c6b26e1d5e74931", - "reference": "a214fe7d62bd4df2a76447c67c6b26e1d5e74931", + "url": "https://api.github.com/repos/symfony/string/zipball/f3570b8c61ca887a9e2938e85cb6458515d2b125", + "reference": "f3570b8c61ca887a9e2938e85cb6458515d2b125", "shasum": "" }, "require": { @@ -7998,7 +7999,7 @@ "utf8" ], "support": { - "source": "https://github.com/symfony/string/tree/v7.2.6" + "source": "https://github.com/symfony/string/tree/v7.3.0" }, "funding": [ { @@ -8014,7 +8015,7 @@ "type": "tidelift" } ], - "time": "2025-04-20T20:18:16+00:00" + "time": "2025-04-20T20:19:01+00:00" }, { "name": "textalk/websocket", From d7653c68cebaffb3d299f9058604604ac39831ad Mon Sep 17 00:00:00 2001 From: fogelito Date: Thu, 29 May 2025 14:51:18 +0300 Subject: [PATCH 147/219] formatting --- src/Appwrite/Migration/Version/V22.php | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/Appwrite/Migration/Version/V22.php b/src/Appwrite/Migration/Version/V22.php index 33e18e2956..a3197ec3d9 100644 --- a/src/Appwrite/Migration/Version/V22.php +++ b/src/Appwrite/Migration/Version/V22.php @@ -145,17 +145,17 @@ class V22 extends Migration $this->dbForProject->purgeCachedCollection($id); break; case 'memberships': -// $indexes = [ -// '_key_roles', -// ]; -// foreach ($indexes as $index) { -// try { -// $this->createIndexFromCollection($this->dbForProject, $id, $index); -// } catch (Throwable $th) { -// Console::warning("Failed to create index \"$index\" from {$id}: {$th->getMessage()}"); -// } -// } -// $this->dbForProject->purgeCachedCollection($id); + // $indexes = [ + // '_key_roles', + // ]; + // foreach ($indexes as $index) { + // try { + // $this->createIndexFromCollection($this->dbForProject, $id, $index); + // } catch (Throwable $th) { + // Console::warning("Failed to create index \"$index\" from {$id}: {$th->getMessage()}"); + // } + // } + // $this->dbForProject->purgeCachedCollection($id); break; case 'migrations': $attributes = [ From c6b1209b8ff351c336c15b7139eb19d9b76f6ef1 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 30 May 2025 00:32:55 +1200 Subject: [PATCH 148/219] Disable TCP hook on stats resources --- src/Appwrite/Platform/Tasks/StatsResources.php | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Appwrite/Platform/Tasks/StatsResources.php b/src/Appwrite/Platform/Tasks/StatsResources.php index ca2a6860ff..bcc2d242d7 100644 --- a/src/Appwrite/Platform/Tasks/StatsResources.php +++ b/src/Appwrite/Platform/Tasks/StatsResources.php @@ -4,6 +4,7 @@ namespace Appwrite\Platform\Tasks; use Appwrite\Event\StatsResources as EventStatsResources; use Appwrite\Platform\Action; +use Swoole\Runtime; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\DateTime; @@ -50,6 +51,8 @@ class StatsResources extends Action public function action(Database $dbForPlatform, callable $logError, EventStatsResources $queue): void { + Runtime::enableCoroutine(SWOOLE_HOOK_ALL ^ SWOOLE_HOOK_TCP); + $this->logError = $logError; $this->dbForPlatform = $dbForPlatform; From 0097a0edcd996896e34c4c83a1539601401e1614 Mon Sep 17 00:00:00 2001 From: fogelito Date: Thu, 29 May 2025 15:37:08 +0300 Subject: [PATCH 149/219] Update migration self-hosted --- src/Appwrite/Migration/Version/V22.php | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/src/Appwrite/Migration/Version/V22.php b/src/Appwrite/Migration/Version/V22.php index a3197ec3d9..fd80af565b 100644 --- a/src/Appwrite/Migration/Version/V22.php +++ b/src/Appwrite/Migration/Version/V22.php @@ -145,17 +145,16 @@ class V22 extends Migration $this->dbForProject->purgeCachedCollection($id); break; case 'memberships': - // $indexes = [ - // '_key_roles', - // ]; - // foreach ($indexes as $index) { - // try { - // $this->createIndexFromCollection($this->dbForProject, $id, $index); - // } catch (Throwable $th) { - // Console::warning("Failed to create index \"$index\" from {$id}: {$th->getMessage()}"); - // } - // } - // $this->dbForProject->purgeCachedCollection($id); + $indexes = [ + '_key_roles', + ]; + foreach ($indexes as $index) { + try { + $this->dbForProject->deleteIndex($id, $index); + } catch (Throwable $th) { + Console::warning("Failed to delete index \"$index\" from {$id}: {$th->getMessage()}"); + } + } break; case 'migrations': $attributes = [ From 9829ba2afba6fc621ff581bda8754ed41bc3a0a0 Mon Sep 17 00:00:00 2001 From: fogelito Date: Thu, 29 May 2025 15:40:11 +0300 Subject: [PATCH 150/219] Not sure we need it but ok --- src/Appwrite/Migration/Version/V22.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Appwrite/Migration/Version/V22.php b/src/Appwrite/Migration/Version/V22.php index fd80af565b..cfe4f1fe57 100644 --- a/src/Appwrite/Migration/Version/V22.php +++ b/src/Appwrite/Migration/Version/V22.php @@ -155,6 +155,7 @@ class V22 extends Migration Console::warning("Failed to delete index \"$index\" from {$id}: {$th->getMessage()}"); } } + $this->dbForProject->purgeCachedCollection($id); break; case 'migrations': $attributes = [ From 0a80ffe4a7e6b781e9eaf3cd42f876fc5c6b6554 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Thu, 29 May 2025 18:29:15 +0530 Subject: [PATCH 151/219] Fix error --- tests/e2e/Services/Sites/SitesCustomServerTest.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index 8459e46c6f..879182539a 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -1446,7 +1446,7 @@ class SitesCustomServerTest extends Scope $this->assertEquals(404, $response['headers']['status-code']); $this->assertStringContainsString("Page not found", $response['body']); // Title $this->assertStringContainsString("Go to homepage", $response['body']); // Button - $this->assertStringNotContainsString("Powered by", $response['body']); // Brand + $this->assertStringContainsString("Powered by", $response['body']); // Brand $this->cleanupSite($siteId); } From 972c9dde210a64d42ae4c7123119bf856f205a41 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 30 May 2025 01:51:00 +1200 Subject: [PATCH 152/219] Revert "Merge pull request #9932 from appwrite/fix-disable-tcp-hook" This reverts commit 7a34c7b8dfd3784f2c393f30d1d5f2398642ef37, reversing changes made to 2b9b76f7bd6fc3dec0d8b85e9cea94c15035d3a7. --- src/Appwrite/Platform/Tasks/StatsResources.php | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/StatsResources.php b/src/Appwrite/Platform/Tasks/StatsResources.php index bcc2d242d7..ca2a6860ff 100644 --- a/src/Appwrite/Platform/Tasks/StatsResources.php +++ b/src/Appwrite/Platform/Tasks/StatsResources.php @@ -4,7 +4,6 @@ namespace Appwrite\Platform\Tasks; use Appwrite\Event\StatsResources as EventStatsResources; use Appwrite\Platform\Action; -use Swoole\Runtime; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\DateTime; @@ -51,8 +50,6 @@ class StatsResources extends Action public function action(Database $dbForPlatform, callable $logError, EventStatsResources $queue): void { - Runtime::enableCoroutine(SWOOLE_HOOK_ALL ^ SWOOLE_HOOK_TCP); - $this->logError = $logError; $this->dbForPlatform = $dbForPlatform; From 502b7df2d0b18393b17890c033fbaedef9889cf2 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Fri, 30 May 2025 11:26:05 +0530 Subject: [PATCH 153/219] Remove powered by from all error pages --- app/views/general/404.phtml | 4 ++-- tests/e2e/Services/Sites/SitesCustomServerTest.php | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/views/general/404.phtml b/app/views/general/404.phtml index 5e63344c8a..fb06c07f3e 100644 --- a/app/views/general/404.phtml +++ b/app/views/general/404.phtml @@ -152,7 +152,7 @@
-
+ \ No newline at end of file diff --git a/tests/e2e/Services/Sites/SitesCustomServerTest.php b/tests/e2e/Services/Sites/SitesCustomServerTest.php index 879182539a..8459e46c6f 100644 --- a/tests/e2e/Services/Sites/SitesCustomServerTest.php +++ b/tests/e2e/Services/Sites/SitesCustomServerTest.php @@ -1446,7 +1446,7 @@ class SitesCustomServerTest extends Scope $this->assertEquals(404, $response['headers']['status-code']); $this->assertStringContainsString("Page not found", $response['body']); // Title $this->assertStringContainsString("Go to homepage", $response['body']); // Button - $this->assertStringContainsString("Powered by", $response['body']); // Brand + $this->assertStringNotContainsString("Powered by", $response['body']); // Brand $this->cleanupSite($siteId); } From 34150f0c380dbe79b2213088378598fdba519cf1 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Fri, 30 May 2025 12:39:33 +0530 Subject: [PATCH 154/219] Remove div --- app/views/general/404.phtml | 31 ------------------------------- 1 file changed, 31 deletions(-) diff --git a/app/views/general/404.phtml b/app/views/general/404.phtml index fb06c07f3e..2a9ff7f312 100644 --- a/app/views/general/404.phtml +++ b/app/views/general/404.phtml @@ -151,37 +151,6 @@
- - \ No newline at end of file From 2ef2c59d187acebaea28974678355873e31d23c9 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 30 May 2025 14:03:51 +0530 Subject: [PATCH 155/219] update: exceptions and messages. --- app/config/errors.php | 10 ++++++++++ app/controllers/api/teams.php | 7 ++----- src/Appwrite/Extend/Exception.php | 2 ++ 3 files changed, 14 insertions(+), 5 deletions(-) diff --git a/app/config/errors.php b/app/config/errors.php index 6d9d29a8ea..8365e8c705 100644 --- a/app/config/errors.php +++ b/app/config/errors.php @@ -393,6 +393,16 @@ return [ 'description' => 'Membership is already confirmed.', 'code' => 409, ], + Exception::MEMBERSHIP_DELETION_PROHIBITED => [ + 'name' => Exception::MEMBERSHIP_DELETION_PROHIBITED, + 'description' => 'Membership deletion is prohibited.', + 'code' => 400, + ], + Exception::MEMBERSHIP_DOWNGRADE_PROHIBITED => [ + 'name' => Exception::MEMBERSHIP_DOWNGRADE_PROHIBITED, + 'description' => 'Membership role downgrade is prohibited.', + 'code' => 400, + ], /** Avatars */ Exception::AVATAR_SET_NOT_FOUND => [ diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index aa85852049..cc10b7cead 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -1103,7 +1103,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') // Prevent role change if there's only one owner left, // the requester is that owner, and the new `$roles` no longer include 'owner' if ($ownersCount === 1 && $isOwner && $isCurrentUserAnOwner && !\in_array('owner', $roles)) { - throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'There must be at least one owner in the organization.'); + throw new Exception(Exception::MEMBERSHIP_DOWNGRADE_PROHIBITED, 'There must be at least one owner.'); } } @@ -1364,10 +1364,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') if ($ownersCount === 1 && $isCurrentUserAnOwner) { /* Prevent removal if the user is the only owner. */ - throw new Exception( - Exception::GENERAL_ARGUMENT_INVALID, - 'There must be at least one owner in the organization.' - ); + throw new Exception(Exception::MEMBERSHIP_DELETION_PROHIBITED, 'There must be at least one owner.'); } } diff --git a/src/Appwrite/Extend/Exception.php b/src/Appwrite/Extend/Exception.php index 296434ed57..3af6d9962c 100644 --- a/src/Appwrite/Extend/Exception.php +++ b/src/Appwrite/Extend/Exception.php @@ -124,6 +124,8 @@ class Exception extends \Exception /** Membership */ public const MEMBERSHIP_NOT_FOUND = 'membership_not_found'; public const MEMBERSHIP_ALREADY_CONFIRMED = 'membership_already_confirmed'; + public const MEMBERSHIP_DELETION_PROHIBITED = 'membership_deletion_prohibited'; + public const MEMBERSHIP_DOWNGRADE_PROHIBITED = 'membership_downgrade_prohibited'; /** Avatars */ public const AVATAR_SET_NOT_FOUND = 'avatar_set_not_found'; From 65ae22d7cd6af437066320d210b44ad1defe0513 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 30 May 2025 14:08:25 +0530 Subject: [PATCH 156/219] update: messages because the check is only for console project > organizations. --- app/controllers/api/teams.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index cc10b7cead..ede61115e2 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -1103,7 +1103,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') // Prevent role change if there's only one owner left, // the requester is that owner, and the new `$roles` no longer include 'owner' if ($ownersCount === 1 && $isOwner && $isCurrentUserAnOwner && !\in_array('owner', $roles)) { - throw new Exception(Exception::MEMBERSHIP_DOWNGRADE_PROHIBITED, 'There must be at least one owner.'); + throw new Exception(Exception::MEMBERSHIP_DOWNGRADE_PROHIBITED, 'There must be at least one owner in the organization.'); } } @@ -1364,7 +1364,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') if ($ownersCount === 1 && $isCurrentUserAnOwner) { /* Prevent removal if the user is the only owner. */ - throw new Exception(Exception::MEMBERSHIP_DELETION_PROHIBITED, 'There must be at least one owner.'); + throw new Exception(Exception::MEMBERSHIP_DELETION_PROHIBITED, 'There must be at least one owner in the organization.'); } } From b3098085924e4a1df7d0d242ad8347ab6c478f71 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Fri, 30 May 2025 14:18:35 +0530 Subject: [PATCH 157/219] Remove all 'powered by' divs --- app/views/general/error.phtml | 30 ------------------------------ 1 file changed, 30 deletions(-) diff --git a/app/views/general/error.phtml b/app/views/general/error.phtml index 9706c8ee94..a427f1d5e8 100644 --- a/app/views/general/error.phtml +++ b/app/views/general/error.phtml @@ -512,36 +512,6 @@ switch ($type) { - \ No newline at end of file From 3063ac899c9a1cd971e068db3f04020a358fe1b4 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 30 May 2025 14:21:11 +0530 Subject: [PATCH 158/219] update: tests. --- tests/e2e/Services/Teams/TeamsBase.php | 2 +- tests/e2e/Services/Teams/TeamsConsoleClientTest.php | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/e2e/Services/Teams/TeamsBase.php b/tests/e2e/Services/Teams/TeamsBase.php index 80ac1621ee..fccfded1e1 100644 --- a/tests/e2e/Services/Teams/TeamsBase.php +++ b/tests/e2e/Services/Teams/TeamsBase.php @@ -64,7 +64,7 @@ trait TeamsBase // Step 4: Assert failure — cannot remove the only OWNER from a team $this->assertEquals(400, $response['headers']['status-code']); - $this->assertEquals('general_argument_invalid', $response['body']['type']); + $this->assertEquals('membership_downgrade_prohibited', $response['body']['type']); $this->assertEquals('There must be at least one owner in the organization.', $response['body']['message']); } diff --git a/tests/e2e/Services/Teams/TeamsConsoleClientTest.php b/tests/e2e/Services/Teams/TeamsConsoleClientTest.php index 59945b1191..dda7f8e4ae 100644 --- a/tests/e2e/Services/Teams/TeamsConsoleClientTest.php +++ b/tests/e2e/Services/Teams/TeamsConsoleClientTest.php @@ -100,6 +100,7 @@ class TeamsConsoleClientTest extends Scope ], $this->getHeaders())); $this->assertEquals(400, $response['headers']['status-code']); + $this->assertEquals('membership_deletion_prohibited', $response['body']['type']); $this->assertEquals('There must be at least one owner in the organization.', $response['body']['message']); // Remove the excess developer member to reduce the membership count in `TeamsBaseClient` tests. @@ -241,6 +242,7 @@ class TeamsConsoleClientTest extends Scope ], $this->getHeaders())); $this->assertEquals(400, $response['headers']['status-code']); + $this->assertEquals('membership_deletion_prohibited', $response['body']['type']); $this->assertEquals('There must be at least one owner in the organization.', $response['body']['message']); $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships/' . $ownerMembershipUid, array_merge([ From 4fc84bec7d6153a5dacf4cc1f8df8177988b6350 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 30 May 2025 14:33:37 +0530 Subject: [PATCH 159/219] reset: stuff on target branch. --- .github/workflows/sdk-preview.yml | 2 +- app/cli.php | 3 +- app/config/platforms.php | 6 +- app/controllers/api/storage.php | 60 +++++++++---------- docs/sdks/flutter/CHANGELOG.md | 4 +- src/Appwrite/Platform/Tasks/ScheduleBase.php | 10 ++-- .../Platform/Tasks/ScheduleFunctions.php | 2 +- 7 files changed, 42 insertions(+), 45 deletions(-) diff --git a/.github/workflows/sdk-preview.yml b/.github/workflows/sdk-preview.yml index 8abe2c2f91..e317845768 100644 --- a/.github/workflows/sdk-preview.yml +++ b/.github/workflows/sdk-preview.yml @@ -47,7 +47,7 @@ jobs: node-version: 20 - name: Build and Publish SDK - working-directory: ./app/sdks/${{ steps.set-sdk.outputs.platform }}-${{ steps.set-sdk.outputs.sdk_type }} + working-directory: ./app/sdks/console-web run: | npm install npm run build diff --git a/app/cli.php b/app/cli.php index 9517347420..7c2daf4500 100644 --- a/app/cli.php +++ b/app/cli.php @@ -284,6 +284,5 @@ $cli $cli->shutdown()->action(fn () => Timer::clearAll()); -// Enable coroutines, but disable TCP hooks. These don't work until we use `\Utopia\Cache\Adapter\Pool` and `\Utopia\Database\Adapter\Pool`. -Runtime::enableCoroutine(SWOOLE_HOOK_ALL ^ SWOOLE_HOOK_TCP); +Runtime::enableCoroutine(SWOOLE_HOOK_ALL); run($cli->run(...)); diff --git a/app/config/platforms.php b/app/config/platforms.php index 4b2faf0487..7d481d508e 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -11,7 +11,7 @@ return [ [ 'key' => 'web', 'name' => 'Web', - 'version' => '18.1.1', + 'version' => '18.1.0', 'url' => 'https://github.com/appwrite/sdk-for-web', 'package' => 'https://www.npmjs.com/package/appwrite', 'enabled' => true, @@ -59,7 +59,7 @@ return [ [ 'key' => 'flutter', 'name' => 'Flutter', - 'version' => '17.0.0', + 'version' => '16.1.0', 'url' => 'https://github.com/appwrite/sdk-for-flutter', 'package' => 'https://pub.dev/packages/appwrite', 'enabled' => true, @@ -134,7 +134,7 @@ return [ [ 'key' => 'react-native', 'name' => 'React Native', - 'version' => '0.9.2', + 'version' => '0.9.1', 'url' => 'https://github.com/appwrite/sdk-for-react-native', 'package' => 'https://npmjs.com/package/react-native-appwrite', 'enabled' => true, diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index b3b8fb906a..d2edf476f6 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -1004,7 +1004,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $algorithm = $file->getAttribute('algorithm', Compression::NONE); $cipher = $file->getAttribute('openSSLCipher'); $mime = $file->getAttribute('mimeType'); - if (!\in_array($mime, $inputs) || $file->getAttribute('sizeActual') > (int) System::getEnv('_APP_STORAGE_PREVIEW_LIMIT', 20000000)) { + if (!\in_array($mime, $inputs) || $file->getAttribute('sizeActual') > (int) System::getEnv('_APP_STORAGE_PREVIEW_LIMIT', APP_STORAGE_READ_BUFFER)) { if (!\in_array($mime, $inputs)) { $path = (\array_key_exists($mime, $fileLogos)) ? $fileLogos[$mime] : $fileLogos['default']; } else { @@ -1178,13 +1178,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in ' . $path); } - $response - ->setContentType($file->getAttribute('mimeType')) - ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days - ->addHeader('X-Peak', \memory_get_peak_usage()) - ->addHeader('Content-Disposition', 'attachment; filename="' . $file->getAttribute('name', '') . '"') - ; - $size = $file->getAttribute('sizeOriginal', 0); $rangeHeader = $request->getHeader('range'); @@ -1193,7 +1186,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') $end = $request->getRangeEnd(); $unit = $request->getRangeUnit(); - if ($end === null) { + if ($end === null || $end - $start > APP_STORAGE_READ_BUFFER) { $end = min(($start + MAX_OUTPUT_CHUNK_SIZE - 1), ($size - 1)); } @@ -1208,6 +1201,13 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') ->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT); } + $response + ->setContentType($file->getAttribute('mimeType')) + ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days + ->addHeader('X-Peak', \memory_get_peak_usage()) + ->addHeader('Content-Disposition', 'attachment; filename="' . $file->getAttribute('name', '') . '"') + ; + $source = ''; if (!empty($file->getAttribute('openSSLCipher'))) { // Decrypt $source = $deviceForFiles->read($path); @@ -1345,15 +1345,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') $contentType = $file->getAttribute('mimeType'); } - $response - ->setContentType($contentType) - ->addHeader('Content-Security-Policy', 'script-src none;') - ->addHeader('X-Content-Type-Options', 'nosniff') - ->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"') - ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days - ->addHeader('X-Peak', \memory_get_peak_usage()) - ; - $size = $file->getAttribute('sizeOriginal', 0); $rangeHeader = $request->getHeader('range'); @@ -1362,8 +1353,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') $end = $request->getRangeEnd(); $unit = $request->getRangeUnit(); - if ($end === null) { - $end = min(($start + 2000000 - 1), ($size - 1)); + if ($end === null || $end - $start > APP_STORAGE_READ_BUFFER) { + $end = min(($start + APP_STORAGE_READ_BUFFER - 1), ($size - 1)); } if ($unit != 'bytes' || $start >= $end || $end >= $size) { @@ -1377,6 +1368,15 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') ->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT); } + $response + ->setContentType($contentType) + ->addHeader('Content-Security-Policy', 'script-src none;') + ->addHeader('X-Content-Type-Options', 'nosniff') + ->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"') + ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days + ->addHeader('X-Peak', \memory_get_peak_usage()) + ; + $source = ''; if (!empty($file->getAttribute('openSSLCipher'))) { // Decrypt $source = $deviceForFiles->read($path); @@ -1498,14 +1498,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') $contentType = $file->getAttribute('mimeType'); } - $response - ->setContentType($contentType) - ->addHeader('Content-Security-Policy', 'script-src none;') - ->addHeader('X-Content-Type-Options', 'nosniff') - ->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"') - ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days - ->addHeader('X-Peak', \memory_get_peak_usage()); - $size = $file->getAttribute('sizeOriginal', 0); $rangeHeader = $request->getHeader('range'); @@ -1514,8 +1506,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') $end = $request->getRangeEnd(); $unit = $request->getRangeUnit(); - if ($end === null) { - $end = min(($start + 2000000 - 1), ($size - 1)); + if ($end === null || $end - $start > APP_STORAGE_READ_BUFFER) { + $end = min(($start + APP_STORAGE_READ_BUFFER - 1), ($size - 1)); } if ($unit != 'bytes' || $start >= $end || $end >= $size) { @@ -1529,6 +1521,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') ->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT); } + $response + ->setContentType($contentType) + ->addHeader('Content-Security-Policy', 'script-src none;') + ->addHeader('X-Content-Type-Options', 'nosniff') + ->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"') + ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days + ->addHeader('X-Peak', \memory_get_peak_usage()); + $source = ''; if (!empty($file->getAttribute('openSSLCipher'))) { // Decrypt $source = $deviceForFiles->read($path); diff --git a/docs/sdks/flutter/CHANGELOG.md b/docs/sdks/flutter/CHANGELOG.md index 1a9b8c2e29..f707c645e6 100644 --- a/docs/sdks/flutter/CHANGELOG.md +++ b/docs/sdks/flutter/CHANGELOG.md @@ -1,11 +1,9 @@ # Change Log -## 17.0.0 +## 16.1.1 * Update `flutter_web_auth_2` dependency to version 4.1.0 * Update `auth.html` example in README.md to align with `flutter_web_auth_2` documentation -* Breaking changes: - * Minimum iOS version supported is now 17.4 due to the updated requirements of `flutter_web_auth_2` version 4.1.0 ## 16.1.0 diff --git a/src/Appwrite/Platform/Tasks/ScheduleBase.php b/src/Appwrite/Platform/Tasks/ScheduleBase.php index 286ffe45cb..28c77c1832 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleBase.php +++ b/src/Appwrite/Platform/Tasks/ScheduleBase.php @@ -79,16 +79,16 @@ abstract class ScheduleBase extends Action // start with "0" to load all active documents. $lastSyncUpdate = "0"; - $this->collectSchedules($pools, $dbForPlatform, $getProjectDB, $lastSyncUpdate); + $this->collectSchedules($dbForPlatform, $getProjectDB, $lastSyncUpdate); Console::success("Starting timers at " . DateTime::now()); /** * The timer synchronize $schedules copy with database collection. */ - Timer::tick(static::UPDATE_TIMER * 1000, function () use ($pools, $dbForPlatform, $getProjectDB, &$lastSyncUpdate) { + Timer::tick(static::UPDATE_TIMER * 1000, function () use ($dbForPlatform, $getProjectDB, &$lastSyncUpdate) { $time = DateTime::now(); Console::log("Sync tick: Running at $time"); - $this->collectSchedules($pools, $dbForPlatform, $getProjectDB, $lastSyncUpdate); + $this->collectSchedules($dbForPlatform, $getProjectDB, $lastSyncUpdate); }); while (true) { @@ -103,7 +103,7 @@ abstract class ScheduleBase extends Action } } - private function collectSchedules(Group $pools, Database $dbForPlatform, callable $getProjectDB, string &$lastSyncUpdate): void + private function collectSchedules(Database $dbForPlatform, callable $getProjectDB, string &$lastSyncUpdate): void { // If we haven't synced yet, load all active schedules $initialLoad = $lastSyncUpdate === "0"; @@ -115,7 +115,7 @@ abstract class ScheduleBase extends Action * @throws Exception * @var Document $schedule */ - $getSchedule = function (Document $schedule) use ($pools, $dbForPlatform, $getProjectDB): array { + $getSchedule = function (Document $schedule) use ($dbForPlatform, $getProjectDB): array { $project = $dbForPlatform->getDocument('projects', $schedule->getAttribute('projectId')); $resource = $getProjectDB($project)->getDocument( diff --git a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php index 19e068107a..7812b27832 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleFunctions.php +++ b/src/Appwrite/Platform/Tasks/ScheduleFunctions.php @@ -76,7 +76,7 @@ class ScheduleFunctions extends ScheduleBase } foreach ($delayedExecutions as $delay => $schedules) { - \go(function () use ($delay, $schedules, $pools, $dbForPlatform) { + \go(function () use ($delay, $schedules, $dbForPlatform) { \sleep($delay); // in seconds foreach ($schedules as $delayConfig) { From 36bc41a748a03f3820d514d9064edd4cc1b4bad4 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 30 May 2025 14:34:21 +0530 Subject: [PATCH 160/219] reset: stuff on target branch [missed]. --- src/Appwrite/Platform/Tasks/ScheduleMessages.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Tasks/ScheduleMessages.php b/src/Appwrite/Platform/Tasks/ScheduleMessages.php index 5e65f7a8a6..d23e3de575 100644 --- a/src/Appwrite/Platform/Tasks/ScheduleMessages.php +++ b/src/Appwrite/Platform/Tasks/ScheduleMessages.php @@ -40,7 +40,7 @@ class ScheduleMessages extends ScheduleBase continue; } - \go(function () use ($schedule, $scheduledAt, $pools, $dbForPlatform) { + \go(function () use ($schedule, $scheduledAt, $dbForPlatform) { $queueForMessaging = new Messaging($this->publisher); $this->updateProjectAccess($schedule['project'], $dbForPlatform); From 1f5d2b0ec61a09fa8a91bd420228dae67cb9310b Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Fri, 30 May 2025 22:08:04 +1200 Subject: [PATCH 161/219] Update queue --- composer.json | 2 +- composer.lock | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/composer.json b/composer.json index 833f1a462b..b7f7809219 100644 --- a/composer.json +++ b/composer.json @@ -67,7 +67,7 @@ "utopia-php/platform": "0.7.*", "utopia-php/pools": "0.8.*", "utopia-php/preloader": "0.2.*", - "utopia-php/queue": "0.10.*", + "utopia-php/queue": "0.11.*", "utopia-php/registry": "0.5.*", "utopia-php/storage": "0.18.*", "utopia-php/swoole": "0.8.*", diff --git a/composer.lock b/composer.lock index 8ecfcf6a18..b7b1f23545 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "de0a0fb794f826fcc412c788185b69f4", + "content-hash": "3230eea9e592f0b712e78c1ef5f5e244", "packages": [ { "name": "adhocore/jwt", @@ -4109,16 +4109,16 @@ }, { "name": "utopia-php/platform", - "version": "0.7.7", + "version": "0.7.8", "source": { "type": "git", "url": "https://github.com/utopia-php/platform.git", - "reference": "8c43cd866148a7c4c495e3401268429e338004b3" + "reference": "e3a4536c46f10988b1a446ec6b8dd8a9914be854" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/platform/zipball/8c43cd866148a7c4c495e3401268429e338004b3", - "reference": "8c43cd866148a7c4c495e3401268429e338004b3", + "url": "https://api.github.com/repos/utopia-php/platform/zipball/e3a4536c46f10988b1a446ec6b8dd8a9914be854", + "reference": "e3a4536c46f10988b1a446ec6b8dd8a9914be854", "shasum": "" }, "require": { @@ -4127,7 +4127,7 @@ "php": ">=8.0", "utopia-php/cli": "0.15.*", "utopia-php/framework": "0.33.*", - "utopia-php/queue": "0.10.*" + "utopia-php/queue": "0.11.*" }, "require-dev": { "laravel/pint": "1.*", @@ -4153,9 +4153,9 @@ ], "support": { "issues": "https://github.com/utopia-php/platform/issues", - "source": "https://github.com/utopia-php/platform/tree/0.7.7" + "source": "https://github.com/utopia-php/platform/tree/0.7.8" }, - "time": "2025-05-20T09:23:44+00:00" + "time": "2025-05-30T10:05:43+00:00" }, { "name": "utopia-php/pools", @@ -4264,16 +4264,16 @@ }, { "name": "utopia-php/queue", - "version": "0.10.0", + "version": "0.11.0", "source": { "type": "git", "url": "https://github.com/utopia-php/queue.git", - "reference": "0eccc559168ea72241c39a4c482d868314666be1" + "reference": "06b5ced0eaed2ecc6aab6d8e1b4d96bff37a1ce5" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/queue/zipball/0eccc559168ea72241c39a4c482d868314666be1", - "reference": "0eccc559168ea72241c39a4c482d868314666be1", + "url": "https://api.github.com/repos/utopia-php/queue/zipball/06b5ced0eaed2ecc6aab6d8e1b4d96bff37a1ce5", + "reference": "06b5ced0eaed2ecc6aab6d8e1b4d96bff37a1ce5", "shasum": "" }, "require": { @@ -4324,9 +4324,9 @@ ], "support": { "issues": "https://github.com/utopia-php/queue/issues", - "source": "https://github.com/utopia-php/queue/tree/0.10.0" + "source": "https://github.com/utopia-php/queue/tree/0.11.0" }, - "time": "2025-04-17T12:15:52+00:00" + "time": "2025-05-30T09:52:38+00:00" }, { "name": "utopia-php/registry", From 8d5d9dc463c4995fba597bb7f7f0d0b3edc268d1 Mon Sep 17 00:00:00 2001 From: Fabian Gruber Date: Mon, 14 Apr 2025 12:17:12 +0200 Subject: [PATCH 162/219] chore: use exec to replace /bin/sh shell with the actual program --- bin/doctor | 2 +- bin/install | 2 +- bin/maintenance | 2 +- bin/migrate | 2 +- bin/queue-count-failed | 2 +- bin/queue-count-processing | 2 +- bin/queue-count-success | 2 +- bin/queue-retry | 2 +- bin/realtime | 2 +- bin/schedule-executions | 2 +- bin/schedule-functions | 2 +- bin/schedule-messages | 2 +- bin/sdks | 2 +- bin/specs | 2 +- bin/ssl | 2 +- bin/stats-resources | 2 +- bin/test | 2 +- bin/upgrade | 2 +- bin/vars | 2 +- bin/worker-audits | 2 +- bin/worker-builds | 2 +- bin/worker-certificates | 2 +- bin/worker-databases | 2 +- bin/worker-deletes | 2 +- bin/worker-functions | 2 +- bin/worker-mails | 2 +- bin/worker-messaging | 2 +- bin/worker-migrations | 2 +- bin/worker-stats-resources | 2 +- bin/worker-stats-usage | 2 +- bin/worker-webhooks | 2 +- 31 files changed, 31 insertions(+), 31 deletions(-) diff --git a/bin/doctor b/bin/doctor index b2a4547156..92b3cf6bf8 100755 --- a/bin/doctor +++ b/bin/doctor @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/cli.php doctor $@ \ No newline at end of file +exec php /usr/src/code/app/cli.php doctor $@ diff --git a/bin/install b/bin/install index e669e91e6b..126d5373bf 100755 --- a/bin/install +++ b/bin/install @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/cli.php install $@ \ No newline at end of file +exec php /usr/src/code/app/cli.php install $@ diff --git a/bin/maintenance b/bin/maintenance index 099551cb32..70273feb61 100644 --- a/bin/maintenance +++ b/bin/maintenance @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/cli.php maintenance $@ \ No newline at end of file +exec php /usr/src/code/app/cli.php maintenance $@ diff --git a/bin/migrate b/bin/migrate index 28ebbd19e7..32bf7ee2f4 100755 --- a/bin/migrate +++ b/bin/migrate @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/cli.php migrate $@ \ No newline at end of file +exec php /usr/src/code/app/cli.php migrate $@ diff --git a/bin/queue-count-failed b/bin/queue-count-failed index ca8f2b4291..93a6b3136c 100644 --- a/bin/queue-count-failed +++ b/bin/queue-count-failed @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/cli.php queue-count --type=failed $@ \ No newline at end of file +exec php /usr/src/code/app/cli.php queue-count --type=failed $@ diff --git a/bin/queue-count-processing b/bin/queue-count-processing index 325d86111d..18e89664bd 100644 --- a/bin/queue-count-processing +++ b/bin/queue-count-processing @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/cli.php queue-count --type=processing $@ \ No newline at end of file +exec php /usr/src/code/app/cli.php queue-count --type=processing $@ diff --git a/bin/queue-count-success b/bin/queue-count-success index 34fc54b4c1..b38bfa2159 100644 --- a/bin/queue-count-success +++ b/bin/queue-count-success @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/cli.php queue-count --type=success $@ \ No newline at end of file +exec php /usr/src/code/app/cli.php queue-count --type=success $@ diff --git a/bin/queue-retry b/bin/queue-retry index f9473e6b07..2224a66b3b 100644 --- a/bin/queue-retry +++ b/bin/queue-retry @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/cli.php queue-retry $@ \ No newline at end of file +exec php /usr/src/code/app/cli.php queue-retry $@ diff --git a/bin/realtime b/bin/realtime index e43dc269e0..debd4baf2a 100644 --- a/bin/realtime +++ b/bin/realtime @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/realtime.php $@ \ No newline at end of file +exec php /usr/src/code/app/realtime.php $@ diff --git a/bin/schedule-executions b/bin/schedule-executions index f239cad206..5d503e374c 100644 --- a/bin/schedule-executions +++ b/bin/schedule-executions @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/cli.php schedule-executions $@ \ No newline at end of file +exec php /usr/src/code/app/cli.php schedule-executions $@ diff --git a/bin/schedule-functions b/bin/schedule-functions index 10edbe8226..beca1a0420 100644 --- a/bin/schedule-functions +++ b/bin/schedule-functions @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/cli.php schedule-functions $@ \ No newline at end of file +exec php /usr/src/code/app/cli.php schedule-functions $@ diff --git a/bin/schedule-messages b/bin/schedule-messages index fa7219f6ea..3f17a279b5 100644 --- a/bin/schedule-messages +++ b/bin/schedule-messages @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/cli.php schedule-messages $@ \ No newline at end of file +exec php /usr/src/code/app/cli.php schedule-messages $@ diff --git a/bin/sdks b/bin/sdks index ab73414829..3180813ea1 100644 --- a/bin/sdks +++ b/bin/sdks @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/cli.php sdks $@ \ No newline at end of file +exec php /usr/src/code/app/cli.php sdks $@ diff --git a/bin/specs b/bin/specs index e77d1487d4..52875a1675 100644 --- a/bin/specs +++ b/bin/specs @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/cli.php specs $@ \ No newline at end of file +exec php /usr/src/code/app/cli.php specs $@ diff --git a/bin/ssl b/bin/ssl index 83dcf6a026..0cc12375d0 100755 --- a/bin/ssl +++ b/bin/ssl @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/cli.php ssl $@ \ No newline at end of file +exec php /usr/src/code/app/cli.php ssl $@ diff --git a/bin/stats-resources b/bin/stats-resources index 3104bab896..9cc67fb4a6 100644 --- a/bin/stats-resources +++ b/bin/stats-resources @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/cli.php stats-resources $@ \ No newline at end of file +exec php /usr/src/code/app/cli.php stats-resources $@ diff --git a/bin/test b/bin/test index a2153fc536..c3b0d9b74c 100755 --- a/bin/test +++ b/bin/test @@ -1,3 +1,3 @@ #!/bin/sh -/usr/src/code/vendor/bin/phpunit --configuration /usr/src/code/phpunit.xml $@ \ No newline at end of file +exec /usr/src/code/vendor/bin/phpunit --configuration /usr/src/code/phpunit.xml $@ diff --git a/bin/upgrade b/bin/upgrade index ce32b9ca30..fd1f35b65a 100755 --- a/bin/upgrade +++ b/bin/upgrade @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/cli.php upgrade $@ \ No newline at end of file +exec php /usr/src/code/app/cli.php upgrade $@ diff --git a/bin/vars b/bin/vars index 19e3f1ebf2..238d004675 100644 --- a/bin/vars +++ b/bin/vars @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/cli.php vars $@ \ No newline at end of file +exec php /usr/src/code/app/cli.php vars $@ diff --git a/bin/worker-audits b/bin/worker-audits index 3df65d65e8..9bf81b93e2 100644 --- a/bin/worker-audits +++ b/bin/worker-audits @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/worker.php audits $@ \ No newline at end of file +exec php /usr/src/code/app/worker.php audits $@ diff --git a/bin/worker-builds b/bin/worker-builds index 3400111cb5..7ddf5792de 100644 --- a/bin/worker-builds +++ b/bin/worker-builds @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/worker.php builds $@ \ No newline at end of file +exec php /usr/src/code/app/worker.php builds $@ diff --git a/bin/worker-certificates b/bin/worker-certificates index 901688c4c8..958627bc33 100755 --- a/bin/worker-certificates +++ b/bin/worker-certificates @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/worker.php certificates $@ \ No newline at end of file +exec php /usr/src/code/app/worker.php certificates $@ diff --git a/bin/worker-databases b/bin/worker-databases index 61e09aa9f1..235c16927c 100644 --- a/bin/worker-databases +++ b/bin/worker-databases @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/worker.php databases $@ +exec php /usr/src/code/app/worker.php databases $@ diff --git a/bin/worker-deletes b/bin/worker-deletes index 7c9793e6cb..c9711a4e66 100644 --- a/bin/worker-deletes +++ b/bin/worker-deletes @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/worker.php deletes $@ \ No newline at end of file +exec php /usr/src/code/app/worker.php deletes $@ diff --git a/bin/worker-functions b/bin/worker-functions index 4757b1b72a..e82506d0e2 100644 --- a/bin/worker-functions +++ b/bin/worker-functions @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/worker.php functions $@ \ No newline at end of file +exec php /usr/src/code/app/worker.php functions $@ diff --git a/bin/worker-mails b/bin/worker-mails index fee8a96da7..ffb4f7ea77 100644 --- a/bin/worker-mails +++ b/bin/worker-mails @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/worker.php mails $@ \ No newline at end of file +exec php /usr/src/code/app/worker.php mails $@ diff --git a/bin/worker-messaging b/bin/worker-messaging index e6edf80f06..6f39348419 100644 --- a/bin/worker-messaging +++ b/bin/worker-messaging @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/worker.php messaging $@ \ No newline at end of file +exec php /usr/src/code/app/worker.php messaging $@ diff --git a/bin/worker-migrations b/bin/worker-migrations index 32d4aef468..2728d9d22c 100644 --- a/bin/worker-migrations +++ b/bin/worker-migrations @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/worker.php migrations $@ \ No newline at end of file +exec php /usr/src/code/app/worker.php migrations $@ diff --git a/bin/worker-stats-resources b/bin/worker-stats-resources index 9c5d2bebff..70bfacbe52 100644 --- a/bin/worker-stats-resources +++ b/bin/worker-stats-resources @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/worker.php stats-resources $@ \ No newline at end of file +exec php /usr/src/code/app/worker.php stats-resources $@ diff --git a/bin/worker-stats-usage b/bin/worker-stats-usage index 2c267d805e..e6dd849a48 100644 --- a/bin/worker-stats-usage +++ b/bin/worker-stats-usage @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/worker.php stats-usage $@ \ No newline at end of file +exec php /usr/src/code/app/worker.php stats-usage $@ diff --git a/bin/worker-webhooks b/bin/worker-webhooks index 93f8027a81..63fc13e3c5 100644 --- a/bin/worker-webhooks +++ b/bin/worker-webhooks @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/worker.php webhooks $@ \ No newline at end of file +exec php /usr/src/code/app/worker.php webhooks $@ From d98c06abf2fbae4bfb7bd661aacf51cb671e9e74 Mon Sep 17 00:00:00 2001 From: Fabian Gruber Date: Sun, 25 May 2025 17:48:09 +0200 Subject: [PATCH 163/219] feat(worker): install stop hooks and close consumer --- app/worker.php | 13 +++++++++++-- bin/screenshot | 2 +- composer.lock | 12 ++++++------ 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/app/worker.php b/app/worker.php index 597e8a9943..b5b65890ea 100644 --- a/app/worker.php +++ b/app/worker.php @@ -18,7 +18,9 @@ use Appwrite\Event\StatsUsage; use Appwrite\Event\Webhook; use Appwrite\Platform\Appwrite; use Executor\Executor; +use Swoole\Process; use Swoole\Runtime; +use Swoole\Timer; use Utopia\Abuse\Adapters\TimeLimit\Redis as TimeLimitRedis; use Utopia\Cache\Adapter\Pool as CachePool; use Utopia\Cache\Adapter\Sharding; @@ -480,8 +482,15 @@ $worker }); $worker->workerStart() - ->action(function () use ($workerName) { - Console::info("Worker $workerName started"); + ->action(function () use ($worker, $workerName) { + Console::info("Worker $workerName started"); + + Process::signal(SIGTERM, function () use ($worker, $workerName) { + Console::info("Stopping worker $workerName."); + + $worker->stop(); + Timer::clearAll(); + }); }); $worker->start(); diff --git a/bin/screenshot b/bin/screenshot index 4d8ceb998f..aef15eb96f 100755 --- a/bin/screenshot +++ b/bin/screenshot @@ -1,3 +1,3 @@ #!/bin/sh -php /usr/src/code/app/cli.php screenshot $@ \ No newline at end of file +exec php /usr/src/code/app/cli.php screenshot $@ \ No newline at end of file diff --git a/composer.lock b/composer.lock index b7b1f23545..8603361673 100644 --- a/composer.lock +++ b/composer.lock @@ -4264,16 +4264,16 @@ }, { "name": "utopia-php/queue", - "version": "0.11.0", + "version": "0.11.1", "source": { "type": "git", "url": "https://github.com/utopia-php/queue.git", - "reference": "06b5ced0eaed2ecc6aab6d8e1b4d96bff37a1ce5" + "reference": "498bbbef418b1db71b51e1bb62f5d1d752ddd8d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/queue/zipball/06b5ced0eaed2ecc6aab6d8e1b4d96bff37a1ce5", - "reference": "06b5ced0eaed2ecc6aab6d8e1b4d96bff37a1ce5", + "url": "https://api.github.com/repos/utopia-php/queue/zipball/498bbbef418b1db71b51e1bb62f5d1d752ddd8d6", + "reference": "498bbbef418b1db71b51e1bb62f5d1d752ddd8d6", "shasum": "" }, "require": { @@ -4324,9 +4324,9 @@ ], "support": { "issues": "https://github.com/utopia-php/queue/issues", - "source": "https://github.com/utopia-php/queue/tree/0.11.0" + "source": "https://github.com/utopia-php/queue/tree/0.11.1" }, - "time": "2025-05-30T09:52:38+00:00" + "time": "2025-05-30T11:50:34+00:00" }, { "name": "utopia-php/registry", From e1ee9ba89e756e2ae4985a8d18ea7095e5f0fb77 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 30 May 2025 18:04:57 +0530 Subject: [PATCH 164/219] fix: logic. --- app/controllers/api/teams.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index ede61115e2..7e52b16911 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -1359,10 +1359,12 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') max: 2 ); - // Is the deletion being requested by the user on their own membership? - $isCurrentUserAnOwner = $user->getInternalId() === $membership->getAttribute('userInternalId'); + // Is the deletion being requested by the user on their own membership and they are also the owner? + $isSelfOwner = + in_array('owner', $membership->getAttribute('roles')) && + $membership->getAttribute('userInternalId') === $user->getInternalId(); - if ($ownersCount === 1 && $isCurrentUserAnOwner) { + if ($ownersCount === 1 && $isSelfOwner) { /* Prevent removal if the user is the only owner. */ throw new Exception(Exception::MEMBERSHIP_DELETION_PROHIBITED, 'There must be at least one owner in the organization.'); } From 67cb3aad2f505946cb649c27f8ee79503fd40e32 Mon Sep 17 00:00:00 2001 From: Darshan Date: Fri, 30 May 2025 18:05:03 +0530 Subject: [PATCH 165/219] fix: test. --- tests/e2e/Services/Teams/TeamsConsoleClientTest.php | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/tests/e2e/Services/Teams/TeamsConsoleClientTest.php b/tests/e2e/Services/Teams/TeamsConsoleClientTest.php index dda7f8e4ae..7949761d7f 100644 --- a/tests/e2e/Services/Teams/TeamsConsoleClientTest.php +++ b/tests/e2e/Services/Teams/TeamsConsoleClientTest.php @@ -212,9 +212,6 @@ class TeamsConsoleClientTest extends Scope $this->assertEquals(401, $response['headers']['status-code']); $this->assertEquals('The current user is not authorized to perform the requested action.', $response['body']['message']); - /** - * Test for when a user other than the owner tries to delete their membership - */ $response = $this->client->call(Client::METHOD_DELETE, '/teams/' . $teamUid . '/memberships/' . $membershipUid, [ 'origin' => 'http://localhost', 'content-type' => 'application/json', @@ -222,7 +219,7 @@ class TeamsConsoleClientTest extends Scope 'cookie' => 'a_session_' . $this->getProject()['$id'] . '=' . $session, ]); - $this->assertEquals(400, $response['headers']['status-code']); + $this->assertEquals(204, $response['headers']['status-code']); $response = $this->client->call(Client::METHOD_GET, '/teams/' . $teamUid . '/memberships', array_merge([ 'content-type' => 'application/json', @@ -230,7 +227,7 @@ class TeamsConsoleClientTest extends Scope ], $this->getHeaders())); $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(3, $response['body']['total']); + $this->assertEquals(2, $response['body']['total']); /** * Test for when the owner tries to delete their membership From 8716ef98ca5581f7403f7d122b4d60d366995097 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Sat, 31 May 2025 02:44:54 +1200 Subject: [PATCH 166/219] Update database for upsert fix --- composer.lock | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/composer.lock b/composer.lock index b7b1f23545..729174e86a 100644 --- a/composer.lock +++ b/composer.lock @@ -3503,16 +3503,16 @@ }, { "name": "utopia-php/database", - "version": "0.69.6", + "version": "0.69.7", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "42bfc0d87de4ade26cfd9915aaad84912761466b" + "reference": "3db51ec544b3f287511209e34bab3f5ec85fa56e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/42bfc0d87de4ade26cfd9915aaad84912761466b", - "reference": "42bfc0d87de4ade26cfd9915aaad84912761466b", + "url": "https://api.github.com/repos/utopia-php/database/zipball/3db51ec544b3f287511209e34bab3f5ec85fa56e", + "reference": "3db51ec544b3f287511209e34bab3f5ec85fa56e", "shasum": "" }, "require": { @@ -3553,9 +3553,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.69.6" + "source": "https://github.com/utopia-php/database/tree/0.69.7" }, - "time": "2025-05-29T10:36:03+00:00" + "time": "2025-05-30T14:41:25+00:00" }, { "name": "utopia-php/detector", @@ -4264,16 +4264,16 @@ }, { "name": "utopia-php/queue", - "version": "0.11.0", + "version": "0.11.1", "source": { "type": "git", "url": "https://github.com/utopia-php/queue.git", - "reference": "06b5ced0eaed2ecc6aab6d8e1b4d96bff37a1ce5" + "reference": "498bbbef418b1db71b51e1bb62f5d1d752ddd8d6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/queue/zipball/06b5ced0eaed2ecc6aab6d8e1b4d96bff37a1ce5", - "reference": "06b5ced0eaed2ecc6aab6d8e1b4d96bff37a1ce5", + "url": "https://api.github.com/repos/utopia-php/queue/zipball/498bbbef418b1db71b51e1bb62f5d1d752ddd8d6", + "reference": "498bbbef418b1db71b51e1bb62f5d1d752ddd8d6", "shasum": "" }, "require": { @@ -4324,9 +4324,9 @@ ], "support": { "issues": "https://github.com/utopia-php/queue/issues", - "source": "https://github.com/utopia-php/queue/tree/0.11.0" + "source": "https://github.com/utopia-php/queue/tree/0.11.1" }, - "time": "2025-05-30T09:52:38+00:00" + "time": "2025-05-30T11:50:34+00:00" }, { "name": "utopia-php/registry", From df67dd55766175157ccfee2864fd2d3121acbb5f Mon Sep 17 00:00:00 2001 From: Damodar Lohani Date: Sun, 1 Jun 2025 02:09:30 +0000 Subject: [PATCH 167/219] Fix: remove stats usage dump worker --- .../Platform/Workers/StatsUsageDump.php | 206 ------------------ 1 file changed, 206 deletions(-) delete mode 100644 src/Appwrite/Platform/Workers/StatsUsageDump.php diff --git a/src/Appwrite/Platform/Workers/StatsUsageDump.php b/src/Appwrite/Platform/Workers/StatsUsageDump.php deleted file mode 100644 index 77ec3f13e6..0000000000 --- a/src/Appwrite/Platform/Workers/StatsUsageDump.php +++ /dev/null @@ -1,206 +0,0 @@ - true, - METRIC_BUCKETS => true, - METRIC_USERS => true, - METRIC_FUNCTIONS => true, - METRIC_TEAMS => true, - METRIC_MESSAGES => true, - METRIC_MAU => true, - METRIC_WEBHOOKS => true, - METRIC_PLATFORMS => true, - METRIC_PROVIDERS => true, - METRIC_TOPICS => true, - METRIC_KEYS => true, - METRIC_FILES => true, - METRIC_FILES_STORAGE => true, - METRIC_DEPLOYMENTS_STORAGE => true, - METRIC_BUILDS_STORAGE => true, - METRIC_DEPLOYMENTS => true, - METRIC_BUILDS => true, - METRIC_COLLECTIONS => true, - METRIC_DOCUMENTS => true, - METRIC_DATABASES_STORAGE => true, - ]; - - /** - * Skip metrics associated with parent IDs - * these need to be checked individually with `str_ends_with` - */ - protected array $skipParentIdMetrics = [ - '.files', - '.files.storage', - '.collections', - '.documents', - '.deployments', - '.deployments.storage', - '.builds', - '.builds.storage', - '.databases.storage' - ]; - - /** - * @var callable(Document): Database - */ - protected $getLogsDB; - - protected array $periods = [ - '1h' => 'Y-m-d H:00', - '1d' => 'Y-m-d 00:00', - 'inf' => '0000-00-00 00:00' - ]; - - public static function getName(): string - { - return 'stats-usage-dump'; - } - - /** - * @throws \Exception - */ - public function __construct() - { - $this - ->inject('message') - ->inject('getProjectDB') - ->inject('getLogsDB') - ->inject('register') - ->callback([$this, 'action']); - } - - /** - * @param Message $message - * @param callable $getProjectDB - * @param callable $getLogsDB - * @param Registry $register - * @return void - * @throws Exception - * @throws \Throwable - * @throws \Utopia\Database\Exception - */ - public function action(Message $message, callable $getProjectDB, callable $getLogsDB, Registry $register): void - { - $this->getLogsDB = $getLogsDB; - $this->register = $register; - $payload = $message->getPayload() ?? []; - if (empty($payload)) { - throw new Exception('Missing payload'); - } - - foreach ($payload['stats'] ?? [] as $stats) { - $project = new Document($stats['project'] ?? []); - - $numberOfKeys = !empty($stats['keys']) ? count($stats['keys']) : 0; - $receivedAt = $stats['receivedAt'] ?? null; - if ($numberOfKeys === 0) { - continue; - } - - Console::log('['.DateTime::now().'] Id: '.$project->getId(). ' InternalId: '.$project->getInternalId(). ' Db: '.$project->getAttribute('database').' ReceivedAt: '.$receivedAt. ' Keys: '.$numberOfKeys); - - try { - /** @var Database $dbForProject */ - $dbForProject = $getProjectDB($project); - foreach ($stats['keys'] ?? [] as $key => $value) { - if ($value == 0) { - continue; - } - - if (str_contains($key, METRIC_DATABASES_STORAGE)) { - continue; - } - - foreach ($this->periods as $period => $format) { - $time = null; - - if ($period !== 'inf') { - $time = !empty($receivedAt) ? (new \DateTime($receivedAt))->format($format) : date($format, time()); - } - $id = \md5("{$time}_{$period}_{$key}"); - - $document = new Document([ - '$id' => $id, - 'period' => $period, - 'time' => $time, - 'metric' => $key, - 'value' => $value, - 'region' => System::getEnv('_APP_REGION', 'default'), - ]); - - $documentClone = clone $document; - - $dbForProject->createOrUpdateDocumentsWithIncrease( - 'stats', - 'value', - [$document] - ); - - $this->writeToLogsDB($project, $documentClone); - } - } - } catch (\Exception $e) { - Console::error('[' . DateTime::now() . '] project [' . $project->getInternalId() . '] database [' . $project['database'] . '] ' . ' ' . $e->getMessage()); - } - } - } - - protected function writeToLogsDB(Document $project, Document $document): void - { - if (System::getEnv('_APP_STATS_USAGE_DUAL_WRITING', 'disabled') === 'disabled') { - Console::log('Dual Writing is disabled. Skipping...'); - return; - } - - if (array_key_exists($document->getAttribute('metric'), $this->skipBaseMetrics)) { - return; - } - foreach ($this->skipParentIdMetrics as $skipMetric) { - if (str_ends_with($document->getAttribute('metric'), $skipMetric)) { - return; - } - } - - $dbForLogs = ($this->getLogsDB)($project); - - try { - $dbForLogs->createOrUpdateDocumentsWithIncrease( - 'stats', - 'value', - [$document] - ); - Console::success('Usage logs pushed to Logs DB'); - } catch (\Throwable $th) { - Console::error($th->getMessage()); - } - } -} From 0ac6decc99829b09cc93a9d50cbe3587477face4 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Mon, 2 Jun 2025 14:04:03 +0530 Subject: [PATCH 168/219] Fix github comments and deployment creation on branch deletion --- app/controllers/api/vcs.php | 5 +- composer.lock | 108 +++++++++++++++++------------------ docker-compose.yml | 2 +- src/Appwrite/Vcs/Comment.php | 16 ++++-- 4 files changed, 66 insertions(+), 65 deletions(-) diff --git a/app/controllers/api/vcs.php b/app/controllers/api/vcs.php index 588ca417cf..c8a0a36a85 100644 --- a/app/controllers/api/vcs.php +++ b/app/controllers/api/vcs.php @@ -1215,6 +1215,7 @@ App::post('/v1/vcs/github/events') if ($event == $github::EVENT_PUSH) { $providerBranchCreated = $parsedPayload["branchCreated"] ?? false; + $providerBranchDeleted = $parsedPayload["branchDeleted"] ?? false; $providerBranch = $parsedPayload["branch"] ?? ''; $providerBranchUrl = $parsedPayload["branchUrl"] ?? ''; $providerRepositoryId = $parsedPayload["repositoryId"] ?? ''; @@ -1236,8 +1237,8 @@ App::post('/v1/vcs/github/events') Query::limit(100), ])); - // create new deployment only on push and not when branch is created - if (!$providerBranchCreated) { + // create new deployment only on push and not when branch is created or deleted + if (!$providerBranchCreated && !$providerBranchDeleted) { $createGitDeployments($github, $providerInstallationId, $repositories, $providerBranch, $providerBranchUrl, $providerRepositoryName, $providerRepositoryUrl, $providerRepositoryOwner, $providerCommitHash, $providerCommitAuthor, $providerCommitAuthorUrl, $providerCommitMessage, $providerCommitUrl, '', false, $dbForPlatform, $queueForBuilds, $getProjectDB, $request); } } elseif ($event == $github::EVENT_INSTALLATION) { diff --git a/composer.lock b/composer.lock index 729174e86a..8c8bcc0a6e 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3230eea9e592f0b712e78c1ef5f5e244", + "content-hash": "d1e8bc951ce7d70a3254381a9f639971", "packages": [ { "name": "adhocore/jwt", @@ -283,16 +283,16 @@ }, { "name": "brick/math", - "version": "0.12.3", + "version": "0.13.1", "source": { "type": "git", "url": "https://github.com/brick/math.git", - "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba" + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/brick/math/zipball/866551da34e9a618e64a819ee1e01c20d8a588ba", - "reference": "866551da34e9a618e64a819ee1e01c20d8a588ba", + "url": "https://api.github.com/repos/brick/math/zipball/fc7ed316430118cc7836bf45faff18d5dfc8de04", + "reference": "fc7ed316430118cc7836bf45faff18d5dfc8de04", "shasum": "" }, "require": { @@ -331,7 +331,7 @@ ], "support": { "issues": "https://github.com/brick/math/issues", - "source": "https://github.com/brick/math/tree/0.12.3" + "source": "https://github.com/brick/math/tree/0.13.1" }, "funding": [ { @@ -339,7 +339,7 @@ "type": "github" } ], - "time": "2025-02-28T13:11:00+00:00" + "time": "2025-03-29T13:50:30+00:00" }, { "name": "chillerlan/php-qrcode", @@ -2323,20 +2323,20 @@ }, { "name": "ramsey/uuid", - "version": "4.7.6", + "version": "4.8.1", "source": { "type": "git", "url": "https://github.com/ramsey/uuid.git", - "reference": "91039bc1faa45ba123c4328958e620d382ec7088" + "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ramsey/uuid/zipball/91039bc1faa45ba123c4328958e620d382ec7088", - "reference": "91039bc1faa45ba123c4328958e620d382ec7088", + "url": "https://api.github.com/repos/ramsey/uuid/zipball/fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", + "reference": "fdf4dd4e2ff1813111bd0ad58d7a1ddbb5b56c28", "shasum": "" }, "require": { - "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12", + "brick/math": "^0.8.8 || ^0.9 || ^0.10 || ^0.11 || ^0.12 || ^0.13", "ext-json": "*", "php": "^8.0", "ramsey/collection": "^1.2 || ^2.0" @@ -2345,26 +2345,23 @@ "rhumsaa/uuid": "self.version" }, "require-dev": { - "captainhook/captainhook": "^5.10", + "captainhook/captainhook": "^5.25", "captainhook/plugin-composer": "^5.3", - "dealerdirect/phpcodesniffer-composer-installer": "^0.7.0", - "doctrine/annotations": "^1.8", - "ergebnis/composer-normalize": "^2.15", - "mockery/mockery": "^1.3", + "dealerdirect/phpcodesniffer-composer-installer": "^1.0", + "ergebnis/composer-normalize": "^2.47", + "mockery/mockery": "^1.6", "paragonie/random-lib": "^2", - "php-mock/php-mock": "^2.2", - "php-mock/php-mock-mockery": "^1.3", - "php-parallel-lint/php-parallel-lint": "^1.1", - "phpbench/phpbench": "^1.0", - "phpstan/extension-installer": "^1.1", - "phpstan/phpstan": "^1.8", - "phpstan/phpstan-mockery": "^1.1", - "phpstan/phpstan-phpunit": "^1.1", - "phpunit/phpunit": "^8.5 || ^9", - "ramsey/composer-repl": "^1.4", - "slevomat/coding-standard": "^8.4", - "squizlabs/php_codesniffer": "^3.5", - "vimeo/psalm": "^4.9" + "php-mock/php-mock": "^2.6", + "php-mock/php-mock-mockery": "^1.5", + "php-parallel-lint/php-parallel-lint": "^1.4.0", + "phpbench/phpbench": "^1.2.14", + "phpstan/extension-installer": "^1.4", + "phpstan/phpstan": "^2.1", + "phpstan/phpstan-mockery": "^2.0", + "phpstan/phpstan-phpunit": "^2.0", + "phpunit/phpunit": "^9.6", + "slevomat/coding-standard": "^8.18", + "squizlabs/php_codesniffer": "^3.13" }, "suggest": { "ext-bcmath": "Enables faster math with arbitrary-precision integers using BCMath.", @@ -2399,19 +2396,9 @@ ], "support": { "issues": "https://github.com/ramsey/uuid/issues", - "source": "https://github.com/ramsey/uuid/tree/4.7.6" + "source": "https://github.com/ramsey/uuid/tree/4.8.1" }, - "funding": [ - { - "url": "https://github.com/ramsey", - "type": "github" - }, - { - "url": "https://tidelift.com/funding/github/packagist/ramsey/uuid", - "type": "tidelift" - } - ], - "time": "2024-04-27T21:32:50+00:00" + "time": "2025-06-01T06:28:46+00:00" }, { "name": "spomky-labs/otphp", @@ -4597,16 +4584,16 @@ }, { "name": "utopia-php/vcs", - "version": "0.10.2", + "version": "dev-feat-check-deleted-attribute-on-push", "source": { "type": "git", "url": "https://github.com/utopia-php/vcs.git", - "reference": "1f9823ebcb8fd098607de0074f18f48e28985012" + "reference": "ba43fd0e797a61c92197885413b650aed6a45577" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/vcs/zipball/1f9823ebcb8fd098607de0074f18f48e28985012", - "reference": "1f9823ebcb8fd098607de0074f18f48e28985012", + "url": "https://api.github.com/repos/utopia-php/vcs/zipball/ba43fd0e797a61c92197885413b650aed6a45577", + "reference": "ba43fd0e797a61c92197885413b650aed6a45577", "shasum": "" }, "require": { @@ -4640,9 +4627,9 @@ ], "support": { "issues": "https://github.com/utopia-php/vcs/issues", - "source": "https://github.com/utopia-php/vcs/tree/0.10.2" + "source": "https://github.com/utopia-php/vcs/tree/feat-check-deleted-attribute-on-push" }, - "time": "2025-04-17T04:35:25+00:00" + "time": "2025-06-02T08:03:56+00:00" }, { "name": "utopia-php/websocket", @@ -5344,16 +5331,16 @@ }, { "name": "nikic/php-parser", - "version": "v5.4.0", + "version": "v5.5.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "447a020a1f875a434d62f2a401f53b82a396e494" + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/447a020a1f875a434d62f2a401f53b82a396e494", - "reference": "447a020a1f875a434d62f2a401f53b82a396e494", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/ae59794362fe85e051a58ad36b289443f57be7a9", + "reference": "ae59794362fe85e051a58ad36b289443f57be7a9", "shasum": "" }, "require": { @@ -5396,9 +5383,9 @@ ], "support": { "issues": "https://github.com/nikic/PHP-Parser/issues", - "source": "https://github.com/nikic/PHP-Parser/tree/v5.4.0" + "source": "https://github.com/nikic/PHP-Parser/tree/v5.5.0" }, - "time": "2024-12-30T11:07:19+00:00" + "time": "2025-05-31T08:24:38+00:00" }, { "name": "phar-io/manifest", @@ -8245,9 +8232,18 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [], + "aliases": [ + { + "package": "utopia-php/vcs", + "version": "dev-feat-check-deleted-attribute-on-push", + "alias": "0.10.99", + "alias_normalized": "0.10.99.0" + } + ], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": { + "utopia-php/vcs": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/docker-compose.yml b/docker-compose.yml index cefd082c2f..29a43aca91 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -213,7 +213,7 @@ services: appwrite-console: <<: *x-logging container_name: appwrite-console - image: appwrite/console:6.0.13 + image: appwrite/console:6.0.32 restart: unless-stopped networks: - appwrite diff --git a/src/Appwrite/Vcs/Comment.php b/src/Appwrite/Vcs/Comment.php index 7c550ad528..3fc4e287f8 100644 --- a/src/Appwrite/Vcs/Comment.php +++ b/src/Appwrite/Vcs/Comment.php @@ -105,8 +105,10 @@ class Comment foreach ($project['site'] as $siteId => $site) { $extension = $site['status'] === 'building' ? 'gif' : 'png'; - $pathLight = '/images/vcs/status-' . $site['status'] . '-light.' . $extension; - $pathDark = '/images/vcs/status-' . $site['status'] . '-dark.' . $extension; + $imageStatus = in_array($site['status'], ['processing', 'building']) ? 'building' : $site['status']; + + $pathLight = '/images/vcs/status-' . $imageStatus . '-light.' . $extension; + $pathDark = '/images/vcs/status-' . $imageStatus . '-dark.' . $extension; $status = match ($site['status']) { 'waiting' => $this->generatImage($pathLight, $pathDark, 'Queued', 85) . ' _Queued_', @@ -149,10 +151,11 @@ class Comment $text .= "| :- | :- | :- | :- |\n"; foreach ($project['function'] as $functionId => $function) { - $extension = $function['status'] === 'building' ? 'gif' : 'png'; + $imageStatus = in_array($function['status'], ['processing', 'building']) ? 'building' : $function['status']; + $extension = $imageStatus === 'building' ? 'gif' : 'png'; - $pathLight = '/images/vcs/status-' . $function['status'] . '-light.' . $extension; - $pathDark = '/images/vcs/status-' . $function['status'] . '-dark.' . $extension; + $pathLight = '/images/vcs/status-' . $imageStatus . '-light.' . $extension; + $pathDark = '/images/vcs/status-' . $imageStatus . '-dark.' . $extension; $status = match ($function['status']) { 'waiting' => $this->generatImage($pathLight, $pathDark, 'Queued', 85) . ' _Queued_', @@ -168,7 +171,8 @@ class Comment $action = '[Authorize](' . $function['action']['url'] . ')'; } - $text .= "|  **{$function['name']}**
`$functionId`"; + $text .= "|  **{$function['name']}**"; + $text .= "| `{$functionId}`"; $text .= "| {$status}"; $text .= "| {$action}"; $text .= "|\n"; From e7963e68257cca174d7eb0f04def3823e2dad534 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Mon, 2 Jun 2025 14:07:53 +0530 Subject: [PATCH 169/219] Update composer.lock --- composer.lock | 27 +++++++++------------------ 1 file changed, 9 insertions(+), 18 deletions(-) diff --git a/composer.lock b/composer.lock index 8c8bcc0a6e..fb9db2aa20 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "d1e8bc951ce7d70a3254381a9f639971", + "content-hash": "3230eea9e592f0b712e78c1ef5f5e244", "packages": [ { "name": "adhocore/jwt", @@ -4584,16 +4584,16 @@ }, { "name": "utopia-php/vcs", - "version": "dev-feat-check-deleted-attribute-on-push", + "version": "0.10.3", "source": { "type": "git", "url": "https://github.com/utopia-php/vcs.git", - "reference": "ba43fd0e797a61c92197885413b650aed6a45577" + "reference": "a51ca929aa8a82cc790c2df8b653d6c60cb889d3" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/vcs/zipball/ba43fd0e797a61c92197885413b650aed6a45577", - "reference": "ba43fd0e797a61c92197885413b650aed6a45577", + "url": "https://api.github.com/repos/utopia-php/vcs/zipball/a51ca929aa8a82cc790c2df8b653d6c60cb889d3", + "reference": "a51ca929aa8a82cc790c2df8b653d6c60cb889d3", "shasum": "" }, "require": { @@ -4627,9 +4627,9 @@ ], "support": { "issues": "https://github.com/utopia-php/vcs/issues", - "source": "https://github.com/utopia-php/vcs/tree/feat-check-deleted-attribute-on-push" + "source": "https://github.com/utopia-php/vcs/tree/0.10.3" }, - "time": "2025-06-02T08:03:56+00:00" + "time": "2025-06-02T08:23:44+00:00" }, { "name": "utopia-php/websocket", @@ -8232,18 +8232,9 @@ "time": "2024-03-07T20:33:40+00:00" } ], - "aliases": [ - { - "package": "utopia-php/vcs", - "version": "dev-feat-check-deleted-attribute-on-push", - "alias": "0.10.99", - "alias_normalized": "0.10.99.0" - } - ], + "aliases": [], "minimum-stability": "stable", - "stability-flags": { - "utopia-php/vcs": 20 - }, + "stability-flags": {}, "prefer-stable": false, "prefer-lowest": false, "platform": { From 288f3b2cc83083241f359f1aab0a0af32fc0d789 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Mon, 2 Jun 2025 14:12:25 +0530 Subject: [PATCH 170/219] Fix order --- src/Appwrite/Vcs/Comment.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Vcs/Comment.php b/src/Appwrite/Vcs/Comment.php index 3fc4e287f8..d1d50c2ffd 100644 --- a/src/Appwrite/Vcs/Comment.php +++ b/src/Appwrite/Vcs/Comment.php @@ -103,10 +103,10 @@ class Comment $text .= "| :- | :- | :- | :- | :- |\n"; foreach ($project['site'] as $siteId => $site) { - $extension = $site['status'] === 'building' ? 'gif' : 'png'; - $imageStatus = in_array($site['status'], ['processing', 'building']) ? 'building' : $site['status']; + $extension = $site['status'] === 'building' ? 'gif' : 'png'; + $pathLight = '/images/vcs/status-' . $imageStatus . '-light.' . $extension; $pathDark = '/images/vcs/status-' . $imageStatus . '-dark.' . $extension; From 7049a58f212b1a7a8b277905855244bee82cf634 Mon Sep 17 00:00:00 2001 From: Khushboo Verma Date: Mon, 2 Jun 2025 15:06:00 +0530 Subject: [PATCH 171/219] Update composer.lock --- composer.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/composer.lock b/composer.lock index fb9db2aa20..9e757f9db8 100644 --- a/composer.lock +++ b/composer.lock @@ -4584,16 +4584,16 @@ }, { "name": "utopia-php/vcs", - "version": "0.10.3", + "version": "0.10.4", "source": { "type": "git", "url": "https://github.com/utopia-php/vcs.git", - "reference": "a51ca929aa8a82cc790c2df8b653d6c60cb889d3" + "reference": "f635b368909eb3c3fe57344fe43525e74e8fdc03" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/vcs/zipball/a51ca929aa8a82cc790c2df8b653d6c60cb889d3", - "reference": "a51ca929aa8a82cc790c2df8b653d6c60cb889d3", + "url": "https://api.github.com/repos/utopia-php/vcs/zipball/f635b368909eb3c3fe57344fe43525e74e8fdc03", + "reference": "f635b368909eb3c3fe57344fe43525e74e8fdc03", "shasum": "" }, "require": { @@ -4627,9 +4627,9 @@ ], "support": { "issues": "https://github.com/utopia-php/vcs/issues", - "source": "https://github.com/utopia-php/vcs/tree/0.10.3" + "source": "https://github.com/utopia-php/vcs/tree/0.10.4" }, - "time": "2025-06-02T08:23:44+00:00" + "time": "2025-06-02T09:18:36+00:00" }, { "name": "utopia-php/websocket", From c92a14d31805b693de8046dc06bfb6f368c8b80f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Mon, 2 Jun 2025 12:47:13 +0200 Subject: [PATCH 172/219] Simplify router redirect --- app/controllers/general.php | 6 ------ 1 file changed, 6 deletions(-) diff --git a/app/controllers/general.php b/app/controllers/general.php index bff701792e..5beac9e1e8 100644 --- a/app/controllers/general.php +++ b/app/controllers/general.php @@ -749,12 +749,6 @@ function router(App $utopia, Database $dbForPlatform, callable $getProjectDB, Sw return false; } elseif ($type === 'redirect') { $url = $rule->getAttribute('redirectUrl', ''); - - $query = ($swooleRequest->server['query_string'] ?? ''); - if (!empty($query)) { - $url .= '?' . $query; - } - $response->redirect($url, \intval($rule->getAttribute('redirectStatusCode', 301))); return true; } else { From c449144926aa6280f358be9a56ac16e628f626d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Mon, 2 Jun 2025 17:56:13 +0200 Subject: [PATCH 173/219] Fix flaky usage tests --- tests/e2e/General/UsageTest.php | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/tests/e2e/General/UsageTest.php b/tests/e2e/General/UsageTest.php index 5549ef800d..f0bb32156d 100644 --- a/tests/e2e/General/UsageTest.php +++ b/tests/e2e/General/UsageTest.php @@ -183,9 +183,11 @@ class UsageTest extends Scope /** * @depends testPrepareUsersStats */ - #[Retry(count: 1)] + #[Retry(count: 10)] public function testUsersStats(array $data): array { + \sleep(1); // To prevent all 10 retries from running instantly + $requestsTotal = $data['requestsTotal']; $response = $this->client->call( @@ -362,6 +364,8 @@ class UsageTest extends Scope #[Retry(count: 10)] public function testStorageStats(array $data): array { + \sleep(1); // To prevent all 10 retries from running instantly + $bucketId = $data['bucketId']; $bucketsTotal = $data['bucketsTotal']; $requestsTotal = $data['requestsTotal']; @@ -577,9 +581,11 @@ class UsageTest extends Scope } /** @depends testPrepareDatabaseStats */ - #[Retry(count: 1)] + #[Retry(count: 10)] public function testDatabaseStats(array $data): array { + \sleep(1); // To prevent all 10 retries from running instantly + $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; $requestsTotal = $data['requestsTotal']; @@ -799,9 +805,11 @@ class UsageTest extends Scope } /** @depends testPrepareFunctionsStats */ - #[Retry(count: 1)] + #[Retry(count: 10)] public function testFunctionsStats(array $data): array { + \sleep(1); // To prevent all 10 retries from running instantly + $functionId = $data['functionId']; $executionTime = $data['executionTime']; $executions = $data['executions']; @@ -927,9 +935,11 @@ class UsageTest extends Scope } /** @depends testPrepareSitesStats */ - #[Retry(count: 1)] + #[Retry(count: 10)] public function testSitesStats(array $data) { + \sleep(1); // To prevent all 10 retries from running instantly + $siteId = $data['siteId']; $executionTime = $data['executionTime'] ?? 0; $executions = $data['executions'] ?? 0; From 854304dd1643a1763b44a31b65aaab099078bc0c Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 2 Jun 2025 17:09:03 +0100 Subject: [PATCH 174/219] tests: fix flaky account tests commit-id:3865765d --- tests/e2e/Scopes/Scope.php | 14 +++++++++ .../Account/AccountCustomClientTest.php | 30 ++++++++----------- 2 files changed, 27 insertions(+), 17 deletions(-) diff --git a/tests/e2e/Scopes/Scope.php b/tests/e2e/Scopes/Scope.php index 6deaa62c05..2fa6416bf7 100644 --- a/tests/e2e/Scopes/Scope.php +++ b/tests/e2e/Scopes/Scope.php @@ -2,6 +2,7 @@ namespace Tests\E2E\Scopes; +use Appwrite\Tests\Async; use Appwrite\Tests\Retryable; use PHPUnit\Framework\TestCase; use Tests\E2E\Client; @@ -10,6 +11,7 @@ use Utopia\Database\Helpers\ID; abstract class Scope extends TestCase { use Retryable; + use Async; protected ?Client $client = null; protected string $endpoint = 'http://localhost/v1'; @@ -43,6 +45,18 @@ abstract class Scope extends TestCase return []; } + protected function assertLastRequest(callable $probe, $timeoutMs = 20_000, $waitMs = 500): array + { + $this->assertEventually(function () use (&$request, $probe) { + $request = json_decode(file_get_contents('http://request-catcher:5000/__last_request__'), true); + $request['data'] = json_decode($request['data'], true); + + call_user_func($probe, $request); + }, $timeoutMs, $waitMs); + + return $request; + } + protected function getLastRequest(): array { sleep(2); diff --git a/tests/e2e/Services/Account/AccountCustomClientTest.php b/tests/e2e/Services/Account/AccountCustomClientTest.php index 452b725c11..0cc2eb893a 100644 --- a/tests/e2e/Services/Account/AccountCustomClientTest.php +++ b/tests/e2e/Services/Account/AccountCustomClientTest.php @@ -2034,7 +2034,6 @@ class AccountCustomClientTest extends Scope $this->assertEquals($response['body']['users'][0]['email'], $email); } - #[Retry(count: 2)] public function testCreatePhone(): array { $number = '+123456789'; @@ -2058,17 +2057,15 @@ class AccountCustomClientTest extends Scope $userId = $response['body']['userId']; - \sleep(7); - - $smsRequest = $this->getLastRequest(); - - $this->assertEquals('http://request-catcher:5000/mock-sms', $smsRequest['url']); - $this->assertEquals('Appwrite Mock Message Sender', $smsRequest['headers']['User-Agent']); - $this->assertEquals('username', $smsRequest['headers']['X-Username']); - $this->assertEquals('password', $smsRequest['headers']['X-Key']); - $this->assertEquals('POST', $smsRequest['method']); - $this->assertEquals('+123456789', $smsRequest['data']['from']); - $this->assertEquals($number, $smsRequest['data']['to']); + $smsRequest = $this->assertLastRequest(function (array $request) use ($number) { + $this->assertEquals('http://request-catcher:5000/mock-sms', $request['url']); + $this->assertEquals('Appwrite Mock Message Sender', $request['headers']['User-Agent']); + $this->assertEquals('username', $request['headers']['X-Username']); + $this->assertEquals('password', $request['headers']['X-Key']); + $this->assertEquals('POST', $request['method']); + $this->assertEquals('+123456789', $request['data']['from']); + $this->assertEquals($number, $request['data']['to']); + }); $data['token'] = $smsRequest['data']['message']; $data['id'] = $userId; @@ -2396,7 +2393,6 @@ class AccountCustomClientTest extends Scope /** * @depends testUpdatePhone */ - #[Retry(count: 3)] public function testPhoneVerification(array $data): array { $session = $data['session'] ?? ''; @@ -2416,10 +2412,10 @@ class AccountCustomClientTest extends Scope $this->assertEmpty($response['body']['secret']); $this->assertTrue((new DatetimeValidator())->isValid($response['body']['expire'])); - $smsRequest = $this->getLastRequest(); - - $message = $smsRequest['data']['message']; - $token = substr($message, 0, 6); + $smsRequest = $this->assertLastRequest(function ($request) { + $this->assertArrayHasKey('data', $request); + $this->assertArrayHasKey('message', $request['data']); + }); /** * Test for FAILURE From b9579c8922eede87d5a398af5392a0321ba2be9c Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 2 Jun 2025 18:36:48 +0100 Subject: [PATCH 175/219] tests: fix flaky messaging test commit-id:336a4f07 --- .../Messaging/MessagingConsoleClientTest.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php b/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php index 245eb3e8de..49d13128e2 100644 --- a/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php +++ b/tests/e2e/Services/Messaging/MessagingConsoleClientTest.php @@ -206,15 +206,17 @@ class MessagingConsoleClientTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); - $logs = $this->client->call(Client::METHOD_GET, '/messaging/topics/' . $topic['body']['$id'] . '/logs', \array_merge([ - 'content-type' => 'application/json', - 'x-appwrite-project' => $this->getProject()['$id'], - ], $this->getHeaders())); + $this->assertEventually(function () use ($topic) { + $logs = $this->client->call(Client::METHOD_GET, '/messaging/topics/' . $topic['body']['$id'] . '/logs', \array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); - $this->assertEquals($logs['headers']['status-code'], 200); - $this->assertIsArray($logs['body']['logs']); - $this->assertCount(2, $logs['body']['logs']); - $this->assertIsNumeric($logs['body']['total']); + $this->assertEquals($logs['headers']['status-code'], 200); + $this->assertIsArray($logs['body']['logs']); + $this->assertCount(2, $logs['body']['logs']); + $this->assertIsNumeric($logs['body']['total']); + }); $logs = $this->client->call(Client::METHOD_GET, '/messaging/topics/' . $topic['body']['$id'] . '/logs', \array_merge([ 'content-type' => 'application/json', From c19d123d48f0f83353845e2600495287550951f0 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 2 Jun 2025 18:20:08 +0100 Subject: [PATCH 176/219] tests: make usagetests robust commit-id:35fcc17d --- tests/e2e/General/UsageTest.php | 506 ++++++++++++++++---------------- 1 file changed, 258 insertions(+), 248 deletions(-) diff --git a/tests/e2e/General/UsageTest.php b/tests/e2e/General/UsageTest.php index f0bb32156d..6ff9dafada 100644 --- a/tests/e2e/General/UsageTest.php +++ b/tests/e2e/General/UsageTest.php @@ -3,7 +3,6 @@ namespace Tests\E2E\General; use Appwrite\Platform\Modules\Compute\Specification; -use Appwrite\Tests\Retry; use CURLFile; use DateTime; use Tests\E2E\Client; @@ -183,42 +182,43 @@ class UsageTest extends Scope /** * @depends testPrepareUsersStats */ - #[Retry(count: 10)] public function testUsersStats(array $data): array { - \sleep(1); // To prevent all 10 retries from running instantly - $requestsTotal = $data['requestsTotal']; - $response = $this->client->call( - Client::METHOD_GET, - '/project/usage', - $this->getConsoleHeaders(), - [ - 'period' => '1h', - 'startDate' => self::getToday(), - 'endDate' => self::getTomorrow(), - ] - ); + $this->assertEventually(function () { + $response = $this->client->call( + Client::METHOD_GET, + '/project/usage', + $this->getConsoleHeaders(), + [ + 'period' => '1h', + 'startDate' => self::getToday(), + 'endDate' => self::getTomorrow(), + ] + ); - $this->assertEquals(200, $response['headers']['status-code']); - $this->assertGreaterThanOrEqual(31, count($response['body'])); - $this->validateDates($response['body']['network']); - $this->validateDates($response['body']['requests']); - $this->validateDates($response['body']['users']); - $this->assertArrayHasKey('executionsBreakdown', $response['body']); - $this->assertArrayHasKey('bucketsBreakdown', $response['body']); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertGreaterThanOrEqual(31, count($response['body'])); + $this->validateDates($response['body']['network']); + $this->validateDates($response['body']['requests']); + $this->validateDates($response['body']['users']); + $this->assertArrayHasKey('executionsBreakdown', $response['body']); + $this->assertArrayHasKey('bucketsBreakdown', $response['body']); + }); - $response = $this->client->call( - Client::METHOD_GET, - '/users/usage?range=90d', - $this->getConsoleHeaders() - ); + $this->assertEventually(function () { + $response = $this->client->call( + Client::METHOD_GET, + '/users/usage?range=90d', + $this->getConsoleHeaders() + ); - $this->assertEquals('90d', $response['body']['range']); - $this->assertEquals(90, count($response['body']['users'])); - $this->assertEquals(90, count($response['body']['sessions'])); - $this->assertEquals((self::CREATE / 2), $response['body']['users'][array_key_last($response['body']['users'])]['value']); + $this->assertEquals('90d', $response['body']['range']); + $this->assertEquals(90, count($response['body']['users'])); + $this->assertEquals(90, count($response['body']['sessions'])); + $this->assertEquals((self::CREATE / 2), $response['body']['users'][array_key_last($response['body']['users'])]['value']); + }); return array_merge($data, [ 'requestsTotal' => $requestsTotal @@ -361,55 +361,58 @@ class UsageTest extends Scope /** * @depends testPrepareStorageStats */ - #[Retry(count: 10)] public function testStorageStats(array $data): array { - \sleep(1); // To prevent all 10 retries from running instantly - $bucketId = $data['bucketId']; $bucketsTotal = $data['bucketsTotal']; $requestsTotal = $data['requestsTotal']; $storageTotal = $data['storageTotal']; $filesTotal = $data['filesTotal']; - $response = $this->client->call( - Client::METHOD_GET, - '/project/usage', - $this->getConsoleHeaders(), - [ - 'period' => '1d', - 'startDate' => self::getToday(), - 'endDate' => self::getTomorrow(), - ] - ); + $this->assertEventually(function () use ($requestsTotal, $storageTotal) { + $response = $this->client->call( + Client::METHOD_GET, + '/project/usage', + $this->getConsoleHeaders(), + [ + 'period' => '1d', + 'startDate' => self::getToday(), + 'endDate' => self::getTomorrow(), + ] + ); - $this->assertGreaterThanOrEqual(31, count($response['body'])); - $this->assertEquals(1, count($response['body']['requests'])); - $this->assertEquals($requestsTotal, $response['body']['requests'][array_key_last($response['body']['requests'])]['value']); - $this->validateDates($response['body']['requests']); - $this->assertEquals($storageTotal, $response['body']['filesStorageTotal']); + $this->assertGreaterThanOrEqual(31, count($response['body'])); + $this->assertEquals(1, count($response['body']['requests'])); + $this->assertEquals($requestsTotal, $response['body']['requests'][array_key_last($response['body']['requests'])]['value']); + $this->validateDates($response['body']['requests']); + $this->assertEquals($storageTotal, $response['body']['filesStorageTotal']); + }); - $response = $this->client->call( - Client::METHOD_GET, - '/storage/usage?range=30d', - $this->getConsoleHeaders() - ); + $this->assertEventually(function () use ($bucketsTotal, $filesTotal, $storageTotal) { + $response = $this->client->call( + Client::METHOD_GET, + '/storage/usage?range=30d', + $this->getConsoleHeaders() + ); - $this->assertEquals($storageTotal, $response['body']['storage'][array_key_last($response['body']['storage'])]['value']); - $this->validateDates($response['body']['storage']); - $this->assertEquals($bucketsTotal, $response['body']['buckets'][array_key_last($response['body']['buckets'])]['value']); - $this->validateDates($response['body']['buckets']); - $this->assertEquals($filesTotal, $response['body']['files'][array_key_last($response['body']['files'])]['value']); - $this->validateDates($response['body']['files']); + $this->assertEquals($storageTotal, $response['body']['storage'][array_key_last($response['body']['storage'])]['value']); + $this->validateDates($response['body']['storage']); + $this->assertEquals($bucketsTotal, $response['body']['buckets'][array_key_last($response['body']['buckets'])]['value']); + $this->validateDates($response['body']['buckets']); + $this->assertEquals($filesTotal, $response['body']['files'][array_key_last($response['body']['files'])]['value']); + $this->validateDates($response['body']['files']); + }); - $response = $this->client->call( - Client::METHOD_GET, - '/storage/' . $bucketId . '/usage?range=30d', - $this->getConsoleHeaders() - ); + $this->assertEventually(function () use ($bucketId, $storageTotal, $filesTotal) { + $response = $this->client->call( + Client::METHOD_GET, + '/storage/' . $bucketId . '/usage?range=30d', + $this->getConsoleHeaders() + ); - $this->assertEquals($storageTotal, $response['body']['storage'][array_key_last($response['body']['storage'])]['value']); - $this->assertEquals($filesTotal, $response['body']['files'][array_key_last($response['body']['files'])]['value']); + $this->assertEquals($storageTotal, $response['body']['storage'][array_key_last($response['body']['storage'])]['value']); + $this->assertEquals($filesTotal, $response['body']['files'][array_key_last($response['body']['files'])]['value']); + }); return $data; } @@ -581,11 +584,9 @@ class UsageTest extends Scope } /** @depends testPrepareDatabaseStats */ - #[Retry(count: 10)] + public function testDatabaseStats(array $data): array { - \sleep(1); // To prevent all 10 retries from running instantly - $databaseId = $data['databaseId']; $collectionId = $data['collectionId']; $requestsTotal = $data['requestsTotal']; @@ -593,60 +594,66 @@ class UsageTest extends Scope $collectionsTotal = $data['collectionsTotal']; $documentsTotal = $data['documentsTotal']; - sleep(self::WAIT); + $this->assertEventually(function () use ($requestsTotal, $databasesTotal, $documentsTotal) { + $response = $this->client->call( + Client::METHOD_GET, + '/project/usage', + $this->getConsoleHeaders(), + [ + 'period' => '1d', + 'startDate' => self::getToday(), + 'endDate' => self::getTomorrow(), + ] + ); - $response = $this->client->call( - Client::METHOD_GET, - '/project/usage', - $this->getConsoleHeaders(), - [ - 'period' => '1d', - 'startDate' => self::getToday(), - 'endDate' => self::getTomorrow(), - ] - ); + $this->assertGreaterThanOrEqual(31, count($response['body'])); + $this->assertEquals(1, count($response['body']['requests'])); + $this->assertEquals(1, count($response['body']['network'])); + $this->assertEquals($requestsTotal, $response['body']['requests'][array_key_last($response['body']['requests'])]['value']); + $this->validateDates($response['body']['requests']); + $this->assertEquals($databasesTotal, $response['body']['databasesTotal']); + $this->assertEquals($documentsTotal, $response['body']['documentsTotal']); + }); - $this->assertGreaterThanOrEqual(31, count($response['body'])); - $this->assertEquals(1, count($response['body']['requests'])); - $this->assertEquals(1, count($response['body']['network'])); - $this->assertEquals($requestsTotal, $response['body']['requests'][array_key_last($response['body']['requests'])]['value']); - $this->validateDates($response['body']['requests']); - $this->assertEquals($databasesTotal, $response['body']['databasesTotal']); - $this->assertEquals($documentsTotal, $response['body']['documentsTotal']); + $this->assertEventually(function () use ($collectionsTotal, $databasesTotal, $documentsTotal) { + $response = $this->client->call( + Client::METHOD_GET, + '/databases/usage?range=30d', + $this->getConsoleHeaders() + ); - $response = $this->client->call( - Client::METHOD_GET, - '/databases/usage?range=30d', - $this->getConsoleHeaders() - ); + $this->assertEquals($databasesTotal, $response['body']['databases'][array_key_last($response['body']['databases'])]['value']); + $this->validateDates($response['body']['databases']); + $this->assertEquals($collectionsTotal, $response['body']['collections'][array_key_last($response['body']['collections'])]['value']); + $this->validateDates($response['body']['collections']); + $this->assertEquals($documentsTotal, $response['body']['documents'][array_key_last($response['body']['documents'])]['value']); + $this->validateDates($response['body']['documents']); + }); - $this->assertEquals($databasesTotal, $response['body']['databases'][array_key_last($response['body']['databases'])]['value']); - $this->validateDates($response['body']['databases']); - $this->assertEquals($collectionsTotal, $response['body']['collections'][array_key_last($response['body']['collections'])]['value']); - $this->validateDates($response['body']['collections']); - $this->assertEquals($documentsTotal, $response['body']['documents'][array_key_last($response['body']['documents'])]['value']); - $this->validateDates($response['body']['documents']); + $this->assertEventually(function () use ($databaseId, $collectionsTotal, $documentsTotal) { + $response = $this->client->call( + Client::METHOD_GET, + '/databases/' . $databaseId . '/usage?range=30d', + $this->getConsoleHeaders() + ); - $response = $this->client->call( - Client::METHOD_GET, - '/databases/' . $databaseId . '/usage?range=30d', - $this->getConsoleHeaders() - ); + $this->assertEquals($collectionsTotal, $response['body']['collections'][array_key_last($response['body']['collections'])]['value']); + $this->validateDates($response['body']['collections']); - $this->assertEquals($collectionsTotal, $response['body']['collections'][array_key_last($response['body']['collections'])]['value']); - $this->validateDates($response['body']['collections']); + $this->assertEquals($documentsTotal, $response['body']['documents'][array_key_last($response['body']['documents'])]['value']); + $this->validateDates($response['body']['documents']); + }); - $this->assertEquals($documentsTotal, $response['body']['documents'][array_key_last($response['body']['documents'])]['value']); - $this->validateDates($response['body']['documents']); + $this->assertEventually(function () use ($databaseId, $collectionId, $documentsTotal) { + $response = $this->client->call( + Client::METHOD_GET, + '/databases/' . $databaseId . '/collections/' . $collectionId . '/usage?range=30d', + $this->getConsoleHeaders() + ); - $response = $this->client->call( - Client::METHOD_GET, - '/databases/' . $databaseId . '/collections/' . $collectionId . '/usage?range=30d', - $this->getConsoleHeaders() - ); - - $this->assertEquals($documentsTotal, $response['body']['documents'][array_key_last($response['body']['documents'])]['value']); - $this->validateDates($response['body']['documents']); + $this->assertEquals($documentsTotal, $response['body']['documents'][array_key_last($response['body']['documents'])]['value']); + $this->validateDates($response['body']['documents']); + }); return $data; } @@ -805,69 +812,69 @@ class UsageTest extends Scope } /** @depends testPrepareFunctionsStats */ - #[Retry(count: 10)] public function testFunctionsStats(array $data): array { - \sleep(1); // To prevent all 10 retries from running instantly - $functionId = $data['functionId']; $executionTime = $data['executionTime']; $executions = $data['executions']; - $response = $this->client->call( - Client::METHOD_GET, - '/functions/' . $functionId . '/usage?range=30d', - $this->getConsoleHeaders() - ); + $this->assertEventually(function () use ($functionId, $executions, $executionTime) { + $response = $this->client->call( + Client::METHOD_GET, + '/functions/' . $functionId . '/usage?range=30d', + $this->getConsoleHeaders() + ); - $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(24, count($response['body'])); - $this->assertEquals('30d', $response['body']['range']); - $this->assertIsArray($response['body']['deployments']); - $this->assertIsArray($response['body']['deploymentsStorage']); - $this->assertIsNumeric($response['body']['deploymentsStorageTotal']); - $this->assertIsNumeric($response['body']['buildsMbSecondsTotal']); - $this->assertIsNumeric($response['body']['executionsMbSecondsTotal']); - $this->assertIsArray($response['body']['builds']); - $this->assertIsArray($response['body']['buildsTime']); - $this->assertIsArray($response['body']['buildsMbSeconds']); - $this->assertIsArray($response['body']['executions']); - $this->assertIsArray($response['body']['executionsTime']); - $this->assertIsArray($response['body']['executionsMbSeconds']); - $this->assertEquals($executions, $response['body']['executions'][array_key_last($response['body']['executions'])]['value']); - $this->validateDates($response['body']['executions']); - $this->assertEquals($executionTime, $response['body']['executionsTime'][array_key_last($response['body']['executionsTime'])]['value']); - $this->validateDates($response['body']['executionsTime']); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(24, count($response['body'])); + $this->assertEquals('30d', $response['body']['range']); + $this->assertIsArray($response['body']['deployments']); + $this->assertIsArray($response['body']['deploymentsStorage']); + $this->assertIsNumeric($response['body']['deploymentsStorageTotal']); + $this->assertIsNumeric($response['body']['buildsMbSecondsTotal']); + $this->assertIsNumeric($response['body']['executionsMbSecondsTotal']); + $this->assertIsArray($response['body']['builds']); + $this->assertIsArray($response['body']['buildsTime']); + $this->assertIsArray($response['body']['buildsMbSeconds']); + $this->assertIsArray($response['body']['executions']); + $this->assertIsArray($response['body']['executionsTime']); + $this->assertIsArray($response['body']['executionsMbSeconds']); + $this->assertEquals($executions, $response['body']['executions'][array_key_last($response['body']['executions'])]['value']); + $this->validateDates($response['body']['executions']); + $this->assertEquals($executionTime, $response['body']['executionsTime'][array_key_last($response['body']['executionsTime'])]['value']); + $this->validateDates($response['body']['executionsTime']); + }); - $response = $this->client->call( - Client::METHOD_GET, - '/functions/usage?range=30d', - $this->getConsoleHeaders() - ); + $this->assertEventually(function () use ($executions, $executionTime) { + $response = $this->client->call( + Client::METHOD_GET, + '/functions/usage?range=30d', + $this->getConsoleHeaders() + ); - $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(25, count($response['body'])); - $this->assertEquals($response['body']['range'], '30d'); - $this->assertIsArray($response['body']['functions']); - $this->assertIsArray($response['body']['deployments']); - $this->assertIsArray($response['body']['deploymentsStorage']); - $this->assertIsArray($response['body']['builds']); - $this->assertIsArray($response['body']['buildsTime']); - $this->assertIsArray($response['body']['buildsMbSeconds']); - $this->assertIsArray($response['body']['executions']); - $this->assertIsArray($response['body']['executionsTime']); - $this->assertIsArray($response['body']['executionsMbSeconds']); - $this->assertEquals($executions, $response['body']['executions'][array_key_last($response['body']['executions'])]['value']); - $this->validateDates($response['body']['executions']); - $this->assertEquals($executionTime, $response['body']['executionsTime'][array_key_last($response['body']['executionsTime'])]['value']); - $this->validateDates($response['body']['executionsTime']); - $this->assertGreaterThan(0, $response['body']['buildsTime'][array_key_last($response['body']['buildsTime'])]['value']); - $this->validateDates($response['body']['buildsTime']); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(25, count($response['body'])); + $this->assertEquals($response['body']['range'], '30d'); + $this->assertIsArray($response['body']['functions']); + $this->assertIsArray($response['body']['deployments']); + $this->assertIsArray($response['body']['deploymentsStorage']); + $this->assertIsArray($response['body']['builds']); + $this->assertIsArray($response['body']['buildsTime']); + $this->assertIsArray($response['body']['buildsMbSeconds']); + $this->assertIsArray($response['body']['executions']); + $this->assertIsArray($response['body']['executionsTime']); + $this->assertIsArray($response['body']['executionsMbSeconds']); + $this->assertEquals($executions, $response['body']['executions'][array_key_last($response['body']['executions'])]['value']); + $this->validateDates($response['body']['executions']); + $this->assertEquals($executionTime, $response['body']['executionsTime'][array_key_last($response['body']['executionsTime'])]['value']); + $this->validateDates($response['body']['executionsTime']); + $this->assertGreaterThan(0, $response['body']['buildsTime'][array_key_last($response['body']['buildsTime'])]['value']); + $this->validateDates($response['body']['buildsTime']); + }); return $data; } - public function testPrepareSitesStats(): array { $siteId = $this->setupSite([ @@ -935,77 +942,79 @@ class UsageTest extends Scope } /** @depends testPrepareSitesStats */ - #[Retry(count: 10)] public function testSitesStats(array $data) { - \sleep(1); // To prevent all 10 retries from running instantly - $siteId = $data['siteId']; $executionTime = $data['executionTime'] ?? 0; $executions = $data['executions'] ?? 0; $deploymentsSuccess = $data['deploymentsSuccess']; $deploymentsFailed = $data['deploymentsFailed']; - $response = $this->client->call( - Client::METHOD_GET, - '/sites/' . $siteId . '/usage?range=30d', - $this->getConsoleHeaders() - ); - $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(30, count($response['body'])); - $this->assertEquals('30d', $response['body']['range']); - $this->assertIsArray($response['body']['deployments']); - $this->assertEquals($deploymentsSuccess, $response['body']['buildsSuccessTotal']); - $this->assertEquals($deploymentsFailed, $response['body']['buildsFailedTotal']); - $this->assertIsArray($response['body']['deploymentsStorage']); - $this->assertIsNumeric($response['body']['deploymentsStorageTotal']); - $this->assertIsNumeric($response['body']['buildsMbSecondsTotal']); - $this->assertIsNumeric($response['body']['executionsMbSecondsTotal']); - $this->assertIsArray($response['body']['builds']); - $this->assertIsArray($response['body']['buildsTime']); - $this->assertIsArray($response['body']['buildsMbSeconds']); - $this->assertIsArray($response['body']['executions']); - $this->assertIsArray($response['body']['executionsTime']); - $this->assertIsArray($response['body']['executionsMbSeconds']); - $this->assertIsArray($response['body']['buildsSuccess']); - $this->assertIsArray($response['body']['buildsFailed']); - $this->assertIsArray($response['body']['requests']); - $this->assertIsArray($response['body']['inbound']); - $this->assertIsArray($response['body']['outbound']); - $this->assertEquals($executions, $response['body']['executions'][array_key_last($response['body']['executions'])]['value']); - $this->validateDates($response['body']['executions']); - $this->assertEquals($executionTime, $response['body']['executionsTime'][array_key_last($response['body']['executionsTime'])]['value']); - $this->validateDates($response['body']['executionsTime']); + $this->assertEventually(function () use ($siteId, $deploymentsSuccess, $deploymentsFailed, $executions, $executionTime) { + $response = $this->client->call( + Client::METHOD_GET, + '/sites/' . $siteId . '/usage?range=30d', + $this->getConsoleHeaders() + ); - $response = $this->client->call( - Client::METHOD_GET, - '/sites/usage?range=30d', - $this->getConsoleHeaders() - ); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(30, count($response['body'])); + $this->assertEquals('30d', $response['body']['range']); + $this->assertIsArray($response['body']['deployments']); + $this->assertEquals($deploymentsSuccess, $response['body']['buildsSuccessTotal']); + $this->assertEquals($deploymentsFailed, $response['body']['buildsFailedTotal']); + $this->assertIsArray($response['body']['deploymentsStorage']); + $this->assertIsNumeric($response['body']['deploymentsStorageTotal']); + $this->assertIsNumeric($response['body']['buildsMbSecondsTotal']); + $this->assertIsNumeric($response['body']['executionsMbSecondsTotal']); + $this->assertIsArray($response['body']['builds']); + $this->assertIsArray($response['body']['buildsTime']); + $this->assertIsArray($response['body']['buildsMbSeconds']); + $this->assertIsArray($response['body']['executions']); + $this->assertIsArray($response['body']['executionsTime']); + $this->assertIsArray($response['body']['executionsMbSeconds']); + $this->assertIsArray($response['body']['buildsSuccess']); + $this->assertIsArray($response['body']['buildsFailed']); + $this->assertIsArray($response['body']['requests']); + $this->assertIsArray($response['body']['inbound']); + $this->assertIsArray($response['body']['outbound']); + $this->assertEquals($executions, $response['body']['executions'][array_key_last($response['body']['executions'])]['value']); + $this->validateDates($response['body']['executions']); + $this->assertEquals($executionTime, $response['body']['executionsTime'][array_key_last($response['body']['executionsTime'])]['value']); + $this->validateDates($response['body']['executionsTime']); + }); - $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(31, count($response['body'])); - $this->assertEquals($response['body']['range'], '30d'); - $this->assertIsArray($response['body']['sites']); - $this->assertIsArray($response['body']['deployments']); - $this->assertIsArray($response['body']['deploymentsStorage']); - $this->assertIsArray($response['body']['builds']); - $this->assertIsArray($response['body']['buildsTime']); - $this->assertIsArray($response['body']['buildsMbSeconds']); - $this->assertIsArray($response['body']['executions']); - $this->assertIsArray($response['body']['executionsTime']); - $this->assertIsArray($response['body']['executionsMbSeconds']); - $this->assertIsArray($response['body']['buildsSuccess']); - $this->assertIsArray($response['body']['buildsFailed']); - $this->assertIsArray($response['body']['requests']); - $this->assertIsArray($response['body']['inbound']); - $this->assertIsArray($response['body']['outbound']); - $this->assertEquals($executions, $response['body']['executions'][array_key_last($response['body']['executions'])]['value']); - $this->validateDates($response['body']['executions']); - $this->assertEquals($executionTime, $response['body']['executionsTime'][array_key_last($response['body']['executionsTime'])]['value']); - $this->validateDates($response['body']['executionsTime']); - $this->assertGreaterThan(0, $response['body']['buildsTime'][array_key_last($response['body']['buildsTime'])]['value']); - $this->validateDates($response['body']['buildsTime']); + $this->assertEventually(function () use ($executions, $executionTime) { + $response = $this->client->call( + Client::METHOD_GET, + '/sites/usage?range=30d', + $this->getConsoleHeaders() + ); + + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(31, count($response['body'])); + $this->assertEquals($response['body']['range'], '30d'); + $this->assertIsArray($response['body']['sites']); + $this->assertIsArray($response['body']['deployments']); + $this->assertIsArray($response['body']['deploymentsStorage']); + $this->assertIsArray($response['body']['builds']); + $this->assertIsArray($response['body']['buildsTime']); + $this->assertIsArray($response['body']['buildsMbSeconds']); + $this->assertIsArray($response['body']['executions']); + $this->assertIsArray($response['body']['executionsTime']); + $this->assertIsArray($response['body']['executionsMbSeconds']); + $this->assertIsArray($response['body']['buildsSuccess']); + $this->assertIsArray($response['body']['buildsFailed']); + $this->assertIsArray($response['body']['requests']); + $this->assertIsArray($response['body']['inbound']); + $this->assertIsArray($response['body']['outbound']); + $this->assertEquals($executions, $response['body']['executions'][array_key_last($response['body']['executions'])]['value']); + $this->validateDates($response['body']['executions']); + $this->assertEquals($executionTime, $response['body']['executionsTime'][array_key_last($response['body']['executionsTime'])]['value']); + $this->validateDates($response['body']['executionsTime']); + $this->assertGreaterThan(0, $response['body']['buildsTime'][array_key_last($response['body']['buildsTime'])]['value']); + $this->validateDates($response['body']['buildsTime']); + }); } /** @depends testFunctionsStats */ @@ -1042,30 +1051,33 @@ class UsageTest extends Scope $domain = $rule['body']['domain']; - $response = $this->client->call( - Client::METHOD_GET, - '/functions/' . $functionId . '/usage?range=30d', - $this->getConsoleHeaders() - ); + $this->assertEventually(function () use (&$response, $functionId) { + $response = $this->client->call( + Client::METHOD_GET, + '/functions/' . $functionId . '/usage?range=30d', + $this->getConsoleHeaders() + ); - $this->assertEquals(200, $response['headers']['status-code']); - $this->assertEquals(24, count($response['body'])); - $this->assertEquals('30d', $response['body']['range']); + $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEquals(24, count($response['body'])); + $this->assertEquals('30d', $response['body']['range']); + }); $functionsMetrics = $response['body']; - $response = $this->client->call( - Client::METHOD_GET, - '/project/usage', - $this->getConsoleHeaders(), - [ - 'period' => '1h', - 'startDate' => self::getToday(), - 'endDate' => self::getTomorrow(), - ] - ); - - $this->assertEquals(200, $response['headers']['status-code']); + $this->assertEventually(function () use (&$response) { + $response = $this->client->call( + Client::METHOD_GET, + '/project/usage', + $this->getConsoleHeaders(), + [ + 'period' => '1h', + 'startDate' => self::getToday(), + 'endDate' => self::getTomorrow(), + ] + ); + $this->assertEquals(200, $response['headers']['status-code']); + }); $projectMetrics = $response['body']; @@ -1080,8 +1092,6 @@ class UsageTest extends Scope $this->assertEquals(200, $response['headers']['status-code']); - $tries = 0; - $this->assertEventually(function () use ($functionId, $functionsMetrics, $projectMetrics) { // Compare new values with old values $response = $this->client->call( From 71c54f5742196dd55aaa925ab6598fe34013dc14 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Mon, 2 Jun 2025 17:15:01 +0100 Subject: [PATCH 177/219] tests: increase deployment timeouts commit-id:7d7dffac --- tests/e2e/Services/Functions/FunctionsBase.php | 2 +- tests/e2e/Services/Migrations/MigrationsBase.php | 2 +- tests/e2e/Services/Sites/SitesBase.php | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/e2e/Services/Functions/FunctionsBase.php b/tests/e2e/Services/Functions/FunctionsBase.php index 475eb9b9b4..27b67d851d 100644 --- a/tests/e2e/Services/Functions/FunctionsBase.php +++ b/tests/e2e/Services/Functions/FunctionsBase.php @@ -49,7 +49,7 @@ trait FunctionsBase 'x-appwrite-key' => $this->getProject()['apiKey'], ])); $this->assertEquals('ready', $deployment['body']['status'], 'Deployment status is not ready, deployment: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT)); - }, 50000, 500); + }, 100000, 500); // Not === so multipart/form-data works fine too if (($params['activate'] ?? false) == true) { diff --git a/tests/e2e/Services/Migrations/MigrationsBase.php b/tests/e2e/Services/Migrations/MigrationsBase.php index c241b38e3d..b8b9439e64 100644 --- a/tests/e2e/Services/Migrations/MigrationsBase.php +++ b/tests/e2e/Services/Migrations/MigrationsBase.php @@ -871,7 +871,7 @@ trait MigrationsBase $this->assertEquals(1, $deployments['body']['total']); $this->assertEquals('ready', $deployments['body']['deployments'][0]['status'], 'Deployment status is not ready, deployment: ' . json_encode($deployments['body']['deployments'][0], JSON_PRETTY_PRINT)); - }, 50000, 500); + }, 100000, 500); // Attempt execution $execution = $this->client->call(Client::METHOD_POST, '/functions/' . $functionId . '/executions', [ diff --git a/tests/e2e/Services/Sites/SitesBase.php b/tests/e2e/Services/Sites/SitesBase.php index 00edcc1b72..2054744863 100644 --- a/tests/e2e/Services/Sites/SitesBase.php +++ b/tests/e2e/Services/Sites/SitesBase.php @@ -265,7 +265,7 @@ trait SitesBase $this->assertEventually(function () use ($siteId, $deploymentId) { $deployment = $this->getDeployment($siteId, $deploymentId); $this->assertEquals('ready', $deployment['body']['status'], 'Deployment status is not ready, deployment: ' . json_encode($deployment['body'], JSON_PRETTY_PRINT)); - }, 100000, 500); + }, 150000, 500); $this->assertEventually(function () use ($siteId, $deploymentId) { $site = $this->getSite($siteId); From 584ca3065fa64437b78980d3879b417c845de53b Mon Sep 17 00:00:00 2001 From: Fabian Gruber Date: Fri, 30 May 2025 16:38:54 +0200 Subject: [PATCH 178/219] fix(gif preview): enable resource limits --- app/config/storage/inputs.php | 1 + app/config/storage/outputs.php | 1 + app/config/storage/resource_limits.php | 6 ++++++ app/init/configs.php | 2 ++ composer.lock | 24 ++++++++++++------------ 5 files changed, 22 insertions(+), 12 deletions(-) create mode 100644 app/config/storage/resource_limits.php diff --git a/app/config/storage/inputs.php b/app/config/storage/inputs.php index edcf667d86..a102dfdcf0 100644 --- a/app/config/storage/inputs.php +++ b/app/config/storage/inputs.php @@ -7,4 +7,5 @@ return [ "png" => "image/png", "heic" => "image/heic", "webp" => "image/webp", + "gif" => "image/gif", ]; diff --git a/app/config/storage/outputs.php b/app/config/storage/outputs.php index 519ff825fe..3e6fd45651 100644 --- a/app/config/storage/outputs.php +++ b/app/config/storage/outputs.php @@ -8,4 +8,5 @@ return [ "webp" => "image/webp", "heic" => "image/heic", "avif" => "image/avif", + "gif" => "image/gif", ]; diff --git a/app/config/storage/resource_limits.php b/app/config/storage/resource_limits.php new file mode 100644 index 0000000000..cfbcea5a47 --- /dev/null +++ b/app/config/storage/resource_limits.php @@ -0,0 +1,6 @@ + Date: Tue, 18 Mar 2025 12:29:32 +0100 Subject: [PATCH 179/219] chore(audits): return queue pre-fetch results --- src/Appwrite/Platform/Workers/Audits.php | 57 ++++++++++++------------ 1 file changed, 29 insertions(+), 28 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Audits.php b/src/Appwrite/Platform/Workers/Audits.php index 76309145b8..ce8dbedd73 100644 --- a/src/Appwrite/Platform/Workers/Audits.php +++ b/src/Appwrite/Platform/Workers/Audits.php @@ -12,13 +12,13 @@ use Utopia\Database\Exception\Authorization; use Utopia\Database\Exception\Structure; use Utopia\Platform\Action; use Utopia\Queue\Message; +use Utopia\Queue\Result\Commit; +use Utopia\Queue\Result\NoCommit; use Utopia\System\System; class Audits extends Action { - protected const BATCH_SIZE_DEVELOPMENT = 1; // smaller batch size for development - protected const BATCH_SIZE_PRODUCTION = 5_000; - protected const BATCH_AGGREGATION_INTERVAL = 60; // in seconds + protected const int BATCH_AGGREGATION_INTERVAL = 60; // in seconds private int $lastTriggeredTime = 0; @@ -27,9 +27,7 @@ class Audits extends Action protected function getBatchSize(): int { - return System::getEnv('_APP_ENV', 'development') === 'development' - ? self::BATCH_SIZE_DEVELOPMENT - : self::BATCH_SIZE_PRODUCTION; + return intval(System::getEnv('_APP_QUEUE_PREFETCH_COUNT', 1)); } public static function getName(): string @@ -57,13 +55,13 @@ class Audits extends Action * @param Message $message * @param callable $getProjectDB * @param Document $project - * @return void + * @return Commit|NoCommit * @throws Throwable * @throws \Utopia\Database\Exception * @throws Authorization * @throws Structure */ - public function action(Message $message, callable $getProjectDB, Document $project): void + public function action(Message $message, callable $getProjectDB, Document $project): Commit|NoCommit { $payload = $message->getPayload() ?? []; @@ -123,29 +121,32 @@ class Audits extends Action // Check if we should process the batch by checking both for the batch size and the elapsed time $batchSize = $this->getBatchSize(); - $shouldProcessBatch = \count($this->logs) >= $batchSize; - if (!$shouldProcessBatch && \count($this->logs) > 0) { + $logCount = array_reduce($this->logs, fn (int $current, $logs) => $current + count($logs['logs']), 0); + $shouldProcessBatch = $logCount >= $batchSize; + if (!$shouldProcessBatch && $logCount > 0) { $shouldProcessBatch = (\time() - $this->lastTriggeredTime) >= self::BATCH_AGGREGATION_INTERVAL; } - if ($shouldProcessBatch) { - try { - foreach ($this->logs as $internalId => $projectLogs) { - $dbForProject = $getProjectDB($projectLogs['project']); - - Console::log('Processing batch with ' . count($projectLogs['logs']) . ' events'); - $audit = new Audit($dbForProject); - - $audit->logBatch($projectLogs['logs']); - Console::success('Audit logs processed successfully'); - - unset($this->logs[$internalId]); - } - } catch (Throwable $e) { - Console::error('Error processing audit logs: ' . $e->getMessage()); - } finally { - $this->lastTriggeredTime = time(); - } + if (!$shouldProcessBatch) { + return new NoCommit(); } + + try { + foreach ($this->logs as $internalId => $projectLogs) { + $dbForProject = $getProjectDB($projectLogs['project']); + + Console::log('Processing batch with ' . count($projectLogs['logs']) . ' events'); + $audit = new Audit($dbForProject); + + $audit->logBatch($projectLogs['logs']); + Console::success('Audit logs processed successfully'); + + unset($this->logs[$internalId]); + } + } catch (Throwable $e) { + Console::error('Error processing audit logs: ' . $e->getMessage()); + } + $this->lastTriggeredTime = time(); + return new Commit(); } } From 7522a3a56ef84d4cf8aa16a12e24142b3b0c4a1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 3 Jun 2025 13:20:24 +0200 Subject: [PATCH 180/219] Fix multiregion view logs --- src/Appwrite/Vcs/Comment.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Vcs/Comment.php b/src/Appwrite/Vcs/Comment.php index d1d50c2ffd..21e64b4b24 100644 --- a/src/Appwrite/Vcs/Comment.php +++ b/src/Appwrite/Vcs/Comment.php @@ -87,7 +87,7 @@ class Comment $i = 0; foreach ($projects as $projectId => $project) { $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; - $hostname = System::getEnv('_APP_DOMAIN'); + $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN')); $text .= "## {$project['name']}\n\n"; $text .= "Project ID: `{$projectId}`\n\n"; From f9be8dc966ec0f8e15d1ed04b145f587e43bef40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Tue, 3 Jun 2025 13:20:56 +0200 Subject: [PATCH 181/219] Missed spot from previous commit --- src/Appwrite/Vcs/Comment.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Vcs/Comment.php b/src/Appwrite/Vcs/Comment.php index 21e64b4b24..5f528e660f 100644 --- a/src/Appwrite/Vcs/Comment.php +++ b/src/Appwrite/Vcs/Comment.php @@ -201,7 +201,7 @@ class Comment public function generatImage(string $pathLight, string $pathDark, string $alt, int $width): string { $protocol = System::getEnv('_APP_OPTIONS_FORCE_HTTPS') == 'disabled' ? 'http' : 'https'; - $hostname = System::getEnv('_APP_DOMAIN'); + $hostname = System::getEnv('_APP_CONSOLE_DOMAIN', System::getEnv('_APP_DOMAIN')); $imageLight = $protocol . '://' . $hostname . $pathLight; $imageDark = $protocol . '://' . $hostname . $pathDark; From 66f7d1a3c9d28b4a22bdb76772c24cb717f5d35a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Wed, 4 Jun 2025 16:54:07 +0200 Subject: [PATCH 182/219] Fix cache issues with proxy for deployment download --- .../Modules/Functions/Http/Deployments/Download/Get.php | 6 ++++-- .../Modules/Sites/Http/Deployments/Download/Get.php | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Download/Get.php b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Download/Get.php index 9456ff13a6..1993db4cf5 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Download/Get.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Deployments/Download/Get.php @@ -105,9 +105,11 @@ class Get extends Action $response ->setContentType('application/gzip') - ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days + ->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate') + ->addHeader('Expires', '0') + ->addHeader('Pragma', 'no-cache') ->addHeader('X-Peak', \memory_get_peak_usage()) - ->addHeader('Content-Disposition', 'attachment; filename="' . $deploymentId . '.tar.gz"'); + ->addHeader('Content-Disposition', 'attachment; filename="' . $deploymentId . '-' . $type . '.tar.gz"'); $size = $device->getFileSize($path); $rangeHeader = $request->getHeader('range'); diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Download/Get.php b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Download/Get.php index e83af0bab6..d3a2f0b814 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Download/Get.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Deployments/Download/Get.php @@ -99,12 +99,14 @@ class Get extends Action } if (!$device->exists($path)) { - throw new Exception(Exception::BUILD_NOT_FOUND); + throw new Exception(Exception::DEPLOYMENT_NOT_FOUND); } $response ->setContentType('application/gzip') - ->addHeader('Expires', \date('D, d M Y H:i:s', \time() + (60 * 60 * 24 * 45)) . ' GMT') // 45 days cache + ->addHeader('Cache-Control', 'no-cache, no-store, must-revalidate') + ->addHeader('Expires', '0') + ->addHeader('Pragma', 'no-cache') ->addHeader('X-Peak', \memory_get_peak_usage()) ->addHeader('Content-Disposition', 'attachment; filename="' . $deploymentId . '-' . $type . '.tar.gz"'); From 11f31a15b6bd8b2faadb9096fd3340d1883a8ed1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Mon, 9 Jun 2025 11:31:02 +0200 Subject: [PATCH 183/219] Link parent resource of redirect rule to allow list querying --- .../Proxy/Http/Rules/Redirect/Create.php | 18 +++++++++++++++++- tests/e2e/Services/Proxy/ProxyBase.php | 8 +++++--- .../Services/Proxy/ProxyCustomServerTest.php | 18 ++++++++++++++++-- 3 files changed, 38 insertions(+), 6 deletions(-) diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php index d0c9dbbbe3..3396a9c6fd 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php @@ -14,6 +14,7 @@ use Utopia\Database\Database; use Utopia\Database\Document; use Utopia\Database\Exception\Duplicate; use Utopia\Database\Helpers\ID; +use Utopia\Database\Validator\UID; use Utopia\Domains\Domain; use Utopia\Platform\Action; use Utopia\Platform\Scope\HTTP; @@ -65,15 +66,18 @@ class Create extends Action ->param('domain', null, new ValidatorDomain(), 'Domain name.') ->param('url', null, new URL(), 'Target URL of redirection') ->param('statusCode', null, new WhiteList([301, 302, 307, 308]), 'Status code of redirection') + ->param('resourceId', '', new UID(), 'ID of parent resource.') + ->param('resourceType', '', new WhiteList(['site', 'function']), 'Type of parent resource.') ->inject('response') ->inject('project') ->inject('queueForCertificates') ->inject('queueForEvents') ->inject('dbForPlatform') + ->inject('dbForProject') ->callback([$this, 'action']); } - public function action(string $domain, string $url, int $statusCode, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform) + public function action(string $domain, string $url, int $statusCode, string $resourceId, string $resourceType, Response $response, Document $project, Certificate $queueForCertificates, Event $queueForEvents, Database $dbForPlatform, Database $dbForProject) { $deniedDomains = [ 'localhost', @@ -116,6 +120,15 @@ class Create extends Action throw new Exception(Exception::GENERAL_ARGUMENT_INVALID, 'Domain may not start with http:// or https://.'); } + $collection = match ($resourceType) { + 'site' => 'sites', + 'function' => 'functions' + }; + $resource = $dbForProject->getDocument($collection, $resourceId); + if ($resource->isEmpty()) { + throw new Exception(Exception::RULE_RESOURCE_NOT_FOUND); + } + // TODO: @christyjacob remove once we migrate the rules in 1.7.x $ruleId = System::getEnv('_APP_RULES_FORMAT') === 'md5' ? md5($domain->get()) : ID::unique(); @@ -164,6 +177,9 @@ class Create extends Action 'trigger' => 'manual', 'redirectUrl' => $url, 'redirectStatusCode' => $statusCode, + 'deploymentResourceType' => $resourceType, + 'deploymentResourceId' => $resource->getId(), + 'deploymentResourceInternalId' => $resource->getInternalId(), 'certificateId' => '', 'search' => implode(' ', [$ruleId, $domain->get()]), 'owner' => $owner, diff --git a/tests/e2e/Services/Proxy/ProxyBase.php b/tests/e2e/Services/Proxy/ProxyBase.php index 44e015b751..9f8e92d56f 100644 --- a/tests/e2e/Services/Proxy/ProxyBase.php +++ b/tests/e2e/Services/Proxy/ProxyBase.php @@ -68,7 +68,7 @@ trait ProxyBase return $rule; } - protected function createRedirectRule(string $domain, string $url, int $statusCode): mixed + protected function createRedirectRule(string $domain, string $url, int $statusCode, string $resourceType, string $resourceId): mixed { $rule = $this->client->call(Client::METHOD_POST, '/proxy/rules/redirect', array_merge([ 'content-type' => 'application/json', @@ -77,6 +77,8 @@ trait ProxyBase 'domain' => $domain, 'url' => $url, 'statusCode' => $statusCode, + 'resourceType' => $resourceType, + 'resourceId' => $resourceId, ]); return $rule; @@ -115,9 +117,9 @@ trait ProxyBase return $rule['body']['$id']; } - protected function setupRedirectRule(string $domain, string $url, int $statusCode): string + protected function setupRedirectRule(string $domain, string $url, int $statusCode, string $resourceType, string $resourceId): string { - $rule = $this->createRedirectRule($domain, $url, $statusCode); + $rule = $this->createRedirectRule($domain, $url, $statusCode, $resourceType, $resourceId); $this->assertEquals(201, $rule['headers']['status-code'], 'Failed to setup rule: ' . \json_encode($rule)); diff --git a/tests/e2e/Services/Proxy/ProxyCustomServerTest.php b/tests/e2e/Services/Proxy/ProxyCustomServerTest.php index 9a7ba74ec1..ea310d5449 100644 --- a/tests/e2e/Services/Proxy/ProxyCustomServerTest.php +++ b/tests/e2e/Services/Proxy/ProxyCustomServerTest.php @@ -131,7 +131,9 @@ class ProxyCustomServerTest extends Scope $response = $proxyClient->call(Client::METHOD_GET, '/todos/1'); $this->assertEquals(404, $response['headers']['status-code']); - $ruleId = $this->setupRedirectRule($domain, 'https://jsonplaceholder.typicode.com/todos/1', 301); + $siteId = $this->setupSite()['siteId']; + + $ruleId = $this->setupRedirectRule($domain, 'https://jsonplaceholder.typicode.com/todos/1', 301, 'site', $siteId); $this->assertNotEmpty($ruleId); $response = $proxyClient->call(Client::METHOD_GET, '/todos/1'); @@ -147,7 +149,7 @@ class ProxyCustomServerTest extends Scope $this->assertEquals('https://jsonplaceholder.typicode.com/todos/1', $response['headers']['location']); $domain = \uniqid() . '-redirect-307.custom.localhost'; - $ruleId = $this->setupRedirectRule($domain, 'https://jsonplaceholder.typicode.com/todos/1', 307); + $ruleId = $this->setupRedirectRule($domain, 'https://jsonplaceholder.typicode.com/todos/1', 307, 'site', $siteId); $this->assertNotEmpty($ruleId); $proxyClient = new Client(); @@ -158,6 +160,18 @@ class ProxyCustomServerTest extends Scope $this->assertEquals(307, $response['headers']['status-code']); $this->assertEquals('https://jsonplaceholder.typicode.com/todos/1', $response['headers']['location']); + $rules = $this->listRules([ + 'queries' => [ + Query::equal('type', ['redirect'])->toString(), + Query::equal('trigger', ['manual'])->toString(), + Query::equal('deploymentResourceType', ['site'])->toString(), + Query::equal('deploymentResourceId', [$siteId])->toString(), + ], + ]); + $this->assertEquals(200, $rules['headers']['status-code']); + $this->assertEquals(2, $rules['body']['total']); + + $this->cleanupSite($siteId); $this->cleanupRule($ruleId); } From d6bcb46b36a8c11da4da6250ea0e9b7de8df0e6b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Matej=20Ba=C4=8Do?= Date: Mon, 9 Jun 2025 12:12:08 +0200 Subject: [PATCH 184/219] Fix specs and sdk generation --- .../specs/open-api3-latest-console.json | 23 ++++++++++++++++- app/config/specs/swagger2-latest-console.json | 25 ++++++++++++++++++- src/Appwrite/SDK/Specification/Format.php | 18 ++++++++++++- 3 files changed, 63 insertions(+), 3 deletions(-) diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 90ef137fc2..187281716f 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -25446,12 +25446,33 @@ "Temporary Redirect 307", "Permanent Redirect 308" ] + }, + "resourceId": { + "type": "string", + "description": "ID of parent resource.", + "x-example": "" + }, + "resourceType": { + "type": "string", + "description": "Type of parent resource.", + "x-example": "site", + "enum": [ + "site", + "function" + ], + "x-enum-name": "ProxyResourceType", + "x-enum-keys": [ + "Site", + "Function" + ] } }, "required": [ "domain", "url", - "statusCode" + "statusCode", + "resourceId", + "resourceType" ] } } diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index e53a0dfb0b..06a33c9a3d 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -25696,12 +25696,35 @@ "Temporary Redirect 307", "Permanent Redirect 308" ] + }, + "resourceId": { + "type": "string", + "description": "ID of parent resource.", + "default": null, + "x-example": "" + }, + "resourceType": { + "type": "string", + "description": "Type of parent resource.", + "default": null, + "x-example": "site", + "enum": [ + "site", + "function" + ], + "x-enum-name": "ProxyResourceType", + "x-enum-keys": [ + "Site", + "Function" + ] } }, "required": [ "domain", "url", - "statusCode" + "statusCode", + "resourceId", + "resourceType" ] } } diff --git a/src/Appwrite/SDK/Specification/Format.php b/src/Appwrite/SDK/Specification/Format.php index 8dbccf5cbb..af3b5c017e 100644 --- a/src/Appwrite/SDK/Specification/Format.php +++ b/src/Appwrite/SDK/Specification/Format.php @@ -113,6 +113,16 @@ abstract class Format protected function getEnumName(string $service, string $method, string $param): ?string { switch ($service) { + case 'proxy': + switch ($method) { + case 'createRedirectRule': + switch ($param) { + case 'resourceType': + return 'ProxyResourceType'; + } + break; + } + break; case 'console': switch ($method) { case 'getResource': @@ -441,7 +451,13 @@ abstract class Format case 'proxy': switch ($method) { case 'createRedirectRule': - return ['Moved Permanently 301', 'Found 302', 'Temporary Redirect 307', 'Permanent Redirect 308']; + switch ($param) { + case 'statusCode': + return ['Moved Permanently 301', 'Found 302', 'Temporary Redirect 307', 'Permanent Redirect 308']; + case 'resourceType': + return ['Site', 'Function']; + } + break; } break; case 'functions': From 41ce945c02ba70f51c89dc8378a704cb41ca3277 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 9 Jun 2025 20:23:15 -0400 Subject: [PATCH 185/219] Update lock --- composer.lock | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/composer.lock b/composer.lock index 2b2d6e5d61..debb3649b8 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "34142c56876c7ee1e2a798616b8ff114", + "content-hash": "1557e469b3074a6478a0b2fd522e1a2a", "packages": [ { "name": "adhocore/jwt", @@ -3490,16 +3490,16 @@ }, { "name": "utopia-php/database", - "version": "0.71.0", + "version": "0.71.1", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "cf463c0a5c64a4168fe56266ace4ae835d61c920" + "reference": "7b2622d336c2fa4bd6627d5e175083bd4f3c7c0e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/cf463c0a5c64a4168fe56266ace4ae835d61c920", - "reference": "cf463c0a5c64a4168fe56266ace4ae835d61c920", + "url": "https://api.github.com/repos/utopia-php/database/zipball/7b2622d336c2fa4bd6627d5e175083bd4f3c7c0e", + "reference": "7b2622d336c2fa4bd6627d5e175083bd4f3c7c0e", "shasum": "" }, "require": { @@ -3540,9 +3540,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.71.0" + "source": "https://github.com/utopia-php/database/tree/0.71.1" }, - "time": "2025-05-23T07:32:59+00:00" + "time": "2025-06-09T18:14:46+00:00" }, { "name": "utopia-php/detector", From bd4bb48da26fea5c4cb16c349267ff675030dbfe Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 9 Jun 2025 20:50:02 -0400 Subject: [PATCH 186/219] Fix merge --- app/controllers/api/teams.php | 6 +++--- .../Http/Functions/Deployment/Update.php | 10 +++++----- .../Modules/Functions/Workers/Builds.php | 16 +++++++--------- .../Modules/Proxy/Http/Rules/Redirect/Create.php | 2 +- .../Sites/Http/Sites/Deployment/Update.php | 10 +++++----- src/Appwrite/Platform/Workers/Audits.php | 4 ++-- 6 files changed, 23 insertions(+), 25 deletions(-) diff --git a/app/controllers/api/teams.php b/app/controllers/api/teams.php index eb497066f5..e72ea7bc92 100644 --- a/app/controllers/api/teams.php +++ b/app/controllers/api/teams.php @@ -1098,7 +1098,7 @@ App::patch('/v1/teams/:teamId/memberships/:membershipId') ); // Is the role change being requested by the user on their own membership? - $isCurrentUserAnOwner = $user->getInternalId() === $membership->getAttribute('userInternalId'); + $isCurrentUserAnOwner = $user->getSequence() === $membership->getAttribute('userInternalId'); // Prevent role change if there's only one owner left, // the requester is that owner, and the new `$roles` no longer include 'owner' @@ -1354,7 +1354,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') collection: 'memberships', queries: [ Query::contains('roles', ['owner']), - Query::equal('teamInternalId', [$team->getInternalId()]) + Query::equal('teamInternalId', [$team->getSequence()]) ], max: 2 ); @@ -1362,7 +1362,7 @@ App::delete('/v1/teams/:teamId/memberships/:membershipId') // Is the deletion being requested by the user on their own membership and they are also the owner? $isSelfOwner = in_array('owner', $membership->getAttribute('roles')) && - $membership->getAttribute('userInternalId') === $user->getInternalId(); + $membership->getAttribute('userInternalId') === $user->getSequence(); if ($ownersCount === 1 && $isSelfOwner) { /* Prevent removal if the user is the only owner. */ diff --git a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php index f91c8b88e1..23e2fc3b91 100644 --- a/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Functions/Http/Functions/Deployment/Update.php @@ -105,11 +105,11 @@ class Update extends Base $queries = [ Query::equal('trigger', ['manual']), - Query::equal("type", ["deployment"]), - Query::equal("deploymentResourceType", ["function"]), - Query::equal("deploymentResourceInternalId", [$function->getSequence()]), - Query::equal("deploymentVcsProviderBranch", [""]), - Query::equal("projectInternalId", [$project->getInternalId()]) + Query::equal('type', ['deployment']), + Query::equal('deploymentResourceType', ['function']), + Query::equal('deploymentResourceInternalId', [$function->getSequence()]), + Query::equal('deploymentVcsProviderBranch', ['']), + Query::equal('projectInternalId', [$project->getSequence()]) ]; Authorization::skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index 0cfaf096ab..a1159ffcf3 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -1081,13 +1081,12 @@ class Builds extends Action $resource = $dbForProject->updateDocument('functions', $resource->getId(), $resource); $queries = [ - Query::equal("projectInternalId", [$project->getSequence()]), - Query::equal("type", ["deployment"]), - Query::equal("deploymentResourceInternalId", [$resource->getSequence()]), + Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('type', ['deployment']), + Query::equal('deploymentResourceInternalId', [$resource->getSequence()]), Query::equal('deploymentResourceType', ['function']), Query::equal('trigger', ['manual']), Query::equal('deploymentVcsProviderBranch', ['']), - Query::equal("projectInternalId", [$project->getInternalId()]) ]; $rulesUpdated = false; @@ -1107,13 +1106,12 @@ class Builds extends Action $resource->setAttribute('deploymentCreatedAt', $deployment->getCreatedAt()); $resource = $dbForProject->updateDocument('sites', $resource->getId(), $resource); $queries = [ - Query::equal("projectInternalId", [$project->getSequence()]), - Query::equal("type", ["deployment"]), - Query::equal("deploymentResourceInternalId", [$resource->getSequence()]), + Query::equal('projectInternalId', [$project->getSequence()]), + Query::equal('type', ['deployment']), + Query::equal('deploymentResourceInternalId', [$resource->getSequence()]), Query::equal('deploymentResourceType', ['site']), Query::equal('trigger', ['manual']), Query::equal('deploymentVcsProviderBranch', ['']), - Query::equal("projectInternalId", [$project->getInternalId()]) ]; $dbForPlatform->forEach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { @@ -1170,7 +1168,7 @@ class Builds extends Action } $queries = [ - Query::equal('projectInternalId', [$project->getInternalId()]), + Query::equal('projectInternalId', [$project->getSequence()]), Query::equal('type', ['deployment']), Query::equal('deploymentResourceInternalId', [$resource->getSequence()]), Query::equal('deploymentResourceType', ['site']), diff --git a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php index a8f966786c..60e8759e5c 100644 --- a/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php +++ b/src/Appwrite/Platform/Modules/Proxy/Http/Rules/Redirect/Create.php @@ -179,7 +179,7 @@ class Create extends Action 'redirectStatusCode' => $statusCode, 'deploymentResourceType' => $resourceType, 'deploymentResourceId' => $resource->getId(), - 'deploymentResourceInternalId' => $resource->getInternalId(), + 'deploymentResourceInternalId' => $resource->getSequence(), 'certificateId' => '', 'search' => implode(' ', [$ruleId, $domain->get()]), 'owner' => $owner, diff --git a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php index e71e23fa59..a45c2a1243 100644 --- a/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php +++ b/src/Appwrite/Platform/Modules/Sites/Http/Sites/Deployment/Update.php @@ -97,11 +97,11 @@ class Update extends Base $queries = [ Query::equal('trigger', ['manual']), - Query::equal("type", ["deployment"]), - Query::equal("deploymentResourceType", ["site"]), - Query::equal("deploymentResourceInternalId", [$site->getSequence()]), - Query::equal("deploymentVcsProviderBranch", [""]), - Query::equal("projectInternalId", [$project->getInternalId()]) + Query::equal('type', ['deployment']), + Query::equal('deploymentResourceType', ['site']), + Query::equal('deploymentResourceInternalId', [$site->getSequence()]), + Query::equal('deploymentVcsProviderBranch', ['']), + Query::equal('projectInternalId', [$project->getSequence()]) ]; Authorization::skip(fn () => $dbForPlatform->foreach('rules', function (Document $rule) use ($dbForPlatform, $deployment) { diff --git a/src/Appwrite/Platform/Workers/Audits.php b/src/Appwrite/Platform/Workers/Audits.php index 7b68d05cd0..9d4bbbc408 100644 --- a/src/Appwrite/Platform/Workers/Audits.php +++ b/src/Appwrite/Platform/Workers/Audits.php @@ -132,7 +132,7 @@ class Audits extends Action } try { - foreach ($this->logs as $internalId => $projectLogs) { + foreach ($this->logs as $sequence => $projectLogs) { $dbForProject = $getProjectDB($projectLogs['project']); Console::log('Processing batch with ' . count($projectLogs['logs']) . ' events'); @@ -141,7 +141,7 @@ class Audits extends Action $audit->logBatch($projectLogs['logs']); Console::success('Audit logs processed successfully'); - unset($this->logs[$internalId]); + unset($this->logs[$sequence]); } } catch (Throwable $e) { Console::error('Error processing audit logs: ' . $e->getMessage()); From 9fc2c5db69d8ea174caaef384de29496fde00085 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Mon, 9 Jun 2025 23:56:30 -0400 Subject: [PATCH 187/219] Add increment + decrement routes --- app/controllers/api/databases.php | 156 +++++++++++++ composer.lock | 24 +- .../e2e/Services/Databases/DatabasesBase.php | 206 ++++++++++++++++++ 3 files changed, 374 insertions(+), 12 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 6cafc2ffef..887695c087 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -38,6 +38,7 @@ use Utopia\Database\Exception\Relationship as RelationshipException; use Utopia\Database\Exception\Restricted as RestrictedException; use Utopia\Database\Exception\Structure as StructureException; use Utopia\Database\Exception\Truncate as TruncateException; +use Utopia\Database\Exception\Type as TypeException; use Utopia\Database\Helpers\ID; use Utopia\Database\Helpers\Permission; use Utopia\Database\Helpers\Role; @@ -62,6 +63,7 @@ use Utopia\Validator\Integer; use Utopia\Validator\IP; use Utopia\Validator\JSON; use Utopia\Validator\Nullable; +use Utopia\Validator\Numeric; use Utopia\Validator\Range; use Utopia\Validator\Text; use Utopia\Validator\URL; @@ -4462,6 +4464,160 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $response->dynamic($document, Response::MODEL_DOCUMENT); }); +App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId/:key/increment') + ->desc('Increment document attribute') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].upsert') + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'documents.increment') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', new Method( + namespace: 'databases', + group: 'documents', + name: 'incrementDocumentAttribute', + description: '/docs/references/databases/increment-document-attribute.md', + auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DOCUMENT, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('documentId', '', new UID(), 'Document ID.') + ->param('attribute', '', new Key(), 'Document ID.') + ->param('value', 1, new Numeric(), 'Value to increment the attribute by. The value must be a number.', true) + ->param('max', null, new Numeric(), 'Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->action(function (string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, Response $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) { + $database = $dbForProject->getDocument('databases', $databaseId); + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + if ($collection->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + try { + $document = $dbForProject->increaseDocumentAttribute( + collection: 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + id: $documentId, + attribute: $attribute, + value: $value, + max: $max + ); + } catch (ConflictException) { + throw new Exception(Exception::DOCUMENT_UPDATE_CONFLICT); + } catch (NotFoundException) { + throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); + } catch (LimitException) { + throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute `' . $attribute . '` has reached the maximum value of ' . $max); + } catch (TypeException) { + throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, 'Attribute `' . $attribute . '` is not a number'); + } + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1); + + $queueForEvents + ->setParam('databaseId', $databaseId) + ->setParam('collectionId', $collectionId) + ->setContext('collection', $collection) + ->setContext('database', $database); + + $response->dynamic($document, Response::MODEL_DOCUMENT); + }); + +App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId/:key/decrement') + ->desc('Decrement document attribute') + ->groups(['api', 'database']) + ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].decrement') + ->label('scope', 'documents.write') + ->label('resourceType', RESOURCE_TYPE_DATABASES) + ->label('audits.event', 'documents.decrement') + ->label('audits.resource', 'database/{request.databaseId}/collection/{request.collectionId}') + ->label('abuse-key', 'ip:{ip},method:{method},url:{url},userId:{userId}') + ->label('abuse-limit', APP_LIMIT_WRITE_RATE_DEFAULT * 2) + ->label('abuse-time', APP_LIMIT_WRITE_RATE_PERIOD_DEFAULT) + ->label('sdk', new Method( + namespace: 'databases', + group: 'documents', + name: 'decrementDocumentAttribute', + description: '/docs/references/databases/increment-document-attribute.md', + auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT], + responses: [ + new SDKResponse( + code: Response::STATUS_CODE_NOCONTENT, + model: Response::MODEL_NONE, + ) + ], + contentType: ContentType::JSON + )) + ->param('databaseId', '', new UID(), 'Database ID.') + ->param('collectionId', '', new UID(), 'Collection ID.') + ->param('documentId', '', new UID(), 'Document ID.') + ->param('attribute', '', new Key(), 'Document ID.') + ->param('value', 1, new Numeric(), 'Value to decrement the attribute by. The value must be a number.', true) + ->param('min', null, new Numeric(), 'Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.', true) + ->inject('response') + ->inject('dbForProject') + ->inject('queueForEvents') + ->inject('queueForStatsUsage') + ->action(function (string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, Response $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) { + $database = $dbForProject->getDocument('databases', $databaseId); + if ($database->isEmpty()) { + throw new Exception(Exception::DATABASE_NOT_FOUND); + } + + $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + if ($collection->isEmpty()) { + throw new Exception(Exception::COLLECTION_NOT_FOUND); + } + + try { + $document = $dbForProject->decreaseDocumentAttribute( + collection: 'database_' . $database->getSequence() . '_collection_' . $collection->getSequence(), + id: $documentId, + attribute: $attribute, + value: $value, + min: $min + ); + } catch (ConflictException) { + throw new Exception(Exception::DOCUMENT_UPDATE_CONFLICT); + } catch (NotFoundException) { + throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); + } catch (LimitException) { + throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute "' . $attribute . '" has reached the minimum value of ' . $min); + } catch (TypeException) { + throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, 'Attribute "' . $attribute . '" is not a number'); + } + + $queueForStatsUsage + ->addMetric(METRIC_DATABASES_OPERATIONS_WRITES, 1) + ->addMetric(str_replace('{databaseInternalId}', $database->getSequence(), METRIC_DATABASE_ID_OPERATIONS_WRITES), 1); + + $queueForEvents + ->setParam('databaseId', $databaseId) + ->setParam('collectionId', $collectionId) + ->setContext('collection', $collection) + ->setContext('database', $database); + + $response->dynamic($document, Response::MODEL_DOCUMENT); + }); + App::patch('/v1/databases/:databaseId/collections/:collectionId/documents') ->desc('Update documents') ->groups(['api', 'database']) diff --git a/composer.lock b/composer.lock index debb3649b8..0ce712ea30 100644 --- a/composer.lock +++ b/composer.lock @@ -3490,16 +3490,16 @@ }, { "name": "utopia-php/database", - "version": "0.71.1", + "version": "0.71.3", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "7b2622d336c2fa4bd6627d5e175083bd4f3c7c0e" + "reference": "f0c28b78548e2b740d940ca17dca30e1e532d53c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/7b2622d336c2fa4bd6627d5e175083bd4f3c7c0e", - "reference": "7b2622d336c2fa4bd6627d5e175083bd4f3c7c0e", + "url": "https://api.github.com/repos/utopia-php/database/zipball/f0c28b78548e2b740d940ca17dca30e1e532d53c", + "reference": "f0c28b78548e2b740d940ca17dca30e1e532d53c", "shasum": "" }, "require": { @@ -3540,9 +3540,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.71.1" + "source": "https://github.com/utopia-php/database/tree/0.71.3" }, - "time": "2025-06-09T18:14:46+00:00" + "time": "2025-06-10T03:53:35+00:00" }, { "name": "utopia-php/detector", @@ -4807,16 +4807,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.41.1", + "version": "0.41.2", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "6d9318abf4542a757c87abf056557d6afa1dc06b" + "reference": "e9a324efef9080808e07a782be2420cd4454cff7" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/6d9318abf4542a757c87abf056557d6afa1dc06b", - "reference": "6d9318abf4542a757c87abf056557d6afa1dc06b", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/e9a324efef9080808e07a782be2420cd4454cff7", + "reference": "e9a324efef9080808e07a782be2420cd4454cff7", "shasum": "" }, "require": { @@ -4852,9 +4852,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.41.1" + "source": "https://github.com/appwrite/sdk-generator/tree/0.41.2" }, - "time": "2025-06-01T04:20:04+00:00" + "time": "2025-06-10T03:08:44+00:00" }, { "name": "doctrine/annotations", diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 6038448889..b18f918049 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -5298,4 +5298,210 @@ trait DatabasesBase 'x-appwrite-key' => $this->getProject()['apiKey'] ])); } + + /** + * @throws \Exception + */ + public function testIncrementAttributeRoutes(): array + { + $database = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'databaseId' => ID::unique(), + 'name' => 'CounterDatabase' + ]); + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'CounterCollection', + 'documentSecurity' => true, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + Permission::read(Role::user($this->getUser()['$id'])), + ], + ]); + $collectionId = $collection['body']['$id']; + + // Add integer attribute + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'count', + 'required' => true, + 'default' => 0, + ]); + + \sleep(1); + + // Create document with initial count = 5 + $doc = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'documentId' => 'counter1', + 'data' => ['count' => 5], + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + $this->assertEquals(201, $doc['headers']['status-code']); + + // Increment by default 1 + $inc = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/counter1/count/increment', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ])); + $this->assertEquals(200, $inc['headers']['status-code']); + $this->assertEquals(6, $inc['body']['count']); + + // Verify count = 6 + $get = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/counter1', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(6, $get['body']['count']); + + // Increment by custom value 4 + $inc2 = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/counter1/count/increment', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]), [ + 'value' => 4 + ]); + $this->assertEquals(200, $inc2['headers']['status-code']); + $this->assertEquals(10, $inc2['body']['count']); + + $get2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/counter1', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(10, $get2['body']['count']); + + // Test max limit exceeded + $err = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/counter1/count/increment', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]), ['max' => 8]); + $this->assertEquals(400, $err['headers']['status-code']); + + // Test attribute not found + $notFound = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/counter1/unknown/increment', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ])); + $this->assertEquals(404, $notFound['headers']['status-code']); + } + + public function testDecrementAttributeRoutes(array $data): void + { + $database = $this->client->call(Client::METHOD_POST, '/databases', [ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ], [ + 'databaseId' => ID::unique(), + 'name' => 'CounterDatabase' + ]); + + $databaseId = $database['body']['$id']; + + $collection = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'collectionId' => ID::unique(), + 'name' => 'CounterCollection', + 'documentSecurity' => true, + 'permissions' => [ + Permission::create(Role::user($this->getUser()['$id'])), + Permission::read(Role::user($this->getUser()['$id'])), + ], + ]); + + $collectionId = $collection['body']['$id']; + + // Add integer attribute + $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/attributes/integer', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + 'x-appwrite-key' => $this->getProject()['apiKey'] + ]), [ + 'key' => 'count', + 'required' => true, + 'default' => 10, + ]); + + \sleep(1); + + // Create document with initial count = 10 + $documentId = 'counter1'; + $doc = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders()), [ + 'documentId' => $documentId, + 'data' => ['count' => 10], + 'permissions' => [ + Permission::read(Role::any()), + Permission::update(Role::any()), + ], + ]); + + // Decrement by default 1 (count = 10 -> 9) + $dec = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId . '/count/decrement', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ])); + $this->assertEquals(200, $dec['headers']['status-code']); + $this->assertEquals(9, $dec['body']['count']); + + $get = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(9, $get['body']['count']); + + // Decrement by custom value 3 (count 9 -> 6) + $dec2 = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId . '/count/decrement', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]), [ + 'value' => 3 + ]); + $this->assertEquals(200, $dec2['headers']['status-code']); + $this->assertEquals(6, $dec2['body']['count']); + + $get2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId, array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ], $this->getHeaders())); + $this->assertEquals(6, $get2['body']['count']); + + // Test min limit exceeded + $err = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId . '/count/decrement', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]), ['min' => 7]); + $this->assertEquals(400, $err['headers']['status-code']); + + // Test type error on non-numeric attribute + $typeErr = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId . '/count/decrement', array_merge([ + 'content-type' => 'application/json', + 'x-appwrite-project' => $this->getProject()['$id'], + ]), ['value' => 'not-a-number']); + $this->assertEquals(400, $typeErr['headers']['status-code']); + } + + } From fd7d4db4c498ee716631d01155d5bb6ed4b0ae81 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 10 Jun 2025 00:22:38 -0400 Subject: [PATCH 188/219] Fix path param --- app/controllers/api/databases.php | 4 ++-- .../e2e/Services/Databases/DatabasesBase.php | 21 ++++++++++--------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 887695c087..16a8b05339 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4464,7 +4464,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen $response->dynamic($document, Response::MODEL_DOCUMENT); }); -App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId/:key/increment') +App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId/:attribute/increment') ->desc('Increment document attribute') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].upsert') @@ -4541,7 +4541,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum $response->dynamic($document, Response::MODEL_DOCUMENT); }); -App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId/:key/decrement') +App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId/:attribute/decrement') ->desc('Decrement document attribute') ->groups(['api', 'database']) ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].decrement') diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index b18f918049..54502c44f9 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -5302,7 +5302,7 @@ trait DatabasesBase /** * @throws \Exception */ - public function testIncrementAttributeRoutes(): array + public function testIncrementAttribute(): void { $database = $this->client->call(Client::METHOD_POST, '/databases', [ 'content-type' => 'application/json', @@ -5337,10 +5337,9 @@ trait DatabasesBase ]), [ 'key' => 'count', 'required' => true, - 'default' => 0, ]); - \sleep(1); + \sleep(2); // Create document with initial count = 5 $doc = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ @@ -5348,7 +5347,9 @@ trait DatabasesBase 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ 'documentId' => 'counter1', - 'data' => ['count' => 5], + 'data' => [ + 'count' => 5 + ], 'permissions' => [ Permission::read(Role::any()), Permission::update(Role::any()), @@ -5402,7 +5403,7 @@ trait DatabasesBase $this->assertEquals(404, $notFound['headers']['status-code']); } - public function testDecrementAttributeRoutes(array $data): void + public function testDecrementAttribute(): void { $database = $this->client->call(Client::METHOD_POST, '/databases', [ 'content-type' => 'application/json', @@ -5439,18 +5440,16 @@ trait DatabasesBase ]), [ 'key' => 'count', 'required' => true, - 'default' => 10, ]); - \sleep(1); + \sleep(2); // Create document with initial count = 10 - $documentId = 'counter1'; $doc = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => $documentId, + 'documentId' => ID::unique(), 'data' => ['count' => 10], 'permissions' => [ Permission::read(Role::any()), @@ -5458,6 +5457,8 @@ trait DatabasesBase ], ]); + $documentId = $doc['body']['$id']; + // Decrement by default 1 (count = 10 -> 9) $dec = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId . '/count/decrement', array_merge([ 'content-type' => 'application/json', @@ -5495,7 +5496,7 @@ trait DatabasesBase ]), ['min' => 7]); $this->assertEquals(400, $err['headers']['status-code']); - // Test type error on non-numeric attribute + // Test type error on non-numeric attribut $typeErr = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/' . $documentId . '/count/decrement', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], From 5585a75624741bad7d5d8cdf8dd4fe8c42bf945f Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 10 Jun 2025 00:22:46 -0400 Subject: [PATCH 189/219] Fix auth skips --- app/controllers/api/databases.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 16a8b05339..7b7bb2d46f 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4500,12 +4500,12 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum ->inject('queueForEvents') ->inject('queueForStatsUsage') ->action(function (string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $max, Response $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) { - $database = $dbForProject->getDocument('databases', $databaseId); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } @@ -4577,12 +4577,12 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum ->inject('queueForEvents') ->inject('queueForStatsUsage') ->action(function (string $databaseId, string $collectionId, string $documentId, string $attribute, int|float $value, int|float|null $min, Response $response, Database $dbForProject, Event $queueForEvents, StatsUsage $queueForStatsUsage) { - $database = $dbForProject->getDocument('databases', $databaseId); + $database = Authorization::skip(fn () => $dbForProject->getDocument('databases', $databaseId)); if ($database->isEmpty()) { throw new Exception(Exception::DATABASE_NOT_FOUND); } - $collection = $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId); + $collection = Authorization::skip(fn () => $dbForProject->getDocument('database_' . $database->getSequence(), $collectionId)); if ($collection->isEmpty()) { throw new Exception(Exception::COLLECTION_NOT_FOUND); } From e6881c10d4faa509a4127bade870539437c108ea Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 10 Jun 2025 00:32:38 -0400 Subject: [PATCH 190/219] Fix desc --- app/controllers/api/databases.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 7b7bb2d46f..4fa8c75c11 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4492,7 +4492,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') ->param('documentId', '', new UID(), 'Document ID.') - ->param('attribute', '', new Key(), 'Document ID.') + ->param('attribute', '', new Key(), 'Attribute key.') ->param('value', 1, new Numeric(), 'Value to increment the attribute by. The value must be a number.', true) ->param('max', null, new Numeric(), 'Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.', true) ->inject('response') @@ -4569,7 +4569,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum ->param('databaseId', '', new UID(), 'Database ID.') ->param('collectionId', '', new UID(), 'Collection ID.') ->param('documentId', '', new UID(), 'Document ID.') - ->param('attribute', '', new Key(), 'Document ID.') + ->param('attribute', '', new Key(), 'Attribute key.') ->param('value', 1, new Numeric(), 'Value to decrement the attribute by. The value must be a number.', true) ->param('min', null, new Numeric(), 'Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.', true) ->inject('response') From 91b1670e52f72d9df67e4712ee79bc034e3a042f Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 10 Jun 2025 00:35:03 -0400 Subject: [PATCH 191/219] Fix event --- app/controllers/api/databases.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 4fa8c75c11..4defbfe5cd 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4467,7 +4467,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents/:documen App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:documentId/:attribute/increment') ->desc('Increment document attribute') ->groups(['api', 'database']) - ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].upsert') + ->label('event', 'databases.[databaseId].collections.[collectionId].documents.[documentId].increment') ->label('scope', 'documents.write') ->label('resourceType', RESOURCE_TYPE_DATABASES) ->label('audits.event', 'documents.increment') From cf13a4518838264e5199005749b5f90793caee8a Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 10 Jun 2025 00:36:55 -0400 Subject: [PATCH 192/219] Docs --- app/controllers/api/databases.php | 2 +- docs/references/databases/decrement-document-attribute.md | 1 + docs/references/databases/increment-document-attribute.md | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 docs/references/databases/decrement-document-attribute.md create mode 100644 docs/references/databases/increment-document-attribute.md diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 4defbfe5cd..6e308fd090 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4556,7 +4556,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum namespace: 'databases', group: 'documents', name: 'decrementDocumentAttribute', - description: '/docs/references/databases/increment-document-attribute.md', + description: '/docs/references/databases/decrement-document-attribute.md', auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT], responses: [ new SDKResponse( diff --git a/docs/references/databases/decrement-document-attribute.md b/docs/references/databases/decrement-document-attribute.md new file mode 100644 index 0000000000..e0ed8140ea --- /dev/null +++ b/docs/references/databases/decrement-document-attribute.md @@ -0,0 +1 @@ +Decrement a specific attribute of a document by a given value. \ No newline at end of file diff --git a/docs/references/databases/increment-document-attribute.md b/docs/references/databases/increment-document-attribute.md new file mode 100644 index 0000000000..13bd612eed --- /dev/null +++ b/docs/references/databases/increment-document-attribute.md @@ -0,0 +1 @@ +Increment a specific attribute of a document by a given value. \ No newline at end of file From 6ea61106f4db799c1e2ec3387123cb9c20e8e269 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 10 Jun 2025 00:37:33 -0400 Subject: [PATCH 193/219] Update model --- app/controllers/api/databases.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 6e308fd090..85fae8ea35 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4560,8 +4560,8 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT], responses: [ new SDKResponse( - code: Response::STATUS_CODE_NOCONTENT, - model: Response::MODEL_NONE, + code: Response::STATUS_CODE_OK, + model: Response::MODEL_DOCUMENT, ) ], contentType: ContentType::JSON From bc3e1990d0fd6bb830823b14c57849a24e718988 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 10 Jun 2025 16:12:24 +0400 Subject: [PATCH 194/219] chore: update maintenance task to only iterate over active projects --- composer.lock | 12 +++++----- src/Appwrite/Platform/Tasks/Maintenance.php | 25 ++++++++++++++------- 2 files changed, 23 insertions(+), 14 deletions(-) diff --git a/composer.lock b/composer.lock index d7b9f22722..da740d8c72 100644 --- a/composer.lock +++ b/composer.lock @@ -4807,16 +4807,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.41.1", + "version": "0.41.4", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "6d9318abf4542a757c87abf056557d6afa1dc06b" + "reference": "07804269131f411576aac60c795a5ebc3afaa48a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/6d9318abf4542a757c87abf056557d6afa1dc06b", - "reference": "6d9318abf4542a757c87abf056557d6afa1dc06b", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/07804269131f411576aac60c795a5ebc3afaa48a", + "reference": "07804269131f411576aac60c795a5ebc3afaa48a", "shasum": "" }, "require": { @@ -4852,9 +4852,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.41.1" + "source": "https://github.com/appwrite/sdk-generator/tree/0.41.4" }, - "time": "2025-06-01T04:20:04+00:00" + "time": "2025-06-10T08:28:11+00:00" }, { "name": "doctrine/annotations", diff --git a/src/Appwrite/Platform/Tasks/Maintenance.php b/src/Appwrite/Platform/Tasks/Maintenance.php index fd9d05dec9..b2496e813b 100644 --- a/src/Appwrite/Platform/Tasks/Maintenance.php +++ b/src/Appwrite/Platform/Tasks/Maintenance.php @@ -2,11 +2,13 @@ namespace Appwrite\Platform\Tasks; +use DateInterval; +use DateTime; use Appwrite\Event\Certificate; use Appwrite\Event\Delete; use Utopia\CLI\Console; use Utopia\Database\Database; -use Utopia\Database\DateTime; +use Utopia\Database\DateTime as DatabaseDateTime; use Utopia\Database\Document; use Utopia\Database\Query; use Utopia\Platform\Action; @@ -58,29 +60,36 @@ class Maintenance extends Action Console::info('Setting loop start time to ' . $next->format("Y-m-d H:i:s.v") . '. Delaying for ' . $delay . ' seconds.'); Console::loop(function () use ($interval, $cacheRetention, $schedulesDeletionRetention, $usageStatsRetentionHourly, $dbForPlatform, $console, $queueForDeletes, $queueForCertificates) { - $time = DateTime::now(); + $time = DatabaseDateTime::now(); Console::info("[{$time}] Notifying workers with maintenance tasks every {$interval} seconds"); + // Iterate through project only if it was accessed in last 24 hours + $interval = DateInterval::createFromDateString('24 hours'); + $before24h = (new DateTime())->sub($interval); + $dbForPlatform->foreach( 'projects', function (Document $project) use ($queueForDeletes, $usageStatsRetentionHourly) { + Console::info('Project accessed at ' . $project->getId()); $queueForDeletes ->setType(DELETE_TYPE_MAINTENANCE) ->setProject($project) - ->setUsageRetentionHourlyDateTime(DateTime::addSeconds(new \DateTime(), -1 * $usageStatsRetentionHourly)) + ->setUsageRetentionHourlyDateTime(DatabaseDateTime::addSeconds(new \DateTime(), -1 * $usageStatsRetentionHourly)) ->trigger(); }, [ Query::equal('region', [System::getEnv('_APP_REGION', 'default')]), Query::limit(100), + Query::greaterThanEqual('accessedAt', DatabaseDateTime::format($before24h)), + Query::orderAsc('teamInternalId'), ] ); $queueForDeletes ->setType(DELETE_TYPE_MAINTENANCE) ->setProject($console) - ->setUsageRetentionHourlyDateTime(DateTime::addSeconds(new \DateTime(), -1 * $usageStatsRetentionHourly)) + ->setUsageRetentionHourlyDateTime(DatabaseDateTime::addSeconds(new \DateTime(), -1 * $usageStatsRetentionHourly)) ->trigger(); $this->notifyDeleteConnections($queueForDeletes); @@ -94,13 +103,13 @@ class Maintenance extends Action { $queueForDeletes ->setType(DELETE_TYPE_REALTIME) - ->setDatetime(DateTime::addSeconds(new \DateTime(), -60)) + ->setDatetime(DatabaseDateTime::addSeconds(new \DateTime(), -60)) ->trigger(); } private function renewCertificates(Database $dbForPlatform, Certificate $queueForCertificate): void { - $time = DateTime::now(); + $time = DatabaseDateTime::now(); $certificates = $dbForPlatform->find('certificates', [ Query::lessThan('attempts', 5), // Maximum 5 attempts @@ -129,7 +138,7 @@ class Maintenance extends Action { $queueForDeletes ->setType(DELETE_TYPE_CACHE_BY_TIMESTAMP) - ->setDatetime(DateTime::addSeconds(new \DateTime(), -1 * $interval)) + ->setDatetime(DatabaseDateTime::addSeconds(new \DateTime(), -1 * $interval)) ->trigger(); } @@ -137,7 +146,7 @@ class Maintenance extends Action { $queueForDeletes ->setType(DELETE_TYPE_SCHEDULES) - ->setDatetime(DateTime::addSeconds(new \DateTime(), -1 * $interval)) + ->setDatetime(DatabaseDateTime::addSeconds(new \DateTime(), -1 * $interval)) ->trigger(); } } From b1e11ab854c7bf1b37652be8b4f69ab6467de250 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 10 Jun 2025 16:14:53 +0400 Subject: [PATCH 195/219] chore: update maintenance task to only iterate over active projects --- src/Appwrite/Platform/Tasks/Maintenance.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/Maintenance.php b/src/Appwrite/Platform/Tasks/Maintenance.php index b2496e813b..0d7409a936 100644 --- a/src/Appwrite/Platform/Tasks/Maintenance.php +++ b/src/Appwrite/Platform/Tasks/Maintenance.php @@ -65,8 +65,8 @@ class Maintenance extends Action Console::info("[{$time}] Notifying workers with maintenance tasks every {$interval} seconds"); // Iterate through project only if it was accessed in last 24 hours - $interval = DateInterval::createFromDateString('24 hours'); - $before24h = (new DateTime())->sub($interval); + $dateInterval = DateInterval::createFromDateString('24 hours'); + $before24h = (new DateTime())->sub($dateInterval); $dbForPlatform->foreach( 'projects', From e8e2bb87f609401366ebdc7dd7bf0b8c32590e82 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 10 Jun 2025 16:17:38 +0400 Subject: [PATCH 196/219] chore: update maintenance task to only iterate over active projects --- src/Appwrite/Platform/Tasks/Maintenance.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Appwrite/Platform/Tasks/Maintenance.php b/src/Appwrite/Platform/Tasks/Maintenance.php index 0d7409a936..f266ee34f9 100644 --- a/src/Appwrite/Platform/Tasks/Maintenance.php +++ b/src/Appwrite/Platform/Tasks/Maintenance.php @@ -71,7 +71,6 @@ class Maintenance extends Action $dbForPlatform->foreach( 'projects', function (Document $project) use ($queueForDeletes, $usageStatsRetentionHourly) { - Console::info('Project accessed at ' . $project->getId()); $queueForDeletes ->setType(DELETE_TYPE_MAINTENANCE) ->setProject($project) From a1ff96829db046194607474507f284a09c4bb595 Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal Date: Tue, 10 Jun 2025 12:38:48 +0000 Subject: [PATCH 197/219] chore: update pkgs --- app/config/platforms.php | 13 +++++++++---- composer.lock | 12 ++++++------ src/Appwrite/Platform/Tasks/SDKs.php | 3 ++- 3 files changed, 17 insertions(+), 11 deletions(-) diff --git a/app/config/platforms.php b/app/config/platforms.php index 7d481d508e..f08401e8fa 100644 --- a/app/config/platforms.php +++ b/app/config/platforms.php @@ -59,7 +59,7 @@ return [ [ 'key' => 'flutter', 'name' => 'Flutter', - 'version' => '16.1.0', + 'version' => '17.0.1', 'url' => 'https://github.com/appwrite/sdk-for-flutter', 'package' => 'https://pub.dev/packages/appwrite', 'enabled' => true, @@ -77,7 +77,7 @@ return [ [ 'key' => 'apple', 'name' => 'Apple', - 'version' => '10.1.0', + 'version' => '10.1.1', 'url' => 'https://github.com/appwrite/sdk-for-apple', 'package' => 'https://github.com/appwrite/sdk-for-apple', 'enabled' => true, @@ -217,7 +217,7 @@ return [ [ 'key' => 'cli', 'name' => 'Command Line', - 'version' => '7.0.0', + 'version' => '8.0.0', 'url' => 'https://github.com/appwrite/sdk-for-cli', 'package' => 'https://www.npmjs.com/package/appwrite-cli', 'enabled' => true, @@ -231,6 +231,11 @@ return [ 'gitRepoName' => 'sdk-for-cli', 'gitUserName' => 'appwrite', 'gitBranch' => 'dev', + 'exclude' => [ + 'services' => [ + ['name' => 'assistant'], + ], + ], ], ], ], @@ -411,7 +416,7 @@ return [ [ 'key' => 'swift', 'name' => 'Swift', - 'version' => '10.0.0', + 'version' => '10.1.0', 'url' => 'https://github.com/appwrite/sdk-for-swift', 'package' => 'https://github.com/appwrite/sdk-for-swift', 'enabled' => true, diff --git a/composer.lock b/composer.lock index d7b9f22722..da740d8c72 100644 --- a/composer.lock +++ b/composer.lock @@ -4807,16 +4807,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.41.1", + "version": "0.41.4", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "6d9318abf4542a757c87abf056557d6afa1dc06b" + "reference": "07804269131f411576aac60c795a5ebc3afaa48a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/6d9318abf4542a757c87abf056557d6afa1dc06b", - "reference": "6d9318abf4542a757c87abf056557d6afa1dc06b", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/07804269131f411576aac60c795a5ebc3afaa48a", + "reference": "07804269131f411576aac60c795a5ebc3afaa48a", "shasum": "" }, "require": { @@ -4852,9 +4852,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.41.1" + "source": "https://github.com/appwrite/sdk-generator/tree/0.41.4" }, - "time": "2025-06-01T04:20:04+00:00" + "time": "2025-06-10T08:28:11+00:00" }, { "name": "doctrine/annotations", diff --git a/src/Appwrite/Platform/Tasks/SDKs.php b/src/Appwrite/Platform/Tasks/SDKs.php index a0009fd59f..25e8726319 100644 --- a/src/Appwrite/Platform/Tasks/SDKs.php +++ b/src/Appwrite/Platform/Tasks/SDKs.php @@ -251,7 +251,8 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ->setDiscord(APP_SOCIAL_DISCORD_CHANNEL, APP_SOCIAL_DISCORD) ->setDefaultHeaders([ 'X-Appwrite-Response-Format' => '1.7.0', - ]); + ]) + ->setExclude($language['exclude'] ?? []); // Make sure we have a clean slate. // Otherwise, all files in this dir will be pushed, From 261adac306c078b087f3fb6675aa998b8fe812f5 Mon Sep 17 00:00:00 2001 From: Christy Jacob Date: Tue, 10 Jun 2025 16:40:02 +0400 Subject: [PATCH 198/219] chore: linter --- src/Appwrite/Platform/Tasks/Maintenance.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/Maintenance.php b/src/Appwrite/Platform/Tasks/Maintenance.php index f266ee34f9..47f9262006 100644 --- a/src/Appwrite/Platform/Tasks/Maintenance.php +++ b/src/Appwrite/Platform/Tasks/Maintenance.php @@ -2,10 +2,10 @@ namespace Appwrite\Platform\Tasks; -use DateInterval; -use DateTime; use Appwrite\Event\Certificate; use Appwrite\Event\Delete; +use DateInterval; +use DateTime; use Utopia\CLI\Console; use Utopia\Database\Database; use Utopia\Database\DateTime as DatabaseDateTime; From e1a291ff2114ba1146c8735a05bfca871d06ef82 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 10 Jun 2025 11:50:57 -0400 Subject: [PATCH 199/219] Consistent messages --- app/controllers/api/databases.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 85fae8ea35..098361651f 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -4523,9 +4523,9 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum } catch (NotFoundException) { throw new Exception(Exception::ATTRIBUTE_NOT_FOUND); } catch (LimitException) { - throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute `' . $attribute . '` has reached the maximum value of ' . $max); + throw new Exception(Exception::ATTRIBUTE_LIMIT_EXCEEDED, 'Attribute "' . $attribute . '" has reached the maximum value of ' . $max); } catch (TypeException) { - throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, 'Attribute `' . $attribute . '` is not a number'); + throw new Exception(Exception::ATTRIBUTE_TYPE_INVALID, 'Attribute "' . $attribute . '" is not a number'); } $queueForStatsUsage From ffb27284e5b998f34258eb1e9ec9b3ce08b2a846 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 10 Jun 2025 11:51:17 -0400 Subject: [PATCH 200/219] Type as integer in query base --- composer.lock | 36 +++++++++---------- .../Database/Validator/Queries/Base.php | 11 +++--- 2 files changed, 23 insertions(+), 24 deletions(-) diff --git a/composer.lock b/composer.lock index 0ce712ea30..6372df41ba 100644 --- a/composer.lock +++ b/composer.lock @@ -3490,16 +3490,16 @@ }, { "name": "utopia-php/database", - "version": "0.71.3", + "version": "0.71.4", "source": { "type": "git", "url": "https://github.com/utopia-php/database.git", - "reference": "f0c28b78548e2b740d940ca17dca30e1e532d53c" + "reference": "308cbeb65780f954f9f3abfff2ef17c5941ae00e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/database/zipball/f0c28b78548e2b740d940ca17dca30e1e532d53c", - "reference": "f0c28b78548e2b740d940ca17dca30e1e532d53c", + "url": "https://api.github.com/repos/utopia-php/database/zipball/308cbeb65780f954f9f3abfff2ef17c5941ae00e", + "reference": "308cbeb65780f954f9f3abfff2ef17c5941ae00e", "shasum": "" }, "require": { @@ -3540,9 +3540,9 @@ ], "support": { "issues": "https://github.com/utopia-php/database/issues", - "source": "https://github.com/utopia-php/database/tree/0.71.3" + "source": "https://github.com/utopia-php/database/tree/0.71.4" }, - "time": "2025-06-10T03:53:35+00:00" + "time": "2025-06-10T15:47:50+00:00" }, { "name": "utopia-php/detector", @@ -4584,16 +4584,16 @@ }, { "name": "utopia-php/vcs", - "version": "0.10.4", + "version": "0.10.5", "source": { "type": "git", "url": "https://github.com/utopia-php/vcs.git", - "reference": "f635b368909eb3c3fe57344fe43525e74e8fdc03" + "reference": "b358439dc387f6097019eb83ebb9fc258fe9da05" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/utopia-php/vcs/zipball/f635b368909eb3c3fe57344fe43525e74e8fdc03", - "reference": "f635b368909eb3c3fe57344fe43525e74e8fdc03", + "url": "https://api.github.com/repos/utopia-php/vcs/zipball/b358439dc387f6097019eb83ebb9fc258fe9da05", + "reference": "b358439dc387f6097019eb83ebb9fc258fe9da05", "shasum": "" }, "require": { @@ -4627,9 +4627,9 @@ ], "support": { "issues": "https://github.com/utopia-php/vcs/issues", - "source": "https://github.com/utopia-php/vcs/tree/0.10.4" + "source": "https://github.com/utopia-php/vcs/tree/0.10.5" }, - "time": "2025-06-02T09:18:36+00:00" + "time": "2025-06-10T15:01:16+00:00" }, { "name": "utopia-php/websocket", @@ -4807,16 +4807,16 @@ "packages-dev": [ { "name": "appwrite/sdk-generator", - "version": "0.41.2", + "version": "0.41.4", "source": { "type": "git", "url": "https://github.com/appwrite/sdk-generator.git", - "reference": "e9a324efef9080808e07a782be2420cd4454cff7" + "reference": "07804269131f411576aac60c795a5ebc3afaa48a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/e9a324efef9080808e07a782be2420cd4454cff7", - "reference": "e9a324efef9080808e07a782be2420cd4454cff7", + "url": "https://api.github.com/repos/appwrite/sdk-generator/zipball/07804269131f411576aac60c795a5ebc3afaa48a", + "reference": "07804269131f411576aac60c795a5ebc3afaa48a", "shasum": "" }, "require": { @@ -4852,9 +4852,9 @@ "description": "Appwrite PHP library for generating API SDKs for multiple programming languages and platforms", "support": { "issues": "https://github.com/appwrite/sdk-generator/issues", - "source": "https://github.com/appwrite/sdk-generator/tree/0.41.2" + "source": "https://github.com/appwrite/sdk-generator/tree/0.41.4" }, - "time": "2025-06-10T03:08:44+00:00" + "time": "2025-06-10T08:28:11+00:00" }, { "name": "doctrine/annotations", diff --git a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php index 20e7d5cb93..1c5dec44dd 100644 --- a/src/Appwrite/Utopia/Database/Validator/Queries/Base.php +++ b/src/Appwrite/Utopia/Database/Validator/Queries/Base.php @@ -25,7 +25,7 @@ class Base extends Queries { $config = Config::getParam('collections', []); - $collections = array_merge( + $collections = \array_merge( $config['projects'], $config['buckets'], $config['databases'], @@ -34,7 +34,7 @@ class Base extends Queries ); $collection = $collections[$collection]; - // array for constant lookup time + $allowedAttributesLookup = []; foreach ($allowedAttributes as $attribute) { $allowedAttributesLookup[$attribute] = true; @@ -70,10 +70,9 @@ class Base extends Queries 'type' => Database::VAR_DATETIME, 'array' => false, ]); - - $sequence = new Document([ + $attributes[] = new Document([ 'key' => '$sequence', - 'type' => Database::VAR_STRING, + 'type' => Database::VAR_INTEGER, 'array' => false, ]); @@ -82,7 +81,7 @@ class Base extends Queries new Offset(), new Cursor(), new Filter($attributes, APP_DATABASE_QUERY_MAX_VALUES), - new Order([...$attributes, $sequence]), + new Order($attributes), ]; parent::__construct($validators); From 8c6f0a4e7b79a4dad072b484dd7ceae5d981d5d6 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 10 Jun 2025 13:42:41 -0400 Subject: [PATCH 201/219] Fix merge --- app/controllers/api/storage.php | 78 ++++++++++++++++----------------- 1 file changed, 39 insertions(+), 39 deletions(-) diff --git a/app/controllers/api/storage.php b/app/controllers/api/storage.php index a25241ec4b..26c789ce27 100644 --- a/app/controllers/api/storage.php +++ b/app/controllers/api/storage.php @@ -316,15 +316,15 @@ App::put('/v1/storage/buckets/:bucketId') $permissions = Permission::aggregate($permissions); $bucket = $dbForProject->updateDocument('buckets', $bucket->getId(), $bucket - ->setAttribute('name', $name) - ->setAttribute('$permissions', $permissions) - ->setAttribute('maximumFileSize', $maximumFileSize) - ->setAttribute('allowedFileExtensions', $allowedFileExtensions) - ->setAttribute('fileSecurity', $fileSecurity) - ->setAttribute('enabled', $enabled) - ->setAttribute('encryption', $encryption) - ->setAttribute('compression', $compression) - ->setAttribute('antivirus', $antivirus)); + ->setAttribute('name', $name) + ->setAttribute('$permissions', $permissions) + ->setAttribute('maximumFileSize', $maximumFileSize) + ->setAttribute('allowedFileExtensions', $allowedFileExtensions) + ->setAttribute('fileSecurity', $fileSecurity) + ->setAttribute('enabled', $enabled) + ->setAttribute('encryption', $encryption) + ->setAttribute('compression', $compression) + ->setAttribute('antivirus', $antivirus)); $dbForProject->updateCollection('bucket_' . $bucket->getSequence(), $permissions, $fileSecurity); @@ -1004,7 +1004,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/preview') $algorithm = $file->getAttribute('algorithm', Compression::NONE); $cipher = $file->getAttribute('openSSLCipher'); $mime = $file->getAttribute('mimeType'); - if (!\in_array($mime, $inputs) || $file->getAttribute('sizeActual') > (int) System::getEnv('_APP_STORAGE_PREVIEW_LIMIT', 20000000)) { + if (!\in_array($mime, $inputs) || $file->getAttribute('sizeActual') > (int) System::getEnv('_APP_STORAGE_PREVIEW_LIMIT', APP_STORAGE_READ_BUFFER)) { if (!\in_array($mime, $inputs)) { $path = (\array_key_exists($mime, $fileLogos)) ? $fileLogos[$mime] : $fileLogos['default']; } else { @@ -1178,13 +1178,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') throw new Exception(Exception::STORAGE_FILE_NOT_FOUND, 'File not found in ' . $path); } - $response - ->setContentType($file->getAttribute('mimeType')) - ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days - ->addHeader('X-Peak', \memory_get_peak_usage()) - ->addHeader('Content-Disposition', 'attachment; filename="' . $file->getAttribute('name', '') . '"') - ; - $size = $file->getAttribute('sizeOriginal', 0); $rangeHeader = $request->getHeader('range'); @@ -1193,7 +1186,7 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') $end = $request->getRangeEnd(); $unit = $request->getRangeUnit(); - if ($end === null) { + if ($end === null || $end - $start > APP_STORAGE_READ_BUFFER) { $end = min(($start + MAX_OUTPUT_CHUNK_SIZE - 1), ($size - 1)); } @@ -1208,6 +1201,13 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/download') ->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT); } + $response + ->setContentType($file->getAttribute('mimeType')) + ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days + ->addHeader('X-Peak', \memory_get_peak_usage()) + ->addHeader('Content-Disposition', 'attachment; filename="' . $file->getAttribute('name', '') . '"') + ; + $source = ''; if (!empty($file->getAttribute('openSSLCipher'))) { // Decrypt $source = $deviceForFiles->read($path); @@ -1345,15 +1345,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') $contentType = $file->getAttribute('mimeType'); } - $response - ->setContentType($contentType) - ->addHeader('Content-Security-Policy', 'script-src none;') - ->addHeader('X-Content-Type-Options', 'nosniff') - ->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"') - ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days - ->addHeader('X-Peak', \memory_get_peak_usage()) - ; - $size = $file->getAttribute('sizeOriginal', 0); $rangeHeader = $request->getHeader('range'); @@ -1362,8 +1353,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') $end = $request->getRangeEnd(); $unit = $request->getRangeUnit(); - if ($end === null) { - $end = min(($start + 2000000 - 1), ($size - 1)); + if ($end === null || $end - $start > APP_STORAGE_READ_BUFFER) { + $end = min(($start + APP_STORAGE_READ_BUFFER - 1), ($size - 1)); } if ($unit != 'bytes' || $start >= $end || $end >= $size) { @@ -1377,6 +1368,15 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/view') ->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT); } + $response + ->setContentType($contentType) + ->addHeader('Content-Security-Policy', 'script-src none;') + ->addHeader('X-Content-Type-Options', 'nosniff') + ->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"') + ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days + ->addHeader('X-Peak', \memory_get_peak_usage()) + ; + $source = ''; if (!empty($file->getAttribute('openSSLCipher'))) { // Decrypt $source = $deviceForFiles->read($path); @@ -1498,14 +1498,6 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') $contentType = $file->getAttribute('mimeType'); } - $response - ->setContentType($contentType) - ->addHeader('Content-Security-Policy', 'script-src none;') - ->addHeader('X-Content-Type-Options', 'nosniff') - ->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"') - ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days - ->addHeader('X-Peak', \memory_get_peak_usage()); - $size = $file->getAttribute('sizeOriginal', 0); $rangeHeader = $request->getHeader('range'); @@ -1514,8 +1506,8 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') $end = $request->getRangeEnd(); $unit = $request->getRangeUnit(); - if ($end === null) { - $end = min(($start + 2000000 - 1), ($size - 1)); + if ($end === null || $end - $start > APP_STORAGE_READ_BUFFER) { + $end = min(($start + APP_STORAGE_READ_BUFFER - 1), ($size - 1)); } if ($unit != 'bytes' || $start >= $end || $end >= $size) { @@ -1529,6 +1521,14 @@ App::get('/v1/storage/buckets/:bucketId/files/:fileId/push') ->setStatusCode(Response::STATUS_CODE_PARTIALCONTENT); } + $response + ->setContentType($contentType) + ->addHeader('Content-Security-Policy', 'script-src none;') + ->addHeader('X-Content-Type-Options', 'nosniff') + ->addHeader('Content-Disposition', 'inline; filename="' . $file->getAttribute('name', '') . '"') + ->addHeader('Cache-Control', 'private, max-age=3888000') // 45 days + ->addHeader('X-Peak', \memory_get_peak_usage()); + $source = ''; if (!empty($file->getAttribute('openSSLCipher'))) { // Decrypt $source = $deviceForFiles->read($path); From a95a651d30a67e0436a8e364c99c79d2a180f8b7 Mon Sep 17 00:00:00 2001 From: Jake Barnby Date: Tue, 10 Jun 2025 14:08:21 -0400 Subject: [PATCH 202/219] Add specs --- app/config/specs/open-api3-1.8.x-client.json | 10113 ++++ app/config/specs/open-api3-1.8.x-console.json | 44048 +++++++++++++++ app/config/specs/open-api3-1.8.x-server.json | 30573 +++++++++++ app/config/specs/open-api3-latest-client.json | 312 +- .../specs/open-api3-latest-console.json | 886 +- app/config/specs/open-api3-latest-server.json | 678 +- app/config/specs/swagger2-1.8.x-client.json | 10171 ++++ app/config/specs/swagger2-1.8.x-console.json | 44331 ++++++++++++++++ app/config/specs/swagger2-1.8.x-server.json | 30820 +++++++++++ app/config/specs/swagger2-latest-client.json | 300 +- app/config/specs/swagger2-latest-console.json | 874 +- app/config/specs/swagger2-latest-server.json | 666 +- 12 files changed, 172636 insertions(+), 1136 deletions(-) create mode 100644 app/config/specs/open-api3-1.8.x-client.json create mode 100644 app/config/specs/open-api3-1.8.x-console.json create mode 100644 app/config/specs/open-api3-1.8.x-server.json create mode 100644 app/config/specs/swagger2-1.8.x-client.json create mode 100644 app/config/specs/swagger2-1.8.x-console.json create mode 100644 app/config/specs/swagger2-1.8.x-server.json diff --git a/app/config/specs/open-api3-1.8.x-client.json b/app/config/specs/open-api3-1.8.x-client.json new file mode 100644 index 0000000000..fd2752e337 --- /dev/null +++ b/app/config/specs/open-api3-1.8.x-client.json @@ -0,0 +1,10113 @@ +{ + "openapi": "3.0.0", + "info": { + "version": "1.7.4", + "title": "Appwrite", + "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", + "termsOfService": "https:\/\/appwrite.io\/policy\/terms", + "contact": { + "name": "Appwrite Team", + "url": "https:\/\/appwrite.io\/support", + "email": "team@appwrite.io" + }, + "license": { + "name": "BSD-3-Clause", + "url": "https:\/\/raw.githubusercontent.com\/appwrite\/appwrite\/master\/LICENSE" + } + }, + "servers": [ + { + "url": "https:\/\/cloud.appwrite.io\/v1" + }, + { + "url": "https:\/\/.cloud.appwrite.io\/v1" + } + ], + "paths": { + "\/account": { + "get": { + "summary": "Get account", + "operationId": "accountGet", + "tags": [ + "account" + ], + "description": "Get the currently logged in user.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": "account", + "weight": 10, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "post": { + "summary": "Create account", + "operationId": "accountCreate", + "tags": [ + "account" + ], + "description": "Use this endpoint to allow a new user to register a new account in your project. After the user registration completes successfully, you can use the [\/account\/verfication](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createVerification) route to start verifying the user email address. To allow the new user to login to their new account, you need to create a new [account session](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createEmailSession).", + "responses": { + "201": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "create", + "group": "account", + "weight": 9, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "New user password. Must be between 8 and 256 chars.", + "x-example": null + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + } + } + } + }, + "\/account\/email": { + "patch": { + "summary": "Update email", + "operationId": "accountUpdateEmail", + "tags": [ + "account" + ], + "description": "Update currently logged in user account email address. After changing user address, the user confirmation status will get reset. A new confirmation email is not sent automatically however you can use the send confirmation email endpoint again to send the confirmation email. For security measures, user password is required to complete this request.\nThis endpoint can also be used to convert an anonymous account to a normal one, by passing an email address and a new password.\n", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateEmail", + "group": "account", + "weight": 35, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-email.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password. Must be at least 8 chars.", + "x-example": "password" + } + }, + "required": [ + "email", + "password" + ] + } + } + } + } + } + }, + "\/account\/identities": { + "get": { + "summary": "List identities", + "operationId": "accountListIdentities", + "tags": [ + "account" + ], + "description": "Get the list of identities for the currently logged in user.", + "responses": { + "200": { + "description": "Identities List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/identityList" + } + } + } + } + }, + "x-appwrite": { + "method": "listIdentities", + "group": "identities", + "weight": 58, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-identities.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-identities.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, provider, providerUid, providerEmail, providerAccessTokenExpiry", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/account\/identities\/{identityId}": { + "delete": { + "summary": "Delete identity", + "operationId": "accountDeleteIdentity", + "tags": [ + "account" + ], + "description": "Delete an identity by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteIdentity", + "group": "identities", + "weight": 59, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-identity.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-identity.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "identityId", + "description": "Identity ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/account\/jwts": { + "post": { + "summary": "Create JWT", + "operationId": "accountCreateJWT", + "tags": [ + "account" + ], + "description": "Use this endpoint to create a JSON Web Token. You can use the resulting JWT to authenticate on behalf of the current user when working with the Appwrite server-side API and SDKs. The JWT secret is valid for 15 minutes from its creation and will be invalid if the user will logout in that time frame.", + "responses": { + "201": { + "description": "JWT", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/jwt" + } + } + } + } + }, + "x-appwrite": { + "method": "createJWT", + "group": "tokens", + "weight": 30, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-j-w-t.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-jwt.md", + "rate-limit": 100, + "rate-time": 3600, + "rate-key": "url:{url},userId:{userId}", + "scope": "account", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ] + } + }, + "\/account\/logs": { + "get": { + "summary": "List logs", + "operationId": "accountListLogs", + "tags": [ + "account" + ], + "description": "Get the list of latest security activity logs for the currently logged in user. Each log returns user IP address, location and date and time of log.", + "responses": { + "200": { + "description": "Logs List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/logList" + } + } + } + } + }, + "x-appwrite": { + "method": "listLogs", + "group": "logs", + "weight": 32, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/account\/mfa": { + "patch": { + "summary": "Update MFA", + "operationId": "accountUpdateMFA", + "tags": [ + "account" + ], + "description": "Enable or disable MFA on an account.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMFA", + "group": "mfa", + "weight": 45, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-m-f-a.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "mfa": { + "type": "boolean", + "description": "Enable or disable MFA.", + "x-example": false + } + }, + "required": [ + "mfa" + ] + } + } + } + } + } + }, + "\/account\/mfa\/authenticators\/{type}": { + "post": { + "summary": "Create authenticator", + "operationId": "accountCreateMfaAuthenticator", + "tags": [ + "account" + ], + "description": "Add an authenticator app to be used as an MFA factor. Verify the authenticator using the [verify authenticator](\/docs\/references\/cloud\/client-web\/account#updateMfaAuthenticator) method.", + "responses": { + "200": { + "description": "MFAType", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaType" + } + } + } + } + }, + "x-appwrite": { + "method": "createMfaAuthenticator", + "group": "mfa", + "weight": 47, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "type", + "description": "Type of authenticator. Must be `totp`", + "required": true, + "schema": { + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [] + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update authenticator (confirmation)", + "operationId": "accountUpdateMfaAuthenticator", + "tags": [ + "account" + ], + "description": "Verify an authenticator app after adding it using the [add authenticator](\/docs\/references\/cloud\/client-web\/account#createMfaAuthenticator) method.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMfaAuthenticator", + "group": "mfa", + "weight": 48, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "type", + "description": "Type of authenticator.", + "required": true, + "schema": { + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [] + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "otp": { + "type": "string", + "description": "Valid verification token.", + "x-example": "" + } + }, + "required": [ + "otp" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete authenticator", + "operationId": "accountDeleteMfaAuthenticator", + "tags": [ + "account" + ], + "description": "Delete an authenticator for a user by ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteMfaAuthenticator", + "group": "mfa", + "weight": 52, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "type", + "description": "Type of authenticator.", + "required": true, + "schema": { + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [] + }, + "in": "path" + } + ] + } + }, + "\/account\/mfa\/challenge": { + "post": { + "summary": "Create MFA challenge", + "operationId": "accountCreateMfaChallenge", + "tags": [ + "account" + ], + "description": "Begin the process of MFA verification after sign-in. Finish the flow with [updateMfaChallenge](\/docs\/references\/cloud\/client-web\/account#updateMfaChallenge) method.", + "responses": { + "201": { + "description": "MFA Challenge", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaChallenge" + } + } + } + } + }, + "x-appwrite": { + "method": "createMfaChallenge", + "group": "mfa", + "weight": 53, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-mfa-challenge.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-mfa-challenge.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{userId}", + "scope": "account", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "factor": { + "type": "string", + "description": "Factor used for verification. Must be one of following: `email`, `phone`, `totp`, `recoveryCode`.", + "x-example": "email", + "enum": [ + "email", + "phone", + "totp", + "recoverycode" + ], + "x-enum-name": "AuthenticationFactor", + "x-enum-keys": [] + } + }, + "required": [ + "factor" + ] + } + } + } + } + }, + "put": { + "summary": "Update MFA challenge (confirmation)", + "operationId": "accountUpdateMfaChallenge", + "tags": [ + "account" + ], + "description": "Complete the MFA challenge by providing the one-time password. Finish the process of MFA verification by providing the one-time password. To begin the flow, use [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method.", + "responses": { + "200": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMfaChallenge", + "group": "mfa", + "weight": 54, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-mfa-challenge.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa-challenge.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},challengeId:{param-challengeId}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "challengeId": { + "type": "string", + "description": "ID of the challenge.", + "x-example": "" + }, + "otp": { + "type": "string", + "description": "Valid verification token.", + "x-example": "" + } + }, + "required": [ + "challengeId", + "otp" + ] + } + } + } + } + } + }, + "\/account\/mfa\/factors": { + "get": { + "summary": "List factors", + "operationId": "accountListMfaFactors", + "tags": [ + "account" + ], + "description": "List the factors available on the account to be used as a MFA challange.", + "responses": { + "200": { + "description": "MFAFactors", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaFactors" + } + } + } + } + }, + "x-appwrite": { + "method": "listMfaFactors", + "group": "mfa", + "weight": 46, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-mfa-factors.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-mfa-factors.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/account\/mfa\/recovery-codes": { + "get": { + "summary": "List MFA recovery codes", + "operationId": "accountGetMfaRecoveryCodes", + "tags": [ + "account" + ], + "description": "Get recovery codes that can be used as backup for MFA flow. Before getting codes, they must be generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method. An OTP challenge is required to read recovery codes.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaRecoveryCodes" + } + } + } + } + }, + "x-appwrite": { + "method": "getMfaRecoveryCodes", + "group": "mfa", + "weight": 51, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "post": { + "summary": "Create MFA recovery codes", + "operationId": "accountCreateMfaRecoveryCodes", + "tags": [ + "account" + ], + "description": "Generate recovery codes as backup for MFA flow. It's recommended to generate and show then immediately after user successfully adds their authehticator. Recovery codes can be used as a MFA verification type in [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method.", + "responses": { + "201": { + "description": "MFA Recovery Codes", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaRecoveryCodes" + } + } + } + } + }, + "x-appwrite": { + "method": "createMfaRecoveryCodes", + "group": "mfa", + "weight": 49, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "patch": { + "summary": "Update MFA recovery codes (regenerate)", + "operationId": "accountUpdateMfaRecoveryCodes", + "tags": [ + "account" + ], + "description": "Regenerate recovery codes that can be used as backup for MFA flow. Before regenerating codes, they must be first generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method. An OTP challenge is required to regenreate recovery codes.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaRecoveryCodes" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMfaRecoveryCodes", + "group": "mfa", + "weight": 50, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/account\/name": { + "patch": { + "summary": "Update name", + "operationId": "accountUpdateName", + "tags": [ + "account" + ], + "description": "Update currently logged in user account name.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateName", + "group": "account", + "weight": 33, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-name.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-name.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "" + } + }, + "required": [ + "name" + ] + } + } + } + } + } + }, + "\/account\/password": { + "patch": { + "summary": "Update password", + "operationId": "accountUpdatePassword", + "tags": [ + "account" + ], + "description": "Update currently logged in user password. For validation, user is required to pass in the new password, and the old password. For users created with OAuth, Team Invites and Magic URL, oldPassword is optional.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePassword", + "group": "account", + "weight": 34, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-password.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-password.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "password": { + "type": "string", + "description": "New user password. Must be at least 8 chars.", + "x-example": null + }, + "oldPassword": { + "type": "string", + "description": "Current user password. Must be at least 8 chars.", + "x-example": "password" + } + }, + "required": [ + "password" + ] + } + } + } + } + } + }, + "\/account\/phone": { + "patch": { + "summary": "Update phone", + "operationId": "accountUpdatePhone", + "tags": [ + "account" + ], + "description": "Update the currently logged in user's phone number. After updating the phone number, the phone verification status will be reset. A confirmation SMS is not sent automatically, however you can use the [POST \/account\/verification\/phone](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createPhoneVerification) endpoint to send a confirmation SMS.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePhone", + "group": "account", + "weight": 36, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-phone.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-phone.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "x-example": "+12065550100" + }, + "password": { + "type": "string", + "description": "User password. Must be at least 8 chars.", + "x-example": "password" + } + }, + "required": [ + "phone", + "password" + ] + } + } + } + } + } + }, + "\/account\/prefs": { + "get": { + "summary": "Get account preferences", + "operationId": "accountGetPrefs", + "tags": [ + "account" + ], + "description": "Get the preferences as a key-value object for the currently logged in user.", + "responses": { + "200": { + "description": "Preferences", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/preferences" + } + } + } + } + }, + "x-appwrite": { + "method": "getPrefs", + "group": "account", + "weight": 31, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "patch": { + "summary": "Update preferences", + "operationId": "accountUpdatePrefs", + "tags": [ + "account" + ], + "description": "Update currently logged in user account preferences. The object you pass is stored as is, and replaces any previous value. The maximum allowed prefs size is 64kB and throws error if exceeded.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePrefs", + "group": "account", + "weight": 37, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "prefs": { + "type": "object", + "description": "Prefs key-value JSON object.", + "x-example": "{}" + } + }, + "required": [ + "prefs" + ] + } + } + } + } + } + }, + "\/account\/recovery": { + "post": { + "summary": "Create password recovery", + "operationId": "accountCreateRecovery", + "tags": [ + "account" + ], + "description": "Sends the user an email with a temporary secret key for password reset. When the user clicks the confirmation link he is redirected back to your app password reset URL with the secret key and email address values attached to the URL query string. Use the query string params to submit a request to the [PUT \/account\/recovery](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updateRecovery) endpoint to complete the process. The verification link sent to the user's email address is valid for 1 hour.", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createRecovery", + "group": "recovery", + "weight": 39, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-recovery.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-recovery.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},email:{param-email}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "x-example": "https:\/\/example.com" + } + }, + "required": [ + "email", + "url" + ] + } + } + } + } + }, + "put": { + "summary": "Update password recovery (confirmation)", + "operationId": "accountUpdateRecovery", + "tags": [ + "account" + ], + "description": "Use this endpoint to complete the user account password reset. Both the **userId** and **secret** arguments will be passed as query parameters to the redirect URL you have provided when sending your request to the [POST \/account\/recovery](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createRecovery) endpoint.\n\nPlease note that in order to avoid a [Redirect Attack](https:\/\/github.com\/OWASP\/CheatSheetSeries\/blob\/master\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) the only valid redirect URLs are the ones from domains you have set when adding your platforms in the console interface.", + "responses": { + "200": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "updateRecovery", + "group": "recovery", + "weight": 40, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-recovery.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-recovery.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "" + }, + "secret": { + "type": "string", + "description": "Valid reset token.", + "x-example": "" + }, + "password": { + "type": "string", + "description": "New user password. Must be between 8 and 256 chars.", + "x-example": null + } + }, + "required": [ + "userId", + "secret", + "password" + ] + } + } + } + } + } + }, + "\/account\/sessions": { + "get": { + "summary": "List sessions", + "operationId": "accountListSessions", + "tags": [ + "account" + ], + "description": "Get the list of active sessions across different devices for the currently logged in user.", + "responses": { + "200": { + "description": "Sessions List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/sessionList" + } + } + } + } + }, + "x-appwrite": { + "method": "listSessions", + "group": "sessions", + "weight": 12, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-sessions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "delete": { + "summary": "Delete sessions", + "operationId": "accountDeleteSessions", + "tags": [ + "account" + ], + "description": "Delete all sessions from the user account and remove any sessions cookies from the end client.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSessions", + "group": "sessions", + "weight": 13, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-sessions.md", + "rate-limit": 100, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/account\/sessions\/anonymous": { + "post": { + "summary": "Create anonymous session", + "operationId": "accountCreateAnonymousSession", + "tags": [ + "account" + ], + "description": "Use this endpoint to allow a new user to register an anonymous account in your project. This route will also create a new session for the user. To allow the new user to convert an anonymous account to a normal account, you need to update its [email and password](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updateEmail) or create an [OAuth2 session](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#CreateOAuth2Session).", + "responses": { + "201": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "createAnonymousSession", + "group": "sessions", + "weight": 18, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-anonymous-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session-anonymous.md", + "rate-limit": 50, + "rate-time": 3600, + "rate-key": "ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ] + } + }, + "\/account\/sessions\/email": { + "post": { + "summary": "Create email password session", + "operationId": "accountCreateEmailPasswordSession", + "tags": [ + "account" + ], + "description": "Allow the user to login into their account by providing a valid email and password combination. This route will create a new session for the user.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "201": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "createEmailPasswordSession", + "group": "sessions", + "weight": 17, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-email-password-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session-email-password.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},email:{param-email}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password. Must be at least 8 chars.", + "x-example": "password" + } + }, + "required": [ + "email", + "password" + ] + } + } + } + } + } + }, + "\/account\/sessions\/magic-url": { + "put": { + "summary": "Update magic URL session", + "operationId": "accountUpdateMagicURLSession", + "tags": [ + "account" + ], + "description": "Use this endpoint to create a session from token. Provide the **userId** and **secret** parameters from the successful response of authentication flows initiated by token creation. For example, magic URL and phone login.", + "responses": { + "201": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMagicURLSession", + "group": "sessions", + "weight": 27, + "cookies": false, + "type": "", + "deprecated": true, + "demo": "account\/update-magic-u-r-l-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "ip:{ip},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "x-example": "" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + } + } + } + }, + "\/account\/sessions\/oauth2\/{provider}": { + "get": { + "summary": "Create OAuth2 session", + "operationId": "accountCreateOAuth2Session", + "tags": [ + "account" + ], + "description": "Allow the user to login to their account using the OAuth2 provider of their choice. Each OAuth2 provider should be enabled from the Appwrite console first. Use the success and failure arguments to provide a redirect URL's back to your app when login is completed.\n\nIf there is already an active session, the new session will be attached to the logged-in account. If there are no active sessions, the server will attempt to look for a user with the same email address as the email received from the OAuth2 provider and attach the new session to the existing user. If no matching user is found - the server will create a new user.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "responses": { + "301": { + "description": "File" + } + }, + "x-appwrite": { + "method": "createOAuth2Session", + "group": "sessions", + "weight": 20, + "cookies": false, + "type": "webAuth", + "deprecated": false, + "demo": "account\/create-o-auth2session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session-oauth2.md", + "rate-limit": 50, + "rate-time": 3600, + "rate-key": "ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "provider", + "description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.", + "required": true, + "schema": { + "type": "string", + "x-example": "amazon", + "enum": [ + "amazon", + "apple", + "auth0", + "authentik", + "autodesk", + "bitbucket", + "bitly", + "box", + "dailymotion", + "discord", + "disqus", + "dropbox", + "etsy", + "facebook", + "figma", + "github", + "gitlab", + "google", + "linkedin", + "microsoft", + "notion", + "oidc", + "okta", + "paypal", + "paypalSandbox", + "podio", + "salesforce", + "slack", + "spotify", + "stripe", + "tradeshift", + "tradeshiftBox", + "twitch", + "wordpress", + "yahoo", + "yammer", + "yandex", + "zoho", + "zoom", + "mock" + ], + "x-enum-name": "OAuthProvider", + "x-enum-keys": [] + }, + "in": "path" + }, + { + "name": "success", + "description": "URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "schema": { + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "" + }, + "in": "query" + }, + { + "name": "failure", + "description": "URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "schema": { + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "" + }, + "in": "query" + }, + { + "name": "scopes", + "description": "A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of 100 scopes are allowed, each 4096 characters long.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/account\/sessions\/phone": { + "put": { + "summary": "Update phone session", + "operationId": "accountUpdatePhoneSession", + "tags": [ + "account" + ], + "description": "Use this endpoint to create a session from token. Provide the **userId** and **secret** parameters from the successful response of authentication flows initiated by token creation. For example, magic URL and phone login.", + "responses": { + "201": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePhoneSession", + "group": "sessions", + "weight": 28, + "cookies": false, + "type": "", + "deprecated": true, + "demo": "account\/update-phone-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "ip:{ip},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "x-example": "" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + } + } + } + }, + "\/account\/sessions\/token": { + "post": { + "summary": "Create session", + "operationId": "accountCreateSession", + "tags": [ + "account" + ], + "description": "Use this endpoint to create a session from token. Provide the **userId** and **secret** parameters from the successful response of authentication flows initiated by token creation. For example, magic URL and phone login.", + "responses": { + "201": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "createSession", + "group": "sessions", + "weight": 19, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "ip:{ip},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "secret": { + "type": "string", + "description": "Secret of a token generated by login methods. For example, the `createMagicURLToken` or `createPhoneToken` methods.", + "x-example": "" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + } + } + } + }, + "\/account\/sessions\/{sessionId}": { + "get": { + "summary": "Get session", + "operationId": "accountGetSession", + "tags": [ + "account" + ], + "description": "Use this endpoint to get a logged in user's session using a Session ID. Inputting 'current' will return the current session being used.", + "responses": { + "200": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "getSession", + "group": "sessions", + "weight": 14, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get-session.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "description": "Session ID. Use the string 'current' to get the current device session.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update session", + "operationId": "accountUpdateSession", + "tags": [ + "account" + ], + "description": "Use this endpoint to extend a session's length. Extending a session is useful when session expiry is short. If the session was created using an OAuth provider, this endpoint refreshes the access token from the provider.", + "responses": { + "200": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "updateSession", + "group": "sessions", + "weight": 16, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "description": "Session ID. Use the string 'current' to update the current device session.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete session", + "operationId": "accountDeleteSession", + "tags": [ + "account" + ], + "description": "Logout the user. Use 'current' as the session ID to logout on this device, use a session ID to logout on another device. If you're looking to logout the user on all devices, use [Delete Sessions](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#deleteSessions) instead.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSession", + "group": "sessions", + "weight": 15, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-session.md", + "rate-limit": 100, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "description": "Session ID. Use the string 'current' to delete the current device session.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/account\/status": { + "patch": { + "summary": "Update status", + "operationId": "accountUpdateStatus", + "tags": [ + "account" + ], + "description": "Block the currently logged in user account. Behind the scene, the user record is not deleted but permanently blocked from any access. To completely delete a user, use the Users API instead.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateStatus", + "group": "account", + "weight": 38, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/account\/targets\/push": { + "post": { + "summary": "Create push target", + "operationId": "accountCreatePushTarget", + "tags": [ + "account" + ], + "description": "Use this endpoint to register a device for push notifications. Provide a target ID (custom or generated using ID.unique()), a device identifier (usually a device token), and optionally specify which provider should send notifications to this target. The target is automatically linked to the current session and includes device information like brand and model.", + "responses": { + "201": { + "description": "Target", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/target" + } + } + } + } + }, + "x-appwrite": { + "method": "createPushTarget", + "group": "pushTargets", + "weight": 55, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-push-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-push-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "targetId": { + "type": "string", + "description": "Target ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "identifier": { + "type": "string", + "description": "The target identifier (token, email, phone etc.)", + "x-example": "" + }, + "providerId": { + "type": "string", + "description": "Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.", + "x-example": "" + } + }, + "required": [ + "targetId", + "identifier" + ] + } + } + } + } + } + }, + "\/account\/targets\/{targetId}\/push": { + "put": { + "summary": "Update push target", + "operationId": "accountUpdatePushTarget", + "tags": [ + "account" + ], + "description": "Update the currently logged in user's push notification target. You can modify the target's identifier (device token) and provider ID (token, email, phone etc.). The target must exist and belong to the current user. If you change the provider ID, notifications will be sent through the new messaging provider instead.", + "responses": { + "200": { + "description": "Target", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/target" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePushTarget", + "group": "pushTargets", + "weight": 56, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-push-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-push-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [] + } + ], + "parameters": [ + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "description": "The target identifier (token, email, phone etc.)", + "x-example": "" + } + }, + "required": [ + "identifier" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete push target", + "operationId": "accountDeletePushTarget", + "tags": [ + "account" + ], + "description": "Delete a push notification target for the currently logged in user. After deletion, the device will no longer receive push notifications. The target must exist and belong to the current user.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deletePushTarget", + "group": "pushTargets", + "weight": 57, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-push-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-push-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [] + } + ], + "parameters": [ + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/account\/tokens\/email": { + "post": { + "summary": "Create email token (OTP)", + "operationId": "accountCreateEmailToken", + "tags": [ + "account" + ], + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not be registered, a new user will be created. Use the returned user ID and secret and submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The secret sent to the user's email is valid for 15 minutes.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createEmailToken", + "group": "tokens", + "weight": 26, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-email-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-email.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},email:{param-email}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "phrase": { + "type": "boolean", + "description": "Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.", + "x-example": false + } + }, + "required": [ + "userId", + "email" + ] + } + } + } + } + } + }, + "\/account\/tokens\/magic-url": { + "post": { + "summary": "Create magic URL token", + "operationId": "accountCreateMagicURLToken", + "tags": [ + "account" + ], + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createMagicURLToken", + "group": "tokens", + "weight": 25, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-magic-u-r-l-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-magic-url.md", + "rate-limit": 60, + "rate-time": 3600, + "rate-key": [ + "url:{url},email:{param-email}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "x-example": "https:\/\/example.com" + }, + "phrase": { + "type": "boolean", + "description": "Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.", + "x-example": false + } + }, + "required": [ + "userId", + "email" + ] + } + } + } + } + } + }, + "\/account\/tokens\/oauth2\/{provider}": { + "get": { + "summary": "Create OAuth2 token", + "operationId": "accountCreateOAuth2Token", + "tags": [ + "account" + ], + "description": "Allow the user to login to their account using the OAuth2 provider of their choice. Each OAuth2 provider should be enabled from the Appwrite console first. Use the success and failure arguments to provide a redirect URL's back to your app when login is completed. \n\nIf authentication succeeds, `userId` and `secret` of a token will be appended to the success URL as query parameters. These can be used to create a new session using the [Create session](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "301": { + "description": "File" + } + }, + "x-appwrite": { + "method": "createOAuth2Token", + "group": "tokens", + "weight": 24, + "cookies": false, + "type": "webAuth", + "deprecated": false, + "demo": "account\/create-o-auth2token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-oauth2.md", + "rate-limit": 50, + "rate-time": 3600, + "rate-key": "ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "provider", + "description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.", + "required": true, + "schema": { + "type": "string", + "x-example": "amazon", + "enum": [ + "amazon", + "apple", + "auth0", + "authentik", + "autodesk", + "bitbucket", + "bitly", + "box", + "dailymotion", + "discord", + "disqus", + "dropbox", + "etsy", + "facebook", + "figma", + "github", + "gitlab", + "google", + "linkedin", + "microsoft", + "notion", + "oidc", + "okta", + "paypal", + "paypalSandbox", + "podio", + "salesforce", + "slack", + "spotify", + "stripe", + "tradeshift", + "tradeshiftBox", + "twitch", + "wordpress", + "yahoo", + "yammer", + "yandex", + "zoho", + "zoom", + "mock" + ], + "x-enum-name": "OAuthProvider", + "x-enum-keys": [] + }, + "in": "path" + }, + { + "name": "success", + "description": "URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "schema": { + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "" + }, + "in": "query" + }, + { + "name": "failure", + "description": "URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "schema": { + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "" + }, + "in": "query" + }, + { + "name": "scopes", + "description": "A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of 100 scopes are allowed, each 4096 characters long.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/account\/tokens\/phone": { + "post": { + "summary": "Create phone token", + "operationId": "accountCreatePhoneToken", + "tags": [ + "account" + ], + "description": "Sends the user an SMS with a secret key for creating a session. If the provided user ID has not be registered, a new user will be created. Use the returned user ID and secret and submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The secret sent to the user's phone is valid for 15 minutes.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createPhoneToken", + "group": "tokens", + "weight": 29, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-phone-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-phone.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},phone:{param-phone}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "x-example": "+12065550100" + } + }, + "required": [ + "userId", + "phone" + ] + } + } + } + } + } + }, + "\/account\/verification": { + "post": { + "summary": "Create email verification", + "operationId": "accountCreateVerification", + "tags": [ + "account" + ], + "description": "Use this endpoint to send a verification message to your user email address to confirm they are the valid owners of that address. Both the **userId** and **secret** arguments will be passed as query parameters to the URL you have provided to be attached to the verification email. The provided URL should redirect the user back to your app and allow you to complete the verification process by verifying both the **userId** and **secret** parameters. Learn more about how to [complete the verification process](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updateVerification). The verification link sent to the user's email address is valid for 7 days.\n\nPlease note that in order to avoid a [Redirect Attack](https:\/\/github.com\/OWASP\/CheatSheetSeries\/blob\/master\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md), the only valid redirect URLs are the ones from domains you have set when adding your platforms in the console interface.\n", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createVerification", + "group": "verification", + "weight": 41, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-email-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{userId}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "x-example": "https:\/\/example.com" + } + }, + "required": [ + "url" + ] + } + } + } + } + }, + "put": { + "summary": "Update email verification (confirmation)", + "operationId": "accountUpdateVerification", + "tags": [ + "account" + ], + "description": "Use this endpoint to complete the user email verification process. Use both the **userId** and **secret** parameters that were attached to your app URL to verify the user email ownership. If confirmed this route will return a 200 status code.", + "responses": { + "200": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "updateVerification", + "group": "verification", + "weight": 42, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-email-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{param-userId}", + "scope": "public", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "x-example": "" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + } + } + } + }, + "\/account\/verification\/phone": { + "post": { + "summary": "Create phone verification", + "operationId": "accountCreatePhoneVerification", + "tags": [ + "account" + ], + "description": "Use this endpoint to send a verification SMS to the currently logged in user. This endpoint is meant for use after updating a user's phone number using the [accountUpdatePhone](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updatePhone) endpoint. Learn more about how to [complete the verification process](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updatePhoneVerification). The verification code sent to the user's phone number is valid for 15 minutes.", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createPhoneVerification", + "group": "verification", + "weight": 43, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-phone-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-phone-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},userId:{userId}", + "url:{url},ip:{ip}" + ], + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "put": { + "summary": "Update phone verification (confirmation)", + "operationId": "accountUpdatePhoneVerification", + "tags": [ + "account" + ], + "description": "Use this endpoint to complete the user phone verification process. Use the **userId** and **secret** that were sent to your user's phone number to verify the user email ownership. If confirmed this route will return a 200 status code.", + "responses": { + "200": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePhoneVerification", + "group": "verification", + "weight": 44, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-phone-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-phone-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "userId:{param-userId}", + "scope": "public", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "x-example": "" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + } + } + } + }, + "\/avatars\/browsers\/{code}": { + "get": { + "summary": "Get browser icon", + "operationId": "avatarsGetBrowser", + "tags": [ + "avatars" + ], + "description": "You can use this endpoint to show different browser icons to your users. The code argument receives the browser code as it appears in your user [GET \/account\/sessions](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#getSessions) endpoint. Use width, height and quality arguments to change the output settings.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getBrowser", + "group": null, + "weight": 61, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-browser.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-browser.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "code", + "description": "Browser Code.", + "required": true, + "schema": { + "type": "string", + "x-example": "aa", + "enum": [ + "aa", + "an", + "ch", + "ci", + "cm", + "cr", + "ff", + "sf", + "mf", + "ps", + "oi", + "om", + "op", + "on" + ], + "x-enum-name": "Browser", + "x-enum-keys": [ + "Avant Browser", + "Android WebView Beta", + "Google Chrome", + "Google Chrome (iOS)", + "Google Chrome (Mobile)", + "Chromium", + "Mozilla Firefox", + "Safari", + "Mobile Safari", + "Microsoft Edge", + "Microsoft Edge (iOS)", + "Opera Mini", + "Opera", + "Opera (Next)" + ] + }, + "in": "path" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "in": "query" + }, + { + "name": "quality", + "description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1 + }, + "in": "query" + } + ] + } + }, + "\/avatars\/credit-cards\/{code}": { + "get": { + "summary": "Get credit card icon", + "operationId": "avatarsGetCreditCard", + "tags": [ + "avatars" + ], + "description": "The credit card endpoint will return you the icon of the credit card provider you need. Use width, height and quality arguments to change the output settings.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.\n", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getCreditCard", + "group": null, + "weight": 60, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-credit-card.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-credit-card.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "code", + "description": "Credit Card Code. Possible values: amex, argencard, cabal, cencosud, diners, discover, elo, hipercard, jcb, mastercard, naranja, targeta-shopping, union-china-pay, visa, mir, maestro, rupay.", + "required": true, + "schema": { + "type": "string", + "x-example": "amex", + "enum": [ + "amex", + "argencard", + "cabal", + "cencosud", + "diners", + "discover", + "elo", + "hipercard", + "jcb", + "mastercard", + "naranja", + "targeta-shopping", + "union-china-pay", + "visa", + "mir", + "maestro", + "rupay" + ], + "x-enum-name": "CreditCard", + "x-enum-keys": [ + "American Express", + "Argencard", + "Cabal", + "Cencosud", + "Diners Club", + "Discover", + "Elo", + "Hipercard", + "JCB", + "Mastercard", + "Naranja", + "Tarjeta Shopping", + "Union China Pay", + "Visa", + "MIR", + "Maestro", + "Rupay" + ] + }, + "in": "path" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "in": "query" + }, + { + "name": "quality", + "description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1 + }, + "in": "query" + } + ] + } + }, + "\/avatars\/favicon": { + "get": { + "summary": "Get favicon", + "operationId": "avatarsGetFavicon", + "tags": [ + "avatars" + ], + "description": "Use this endpoint to fetch the favorite icon (AKA favicon) of any remote website URL.\n\nThis endpoint does not follow HTTP redirects.", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getFavicon", + "group": null, + "weight": 64, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-favicon.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-favicon.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "url", + "description": "Website URL which you want to fetch the favicon from.", + "required": true, + "schema": { + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com" + }, + "in": "query" + } + ] + } + }, + "\/avatars\/flags\/{code}": { + "get": { + "summary": "Get country flag", + "operationId": "avatarsGetFlag", + "tags": [ + "avatars" + ], + "description": "You can use this endpoint to show different country flags icons to your users. The code argument receives the 2 letter country code. Use width, height and quality arguments to change the output settings. Country codes follow the [ISO 3166-1](https:\/\/en.wikipedia.org\/wiki\/ISO_3166-1) standard.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.\n", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getFlag", + "group": null, + "weight": 62, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-flag.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-flag.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "code", + "description": "Country Code. ISO Alpha-2 country code format.", + "required": true, + "schema": { + "type": "string", + "x-example": "af", + "enum": [ + "af", + "ao", + "al", + "ad", + "ae", + "ar", + "am", + "ag", + "au", + "at", + "az", + "bi", + "be", + "bj", + "bf", + "bd", + "bg", + "bh", + "bs", + "ba", + "by", + "bz", + "bo", + "br", + "bb", + "bn", + "bt", + "bw", + "cf", + "ca", + "ch", + "cl", + "cn", + "ci", + "cm", + "cd", + "cg", + "co", + "km", + "cv", + "cr", + "cu", + "cy", + "cz", + "de", + "dj", + "dm", + "dk", + "do", + "dz", + "ec", + "eg", + "er", + "es", + "ee", + "et", + "fi", + "fj", + "fr", + "fm", + "ga", + "gb", + "ge", + "gh", + "gn", + "gm", + "gw", + "gq", + "gr", + "gd", + "gt", + "gy", + "hn", + "hr", + "ht", + "hu", + "id", + "in", + "ie", + "ir", + "iq", + "is", + "il", + "it", + "jm", + "jo", + "jp", + "kz", + "ke", + "kg", + "kh", + "ki", + "kn", + "kr", + "kw", + "la", + "lb", + "lr", + "ly", + "lc", + "li", + "lk", + "ls", + "lt", + "lu", + "lv", + "ma", + "mc", + "md", + "mg", + "mv", + "mx", + "mh", + "mk", + "ml", + "mt", + "mm", + "me", + "mn", + "mz", + "mr", + "mu", + "mw", + "my", + "na", + "ne", + "ng", + "ni", + "nl", + "no", + "np", + "nr", + "nz", + "om", + "pk", + "pa", + "pe", + "ph", + "pw", + "pg", + "pl", + "pf", + "kp", + "pt", + "py", + "qa", + "ro", + "ru", + "rw", + "sa", + "sd", + "sn", + "sg", + "sb", + "sl", + "sv", + "sm", + "so", + "rs", + "ss", + "st", + "sr", + "sk", + "si", + "se", + "sz", + "sc", + "sy", + "td", + "tg", + "th", + "tj", + "tm", + "tl", + "to", + "tt", + "tn", + "tr", + "tv", + "tz", + "ug", + "ua", + "uy", + "us", + "uz", + "va", + "vc", + "ve", + "vn", + "vu", + "ws", + "ye", + "za", + "zm", + "zw" + ], + "x-enum-name": "Flag", + "x-enum-keys": [ + "Afghanistan", + "Angola", + "Albania", + "Andorra", + "United Arab Emirates", + "Argentina", + "Armenia", + "Antigua and Barbuda", + "Australia", + "Austria", + "Azerbaijan", + "Burundi", + "Belgium", + "Benin", + "Burkina Faso", + "Bangladesh", + "Bulgaria", + "Bahrain", + "Bahamas", + "Bosnia and Herzegovina", + "Belarus", + "Belize", + "Bolivia", + "Brazil", + "Barbados", + "Brunei Darussalam", + "Bhutan", + "Botswana", + "Central African Republic", + "Canada", + "Switzerland", + "Chile", + "China", + "C\u00f4te d'Ivoire", + "Cameroon", + "Democratic Republic of the Congo", + "Republic of the Congo", + "Colombia", + "Comoros", + "Cape Verde", + "Costa Rica", + "Cuba", + "Cyprus", + "Czech Republic", + "Germany", + "Djibouti", + "Dominica", + "Denmark", + "Dominican Republic", + "Algeria", + "Ecuador", + "Egypt", + "Eritrea", + "Spain", + "Estonia", + "Ethiopia", + "Finland", + "Fiji", + "France", + "Micronesia (Federated States of)", + "Gabon", + "United Kingdom", + "Georgia", + "Ghana", + "Guinea", + "Gambia", + "Guinea-Bissau", + "Equatorial Guinea", + "Greece", + "Grenada", + "Guatemala", + "Guyana", + "Honduras", + "Croatia", + "Haiti", + "Hungary", + "Indonesia", + "India", + "Ireland", + "Iran (Islamic Republic of)", + "Iraq", + "Iceland", + "Israel", + "Italy", + "Jamaica", + "Jordan", + "Japan", + "Kazakhstan", + "Kenya", + "Kyrgyzstan", + "Cambodia", + "Kiribati", + "Saint Kitts and Nevis", + "South Korea", + "Kuwait", + "Lao People's Democratic Republic", + "Lebanon", + "Liberia", + "Libya", + "Saint Lucia", + "Liechtenstein", + "Sri Lanka", + "Lesotho", + "Lithuania", + "Luxembourg", + "Latvia", + "Morocco", + "Monaco", + "Moldova", + "Madagascar", + "Maldives", + "Mexico", + "Marshall Islands", + "North Macedonia", + "Mali", + "Malta", + "Myanmar", + "Montenegro", + "Mongolia", + "Mozambique", + "Mauritania", + "Mauritius", + "Malawi", + "Malaysia", + "Namibia", + "Niger", + "Nigeria", + "Nicaragua", + "Netherlands", + "Norway", + "Nepal", + "Nauru", + "New Zealand", + "Oman", + "Pakistan", + "Panama", + "Peru", + "Philippines", + "Palau", + "Papua New Guinea", + "Poland", + "French Polynesia", + "North Korea", + "Portugal", + "Paraguay", + "Qatar", + "Romania", + "Russia", + "Rwanda", + "Saudi Arabia", + "Sudan", + "Senegal", + "Singapore", + "Solomon Islands", + "Sierra Leone", + "El Salvador", + "San Marino", + "Somalia", + "Serbia", + "South Sudan", + "Sao Tome and Principe", + "Suriname", + "Slovakia", + "Slovenia", + "Sweden", + "Eswatini", + "Seychelles", + "Syria", + "Chad", + "Togo", + "Thailand", + "Tajikistan", + "Turkmenistan", + "Timor-Leste", + "Tonga", + "Trinidad and Tobago", + "Tunisia", + "Turkey", + "Tuvalu", + "Tanzania", + "Uganda", + "Ukraine", + "Uruguay", + "United States", + "Uzbekistan", + "Vatican City", + "Saint Vincent and the Grenadines", + "Venezuela", + "Vietnam", + "Vanuatu", + "Samoa", + "Yemen", + "South Africa", + "Zambia", + "Zimbabwe" + ] + }, + "in": "path" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "in": "query" + }, + { + "name": "quality", + "description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1 + }, + "in": "query" + } + ] + } + }, + "\/avatars\/image": { + "get": { + "summary": "Get image from URL", + "operationId": "avatarsGetImage", + "tags": [ + "avatars" + ], + "description": "Use this endpoint to fetch a remote image URL and crop it to any image size you want. This endpoint is very useful if you need to crop and display remote images in your app or in case you want to make sure a 3rd party image is properly served using a TLS protocol.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 400x400px.\n\nThis endpoint does not follow HTTP redirects.", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getImage", + "group": null, + "weight": 63, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-image.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-image.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "url", + "description": "Image URL which you want to crop.", + "required": true, + "schema": { + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com" + }, + "in": "query" + }, + { + "name": "width", + "description": "Resize preview image width, Pass an integer between 0 to 2000. Defaults to 400.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 400 + }, + "in": "query" + }, + { + "name": "height", + "description": "Resize preview image height, Pass an integer between 0 to 2000. Defaults to 400.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 400 + }, + "in": "query" + } + ] + } + }, + "\/avatars\/initials": { + "get": { + "summary": "Get user initials", + "operationId": "avatarsGetInitials", + "tags": [ + "avatars" + ], + "description": "Use this endpoint to show your user initials avatar icon on your website or app. By default, this route will try to print your logged-in user name or email initials. You can also overwrite the user name if you pass the 'name' parameter. If no name is given and no user is logged, an empty avatar will be returned.\n\nYou can use the color and background params to change the avatar colors. By default, a random theme will be selected. The random theme will persist for the user's initials when reloading the same theme will always return for the same initials.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.\n", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getInitials", + "group": null, + "weight": 66, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-initials.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-initials.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "name", + "description": "Full Name. When empty, current user name or email will be used. Max length: 128 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "", + "default": "" + }, + "in": "query" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 500 + }, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 500 + }, + "in": "query" + }, + { + "name": "background", + "description": "Changes background color. By default a random color will be picked and stay will persistent to the given name.", + "required": false, + "schema": { + "type": "string", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/avatars\/qr": { + "get": { + "summary": "Get QR code", + "operationId": "avatarsGetQR", + "tags": [ + "avatars" + ], + "description": "Converts a given plain text to a QR code image. You can use the query parameters to change the size and style of the resulting image.\n", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getQR", + "group": null, + "weight": 65, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-q-r.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-qr.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "text", + "description": "Plain text to be converted to QR code image.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" + }, + { + "name": "size", + "description": "QR code size. Pass an integer between 1 to 1000. Defaults to 400.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 1, + "default": 400 + }, + "in": "query" + }, + { + "name": "margin", + "description": "Margin from edge. Pass an integer between 0 to 10. Defaults to 1.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 1 + }, + "in": "query" + }, + { + "name": "download", + "description": "Return resulting image with 'Content-Disposition: attachment ' headers for the browser to start downloading it. Pass 0 for no header, or 1 for otherwise. Default value is set to 0.", + "required": false, + "schema": { + "type": "boolean", + "x-example": false, + "default": false + }, + "in": "query" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents": { + "get": { + "summary": "List documents", + "operationId": "databasesListDocuments", + "tags": [ + "databases" + ], + "description": "Get a list of all the user's documents in a given collection. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Documents List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/documentList" + } + } + } + } + }, + "x-appwrite": { + "method": "listDocuments", + "group": "documents", + "weight": 110, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-documents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-documents.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create document", + "operationId": "databasesCreateDocument", + "tags": [ + "databases" + ], + "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "201": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "createDocument", + "group": "documents", + "weight": 109, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "methods": [ + { + "name": "createDocument", + "auth": { + "Session": [], + "Key": [], + "JWT": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documentId", + "data", + "permissions" + ], + "required": [ + "databaseId", + "collectionId", + "documentId", + "data" + ], + "responses": [ + { + "code": 201, + "model": "#\/components\/schemas\/document" + } + ], + "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + } + ], + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection). Make sure to define attributes before creating documents.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "documentId": { + "type": "string", + "description": "Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "data": { + "type": "object", + "description": "Document data as JSON object.", + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "documents": { + "type": "array", + "description": "Array of documents data as JSON objects.", + "x-example": null, + "items": { + "type": "object" + } + } + } + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}": { + "get": { + "summary": "Get document", + "operationId": "databasesGetDocument", + "tags": [ + "databases" + ], + "description": "Get a document by its unique ID. This endpoint response returns a JSON object with the document data.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "getDocument", + "group": "documents", + "weight": 111, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-document.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "put": { + "summary": "Upsert document", + "operationId": "databasesUpsertDocument", + "tags": [ + "databases" + ], + "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "upsertDocument", + "group": "documents", + "weight": 114, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include all required attributes of the document to be created or updated.", + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "data" + ] + } + } + } + } + }, + "patch": { + "summary": "Update document", + "operationId": "databasesUpdateDocument", + "tags": [ + "databases" + ], + "description": "Update a document by its unique ID. Using the patch method you can pass only specific fields that will get updated.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "updateDocument", + "group": "documents", + "weight": 113, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include only attribute and value pairs to be updated.", + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete document", + "operationId": "databasesDeleteDocument", + "tags": [ + "databases" + ], + "description": "Delete a document by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDocument", + "group": "documents", + "weight": 119, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-document.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/decrement": { + "patch": { + "summary": "Decrement document attribute", + "operationId": "databasesDecrementDocumentAttribute", + "tags": [ + "databases" + ], + "description": "Decrement a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "decrementDocumentAttribute", + "group": "documents", + "weight": 116, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/decrement-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/decrement-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to decrement the attribute by. The value must be a number.", + "x-example": null + }, + "min": { + "type": "mixed", + "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", + "x-example": null + } + } + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/increment": { + "patch": { + "summary": "Increment document attribute", + "operationId": "databasesIncrementDocumentAttribute", + "tags": [ + "databases" + ], + "description": "Increment a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "incrementDocumentAttribute", + "group": "documents", + "weight": 115, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/increment-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/increment-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to increment the attribute by. The value must be a number.", + "x-example": null + }, + "max": { + "type": "mixed", + "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", + "x-example": null + } + } + } + } + } + } + } + }, + "\/functions\/{functionId}\/executions": { + "get": { + "summary": "List executions", + "operationId": "functionsListExecutions", + "tags": [ + "functions" + ], + "description": "Get a list of all the current user function execution logs. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Executions List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/executionList" + } + } + } + } + }, + "x-appwrite": { + "method": "listExecutions", + "group": "executions", + "weight": 394, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-executions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the current user function execution logs. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: trigger, status, responseStatusCode, duration, requestMethod, requestPath, deploymentId", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create execution", + "operationId": "functionsCreateExecution", + "tags": [ + "functions" + ], + "description": "Trigger a function execution. The returned object will return you the current execution status. You can ping the `Get Execution` endpoint to get updates on the current execution status. Once this endpoint is called, your function execution process will start asynchronously.", + "responses": { + "201": { + "description": "Execution", + "content": { + "multipart\/form-data": { + "schema": { + "$ref": "#\/components\/schemas\/execution" + } + } + } + } + }, + "x-appwrite": { + "method": "createExecution", + "group": "executions", + "weight": 392, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-execution.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterTrigger a function execution. The returned object will return you the current execution status. You can ping the `Get Execution` endpoint to get updates on the current execution status. Once this endpoint is called, your function execution process will start asynchronously.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "body": { + "type": "string", + "description": "HTTP body of execution. Default value is empty string.", + "x-example": "" + }, + "async": { + "type": "boolean", + "description": "Execute code in the background. Default value is false.", + "x-example": false + }, + "path": { + "type": "string", + "description": "HTTP path of execution. Path can include query params. Default value is \/", + "x-example": "" + }, + "method": { + "type": "string", + "description": "HTTP method of execution. Default value is GET.", + "x-example": "GET", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE", + "OPTIONS" + ], + "x-enum-name": "ExecutionMethod", + "x-enum-keys": [] + }, + "headers": { + "type": "string", + "description": "HTTP headers of execution. Defaults to empty.", + "x-example": null + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled execution time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes.", + "x-example": null + } + } + } + } + } + } + } + }, + "\/functions\/{functionId}\/executions\/{executionId}": { + "get": { + "summary": "Get execution", + "operationId": "functionsGetExecution", + "tags": [ + "functions" + ], + "description": "Get a function execution log by its unique ID.", + "responses": { + "200": { + "description": "Execution", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/execution" + } + } + } + } + }, + "x-appwrite": { + "method": "getExecution", + "group": "executions", + "weight": 393, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get-execution.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function execution log by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "executionId", + "description": "Execution ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/graphql": { + "post": { + "summary": "GraphQL endpoint", + "operationId": "graphqlQuery", + "tags": [ + "graphql" + ], + "description": "Execute a GraphQL mutation.", + "responses": { + "200": { + "description": "Any", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/any" + } + } + } + } + }, + "x-appwrite": { + "method": "query", + "group": "graphql", + "weight": 308, + "cookies": false, + "type": "graphql", + "deprecated": false, + "demo": "graphql\/query.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/graphql\/post.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "url:{url},ip:{ip}", + "scope": "graphql", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/graphql\/mutation": { + "post": { + "summary": "GraphQL endpoint", + "operationId": "graphqlMutation", + "tags": [ + "graphql" + ], + "description": "Execute a GraphQL mutation.", + "responses": { + "200": { + "description": "Any", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/any" + } + } + } + } + }, + "x-appwrite": { + "method": "mutation", + "group": "graphql", + "weight": 307, + "cookies": false, + "type": "graphql", + "deprecated": false, + "demo": "graphql\/mutation.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/graphql\/post.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "url:{url},ip:{ip}", + "scope": "graphql", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/locale": { + "get": { + "summary": "Get user locale", + "operationId": "localeGet", + "tags": [ + "locale" + ], + "description": "Get the current user location based on IP. Returns an object with user country code, country name, continent name, continent code, ip address and suggested currency. You can use the locale header to get the data in a supported language.\n\n([IP Geolocation by DB-IP](https:\/\/db-ip.com))", + "responses": { + "200": { + "description": "Locale", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/locale" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": null, + "weight": 124, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/get-locale.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/locale\/codes": { + "get": { + "summary": "List locale codes", + "operationId": "localeListCodes", + "tags": [ + "locale" + ], + "description": "List of all locale codes in [ISO 639-1](https:\/\/en.wikipedia.org\/wiki\/List_of_ISO_639-1_codes).", + "responses": { + "200": { + "description": "Locale codes list", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/localeCodeList" + } + } + } + } + }, + "x-appwrite": { + "method": "listCodes", + "group": null, + "weight": 125, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-locale-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/locale\/continents": { + "get": { + "summary": "List continents", + "operationId": "localeListContinents", + "tags": [ + "locale" + ], + "description": "List of all continents. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Continents List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/continentList" + } + } + } + } + }, + "x-appwrite": { + "method": "listContinents", + "group": null, + "weight": 129, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-continents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-continents.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/locale\/countries": { + "get": { + "summary": "List countries", + "operationId": "localeListCountries", + "tags": [ + "locale" + ], + "description": "List of all countries. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Countries List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/countryList" + } + } + } + } + }, + "x-appwrite": { + "method": "listCountries", + "group": null, + "weight": 126, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-countries.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-countries.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/locale\/countries\/eu": { + "get": { + "summary": "List EU countries", + "operationId": "localeListCountriesEU", + "tags": [ + "locale" + ], + "description": "List of all countries that are currently members of the EU. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Countries List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/countryList" + } + } + } + } + }, + "x-appwrite": { + "method": "listCountriesEU", + "group": null, + "weight": 127, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-countries-e-u.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-countries-eu.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/locale\/countries\/phones": { + "get": { + "summary": "List countries phone codes", + "operationId": "localeListCountriesPhones", + "tags": [ + "locale" + ], + "description": "List of all countries phone codes. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Phones List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/phoneList" + } + } + } + } + }, + "x-appwrite": { + "method": "listCountriesPhones", + "group": null, + "weight": 128, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-countries-phones.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-countries-phones.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/locale\/currencies": { + "get": { + "summary": "List currencies", + "operationId": "localeListCurrencies", + "tags": [ + "locale" + ], + "description": "List of all currencies, including currency symbol, name, plural, and decimal digits for all major and minor currencies. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Currencies List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/currencyList" + } + } + } + } + }, + "x-appwrite": { + "method": "listCurrencies", + "group": null, + "weight": 130, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-currencies.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-currencies.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/locale\/languages": { + "get": { + "summary": "List languages", + "operationId": "localeListLanguages", + "tags": [ + "locale" + ], + "description": "List of all languages classified by ISO 639-1 including 2-letter code, name in English, and name in the respective language.", + "responses": { + "200": { + "description": "Languages List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/languageList" + } + } + } + } + }, + "x-appwrite": { + "method": "listLanguages", + "group": null, + "weight": 131, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-languages.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-languages.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/messaging\/topics\/{topicId}\/subscribers": { + "post": { + "summary": "Create subscriber", + "operationId": "messagingCreateSubscriber", + "tags": [ + "messaging" + ], + "description": "Create a new subscriber.", + "responses": { + "201": { + "description": "Subscriber", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/subscriber" + } + } + } + } + }, + "x-appwrite": { + "method": "createSubscriber", + "group": "subscribers", + "weight": 354, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-subscriber.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-subscriber.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.write", + "platforms": [ + "server", + "client", + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [], + "Session": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID to subscribe to.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "subscriberId": { + "type": "string", + "description": "Subscriber ID. Choose a custom Subscriber ID or a new Subscriber ID.", + "x-example": "" + }, + "targetId": { + "type": "string", + "description": "Target ID. The target ID to link to the specified Topic ID.", + "x-example": "" + } + }, + "required": [ + "subscriberId", + "targetId" + ] + } + } + } + } + } + }, + "\/messaging\/topics\/{topicId}\/subscribers\/{subscriberId}": { + "delete": { + "summary": "Delete subscriber", + "operationId": "messagingDeleteSubscriber", + "tags": [ + "messaging" + ], + "description": "Delete a subscriber by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSubscriber", + "group": "subscribers", + "weight": 358, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/delete-subscriber.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/delete-subscriber.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.write", + "platforms": [ + "server", + "client", + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [], + "Session": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID subscribed to.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "subscriberId", + "description": "Subscriber ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files": { + "get": { + "summary": "List files", + "operationId": "storageListFiles", + "tags": [ + "storage" + ], + "description": "Get a list of all the user files. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Files List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/fileList" + } + } + } + } + }, + "x-appwrite": { + "method": "listFiles", + "group": "files", + "weight": 214, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/list-files.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/list-files.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, signature, mimeType, sizeOriginal, chunksTotal, chunksUploaded", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create file", + "operationId": "storageCreateFile", + "tags": [ + "storage" + ], + "description": "Create a new file. Before using this route, you should create a new bucket resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/storage#storageCreateBucket) API or directly from your Appwrite console.\n\nLarger files should be uploaded using multiple requests with the [content-range](https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Headers\/Content-Range) header to send a partial request with a maximum supported chunk of `5MB`. The `content-range` header values should always be in bytes.\n\nWhen the first request is sent, the server will return the **File** object, and the subsequent part request must include the file's **id** in `x-appwrite-id` header to allow the server to know that the partial upload is for the existing file and not for a new one.\n\nIf you're creating a new file using one of the Appwrite SDKs, all the chunking logic will be managed by the SDK internally.\n", + "responses": { + "201": { + "description": "File", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/file" + } + } + } + } + }, + "x-appwrite": { + "method": "createFile", + "group": "files", + "weight": 213, + "cookies": false, + "type": "upload", + "deprecated": false, + "demo": "storage\/create-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/create-file.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId},chunkId:{chunkId}", + "scope": "files.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "multipart\/form-data": { + "schema": { + "type": "object", + "properties": { + "fileId": { + "type": "string", + "description": "File ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "", + "x-upload-id": true + }, + "file": { + "type": "string", + "description": "Binary file. Appwrite SDKs provide helpers to handle file input. [Learn about file input](https:\/\/appwrite.io\/docs\/products\/storage\/upload-download#input-file).", + "x-example": null + }, + "permissions": { + "type": "array", + "description": "An array of permission strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "fileId", + "file" + ] + } + } + } + } + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}": { + "get": { + "summary": "Get file", + "operationId": "storageGetFile", + "tags": [ + "storage" + ], + "description": "Get a file by its unique ID. This endpoint response returns a JSON object with the file metadata.", + "responses": { + "200": { + "description": "File", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/file" + } + } + } + } + }, + "x-appwrite": { + "method": "getFile", + "group": "files", + "weight": 215, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/get-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update file", + "operationId": "storageUpdateFile", + "tags": [ + "storage" + ], + "description": "Update a file by its unique ID. Only users with write permissions have access to update this resource.", + "responses": { + "200": { + "description": "File", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/file" + } + } + } + } + }, + "x-appwrite": { + "method": "updateFile", + "group": "files", + "weight": 220, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/update-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/update-file.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "files.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the file", + "x-example": "" + }, + "permissions": { + "type": "array", + "description": "An array of permission string. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete file", + "operationId": "storageDeleteFile", + "tags": [ + "storage" + ], + "description": "Delete a file by its unique ID. Only users with write permissions have access to delete this resource.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteFile", + "group": "files", + "weight": 221, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/delete-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/delete-file.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "files.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/download": { + "get": { + "summary": "Get file for download", + "operationId": "storageGetFileDownload", + "tags": [ + "storage" + ], + "description": "Get a file content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "responses": { + "200": { + "description": "File" + } + }, + "x-appwrite": { + "method": "getFileDownload", + "group": "files", + "weight": 217, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "storage\/get-file-download.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file-download.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "token", + "description": "File token for accessing this file.", + "required": false, + "schema": { + "type": "string", + "x-example": "", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/preview": { + "get": { + "summary": "Get file preview", + "operationId": "storageGetFilePreview", + "tags": [ + "storage" + ], + "description": "Get a file preview image. Currently, this method supports preview for image files (jpg, png, and gif), other supported formats, like pdf, docs, slides, and spreadsheets, will return the file icon image. You can also pass query string arguments for cutting and resizing your preview image. Preview is supported only for image files smaller than 10MB.", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getFilePreview", + "group": "files", + "weight": 216, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "storage\/get-file-preview.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file-preview.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File ID", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "width", + "description": "Resize preview image width, Pass an integer between 0 to 4000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0 + }, + "in": "query" + }, + { + "name": "height", + "description": "Resize preview image height, Pass an integer between 0 to 4000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0 + }, + "in": "query" + }, + { + "name": "gravity", + "description": "Image crop gravity. Can be one of center,top-left,top,top-right,left,right,bottom-left,bottom,bottom-right", + "required": false, + "schema": { + "type": "string", + "x-example": "center", + "enum": [ + "center", + "top-left", + "top", + "top-right", + "left", + "right", + "bottom-left", + "bottom", + "bottom-right" + ], + "x-enum-name": "ImageGravity", + "x-enum-keys": [], + "default": "center" + }, + "in": "query" + }, + { + "name": "quality", + "description": "Preview image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1 + }, + "in": "query" + }, + { + "name": "borderWidth", + "description": "Preview image border in pixels. Pass an integer between 0 to 100. Defaults to 0.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0 + }, + "in": "query" + }, + { + "name": "borderColor", + "description": "Preview image border color. Use a valid HEX color, no # is needed for prefix.", + "required": false, + "schema": { + "type": "string", + "default": "" + }, + "in": "query" + }, + { + "name": "borderRadius", + "description": "Preview image border radius in pixels. Pass an integer between 0 to 4000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0 + }, + "in": "query" + }, + { + "name": "opacity", + "description": "Preview image opacity. Only works with images having an alpha channel (like png). Pass a number between 0 to 1.", + "required": false, + "schema": { + "type": "number", + "format": "float", + "x-example": 0, + "default": 1 + }, + "in": "query" + }, + { + "name": "rotation", + "description": "Preview image rotation in degrees. Pass an integer between -360 and 360.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": -360, + "default": 0 + }, + "in": "query" + }, + { + "name": "background", + "description": "Preview image background color. Only works with transparent images (png). Use a valid HEX color, no # is needed for prefix.", + "required": false, + "schema": { + "type": "string", + "default": "" + }, + "in": "query" + }, + { + "name": "output", + "description": "Output format type (jpeg, jpg, png, gif and webp).", + "required": false, + "schema": { + "type": "string", + "x-example": "jpg", + "enum": [ + "jpg", + "jpeg", + "png", + "webp", + "heic", + "avif", + "gif" + ], + "x-enum-name": "ImageFormat", + "x-enum-keys": [], + "default": "" + }, + "in": "query" + }, + { + "name": "token", + "description": "File token for accessing this file.", + "required": false, + "schema": { + "type": "string", + "x-example": "", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/view": { + "get": { + "summary": "Get file for view", + "operationId": "storageGetFileView", + "tags": [ + "storage" + ], + "description": "Get a file content by its unique ID. This endpoint is similar to the download method but returns with no 'Content-Disposition: attachment' header.", + "responses": { + "200": { + "description": "File" + } + }, + "x-appwrite": { + "method": "getFileView", + "group": "files", + "weight": 218, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "storage\/get-file-view.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file-view.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "token", + "description": "File token for accessing this file.", + "required": false, + "schema": { + "type": "string", + "x-example": "", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/teams": { + "get": { + "summary": "List teams", + "operationId": "teamsList", + "tags": [ + "teams" + ], + "description": "Get a list of all the teams in which the current user is a member. You can use the parameters to filter your results.", + "responses": { + "200": { + "description": "Teams List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/teamList" + } + } + } + } + }, + "x-appwrite": { + "method": "list", + "group": "teams", + "weight": 225, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/list-teams.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, total, billingPlan", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create team", + "operationId": "teamsCreate", + "tags": [ + "teams" + ], + "description": "Create a new team. The user who creates the team will automatically be assigned as the owner of the team. Only the users with the owner role can invite new members, add new owners and delete or update the team.", + "responses": { + "201": { + "description": "Team", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/team" + } + } + } + } + }, + "x-appwrite": { + "method": "create", + "group": "teams", + "weight": 224, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/create-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "teamId": { + "type": "string", + "description": "Team ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "name": { + "type": "string", + "description": "Team name. Max length: 128 chars.", + "x-example": "" + }, + "roles": { + "type": "array", + "description": "Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.", + "x-example": null, + "items": { + "type": "string" + } + } + }, + "required": [ + "teamId", + "name" + ] + } + } + } + } + } + }, + "\/teams\/{teamId}": { + "get": { + "summary": "Get team", + "operationId": "teamsGet", + "tags": [ + "teams" + ], + "description": "Get a team by its ID. All team members have read access for this resource.", + "responses": { + "200": { + "description": "Team", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/team" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": "teams", + "weight": 226, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update name", + "operationId": "teamsUpdateName", + "tags": [ + "teams" + ], + "description": "Update the team's name by its unique ID.", + "responses": { + "200": { + "description": "Team", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/team" + } + } + } + } + }, + "x-appwrite": { + "method": "updateName", + "group": "teams", + "weight": 228, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-name.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-name.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "New team name. Max length: 128 chars.", + "x-example": "" + } + }, + "required": [ + "name" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete team", + "operationId": "teamsDelete", + "tags": [ + "teams" + ], + "description": "Delete a team using its ID. Only team members with the owner role can delete the team.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "teams", + "weight": 230, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/delete-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/teams\/{teamId}\/memberships": { + "get": { + "summary": "List team memberships", + "operationId": "teamsListMemberships", + "tags": [ + "teams" + ], + "description": "Use this endpoint to list a team's members using the team's ID. All team members have read access to this endpoint. Hide sensitive attributes from the response by toggling membership privacy in the Console.", + "responses": { + "200": { + "description": "Memberships List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/membershipList" + } + } + } + } + }, + "x-appwrite": { + "method": "listMemberships", + "group": "memberships", + "weight": 232, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/list-memberships.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/list-team-members.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create team membership", + "operationId": "teamsCreateMembership", + "tags": [ + "teams" + ], + "description": "Invite a new member to join your team. Provide an ID for existing users, or invite unregistered users using an email or phone number. If initiated from a Client SDK, Appwrite will send an email or sms with a link to join the team to the invited user, and an account will be created for them if one doesn't exist. If initiated from a Server SDK, the new member will be added automatically to the team.\n\nYou only need to provide one of a user ID, email, or phone number. Appwrite will prioritize accepting the user ID > email > phone number if you provide more than one of these parameters.\n\nUse the `url` parameter to redirect the user from the invitation email to your app. After the user is redirected, use the [Update Team Membership Status](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/teams#updateMembershipStatus) endpoint to allow the user to accept the invitation to the team. \n\nPlease note that to avoid a [Redirect Attack](https:\/\/github.com\/OWASP\/CheatSheetSeries\/blob\/master\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) Appwrite will accept the only redirect URLs under the domains you have added as a platform on the Appwrite Console.\n", + "responses": { + "201": { + "description": "Membership", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/membership" + } + } + } + } + }, + "x-appwrite": { + "method": "createMembership", + "group": "memberships", + "weight": 231, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/create-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/create-team-membership.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "Email of the new team member.", + "x-example": "email@example.com" + }, + "userId": { + "type": "string", + "description": "ID of the user to be added to a team.", + "x-example": "" + }, + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "x-example": "+12065550100" + }, + "roles": { + "type": "array", + "description": "Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.", + "x-example": null, + "items": { + "type": "string" + } + }, + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "x-example": "https:\/\/example.com" + }, + "name": { + "type": "string", + "description": "Name of the new team member. Max length: 128 chars.", + "x-example": "" + } + }, + "required": [ + "roles" + ] + } + } + } + } + } + }, + "\/teams\/{teamId}\/memberships\/{membershipId}": { + "get": { + "summary": "Get team membership", + "operationId": "teamsGetMembership", + "tags": [ + "teams" + ], + "description": "Get a team member by the membership unique id. All team members have read access for this resource. Hide sensitive attributes from the response by toggling membership privacy in the Console.", + "responses": { + "200": { + "description": "Membership", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/membership" + } + } + } + } + }, + "x-appwrite": { + "method": "getMembership", + "group": "memberships", + "weight": 233, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/get-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team-member.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update membership", + "operationId": "teamsUpdateMembership", + "tags": [ + "teams" + ], + "description": "Modify the roles of a team member. Only team members with the owner role have access to this endpoint. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions).\n", + "responses": { + "200": { + "description": "Membership", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/membership" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMembership", + "group": "memberships", + "weight": 234, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-membership.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "roles": { + "type": "array", + "description": "An array of strings. Use this param to set the user's roles in the team. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.", + "x-example": null, + "items": { + "type": "string" + } + } + }, + "required": [ + "roles" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete team membership", + "operationId": "teamsDeleteMembership", + "tags": [ + "teams" + ], + "description": "This endpoint allows a user to leave a team or for a team owner to delete the membership of any other team member. You can also use this endpoint to delete a user membership even if it is not accepted.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteMembership", + "group": "memberships", + "weight": 236, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/delete-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/delete-team-membership.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/teams\/{teamId}\/memberships\/{membershipId}\/status": { + "patch": { + "summary": "Update team membership status", + "operationId": "teamsUpdateMembershipStatus", + "tags": [ + "teams" + ], + "description": "Use this endpoint to allow a user to accept an invitation to join a team after being redirected back to your app from the invitation email received by the user.\n\nIf the request is successful, a session for the user is automatically created.\n", + "responses": { + "200": { + "description": "Membership", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/membership" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMembershipStatus", + "group": "memberships", + "weight": 235, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-membership-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-membership-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "" + }, + "secret": { + "type": "string", + "description": "Secret key.", + "x-example": "" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + } + } + } + }, + "\/teams\/{teamId}\/prefs": { + "get": { + "summary": "Get team preferences", + "operationId": "teamsGetPrefs", + "tags": [ + "teams" + ], + "description": "Get the team's shared preferences by its unique ID. If a preference doesn't need to be shared by all team members, prefer storing them in [user preferences](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#getPrefs).", + "responses": { + "200": { + "description": "Preferences", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/preferences" + } + } + } + } + }, + "x-appwrite": { + "method": "getPrefs", + "group": "teams", + "weight": 227, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/get-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update preferences", + "operationId": "teamsUpdatePrefs", + "tags": [ + "teams" + ], + "description": "Update the team's preferences by its unique ID. The object you pass is stored as is and replaces any previous value. The maximum allowed prefs size is 64kB and throws an error if exceeded.", + "responses": { + "200": { + "description": "Preferences", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/preferences" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePrefs", + "group": "teams", + "weight": 229, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "prefs": { + "type": "object", + "description": "Prefs key-value JSON object.", + "x-example": "{}" + } + }, + "required": [ + "prefs" + ] + } + } + } + } + } + } + }, + "tags": [ + { + "name": "account", + "description": "The Account service allows you to authenticate and manage a user account." + }, + { + "name": "avatars", + "description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars." + }, + { + "name": "databases", + "description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents" + }, + { + "name": "locale", + "description": "The Locale service allows you to customize your app based on your users' location." + }, + { + "name": "health", + "description": "The Health service allows you to both validate and monitor your Appwrite server's health." + }, + { + "name": "projects", + "description": "The Project service allows you to manage all the projects in your Appwrite server." + }, + { + "name": "project", + "description": "The Project service allows you to manage all the projects in your Appwrite server." + }, + { + "name": "storage", + "description": "The Storage service allows you to manage your project files." + }, + { + "name": "teams", + "description": "The Teams service allows you to group users of your project and to enable them to share read and write access to your project resources" + }, + { + "name": "users", + "description": "The Users service allows you to manage your project users." + }, + { + "name": "sites", + "description": "The Sites Service allows you view, create and manage your web applications." + }, + { + "name": "functions", + "description": "The Functions Service allows you view, create and manage your Cloud Functions." + }, + { + "name": "proxy", + "description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration." + }, + { + "name": "graphql", + "description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL." + }, + { + "name": "console", + "description": "The Console service allows you to interact with console relevant informations." + }, + { + "name": "migrations", + "description": "The Migrations service allows you to migrate third-party data to your Appwrite project." + }, + { + "name": "messaging", + "description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.)." + } + ], + "components": { + "schemas": { + "any": { + "description": "Any", + "type": "object", + "additionalProperties": true + }, + "error": { + "description": "Error", + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Error message.", + "x-example": "Not found" + }, + "code": { + "type": "string", + "description": "Error code.", + "x-example": "404" + }, + "type": { + "type": "string", + "description": "Error type. You can learn more about all the error types at https:\/\/appwrite.io\/docs\/error-codes#errorTypes", + "x-example": "not_found" + }, + "version": { + "type": "string", + "description": "Server version number.", + "x-example": "1.0" + } + }, + "required": [ + "message", + "code", + "type", + "version" + ] + }, + "documentList": { + "description": "Documents List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of documents documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "documents": { + "type": "array", + "description": "List of documents.", + "items": { + "$ref": "#\/components\/schemas\/document" + }, + "x-example": "" + } + }, + "required": [ + "total", + "documents" + ] + }, + "sessionList": { + "description": "Sessions List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of sessions documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "sessions": { + "type": "array", + "description": "List of sessions.", + "items": { + "$ref": "#\/components\/schemas\/session" + }, + "x-example": "" + } + }, + "required": [ + "total", + "sessions" + ] + }, + "identityList": { + "description": "Identities List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of identities documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "identities": { + "type": "array", + "description": "List of identities.", + "items": { + "$ref": "#\/components\/schemas\/identity" + }, + "x-example": "" + } + }, + "required": [ + "total", + "identities" + ] + }, + "logList": { + "description": "Logs List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of logs documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "logs": { + "type": "array", + "description": "List of logs.", + "items": { + "$ref": "#\/components\/schemas\/log" + }, + "x-example": "" + } + }, + "required": [ + "total", + "logs" + ] + }, + "fileList": { + "description": "Files List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of files documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "files": { + "type": "array", + "description": "List of files.", + "items": { + "$ref": "#\/components\/schemas\/file" + }, + "x-example": "" + } + }, + "required": [ + "total", + "files" + ] + }, + "teamList": { + "description": "Teams List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of teams documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "teams": { + "type": "array", + "description": "List of teams.", + "items": { + "$ref": "#\/components\/schemas\/team" + }, + "x-example": "" + } + }, + "required": [ + "total", + "teams" + ] + }, + "membershipList": { + "description": "Memberships List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of memberships documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "memberships": { + "type": "array", + "description": "List of memberships.", + "items": { + "$ref": "#\/components\/schemas\/membership" + }, + "x-example": "" + } + }, + "required": [ + "total", + "memberships" + ] + }, + "executionList": { + "description": "Executions List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of executions documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "executions": { + "type": "array", + "description": "List of executions.", + "items": { + "$ref": "#\/components\/schemas\/execution" + }, + "x-example": "" + } + }, + "required": [ + "total", + "executions" + ] + }, + "countryList": { + "description": "Countries List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of countries documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "countries": { + "type": "array", + "description": "List of countries.", + "items": { + "$ref": "#\/components\/schemas\/country" + }, + "x-example": "" + } + }, + "required": [ + "total", + "countries" + ] + }, + "continentList": { + "description": "Continents List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of continents documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "continents": { + "type": "array", + "description": "List of continents.", + "items": { + "$ref": "#\/components\/schemas\/continent" + }, + "x-example": "" + } + }, + "required": [ + "total", + "continents" + ] + }, + "languageList": { + "description": "Languages List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of languages documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "languages": { + "type": "array", + "description": "List of languages.", + "items": { + "$ref": "#\/components\/schemas\/language" + }, + "x-example": "" + } + }, + "required": [ + "total", + "languages" + ] + }, + "currencyList": { + "description": "Currencies List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of currencies documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "currencies": { + "type": "array", + "description": "List of currencies.", + "items": { + "$ref": "#\/components\/schemas\/currency" + }, + "x-example": "" + } + }, + "required": [ + "total", + "currencies" + ] + }, + "phoneList": { + "description": "Phones List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of phones documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "phones": { + "type": "array", + "description": "List of phones.", + "items": { + "$ref": "#\/components\/schemas\/phone" + }, + "x-example": "" + } + }, + "required": [ + "total", + "phones" + ] + }, + "localeCodeList": { + "description": "Locale codes list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of localeCodes documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "localeCodes": { + "type": "array", + "description": "List of localeCodes.", + "items": { + "$ref": "#\/components\/schemas\/localeCode" + }, + "x-example": "" + } + }, + "required": [ + "total", + "localeCodes" + ] + }, + "document": { + "description": "Document", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Document ID.", + "x-example": "5e5ea5c16897e" + }, + "$sequence": { + "type": "integer", + "description": "Document automatically incrementing ID.", + "x-example": 1, + "format": "int32" + }, + "$collectionId": { + "type": "string", + "description": "Collection ID.", + "x-example": "5e5ea5c15117e" + }, + "$databaseId": { + "type": "string", + "description": "Database ID.", + "x-example": "5e5ea5c15117e" + }, + "$createdAt": { + "type": "string", + "description": "Document creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Document update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Document permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + } + }, + "additionalProperties": true, + "required": [ + "$id", + "$sequence", + "$collectionId", + "$databaseId", + "$createdAt", + "$updatedAt", + "$permissions" + ] + }, + "log": { + "description": "Log", + "type": "object", + "properties": { + "event": { + "type": "string", + "description": "Event name.", + "x-example": "account.sessions.create" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "610fc2f985ee0" + }, + "userEmail": { + "type": "string", + "description": "User Email.", + "x-example": "john@appwrite.io" + }, + "userName": { + "type": "string", + "description": "User Name.", + "x-example": "John Doe" + }, + "mode": { + "type": "string", + "description": "API mode when event triggered.", + "x-example": "admin" + }, + "ip": { + "type": "string", + "description": "IP session in use when the session was created.", + "x-example": "127.0.0.1" + }, + "time": { + "type": "string", + "description": "Log creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "osCode": { + "type": "string", + "description": "Operating system code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/os.json).", + "x-example": "Mac" + }, + "osName": { + "type": "string", + "description": "Operating system name.", + "x-example": "Mac" + }, + "osVersion": { + "type": "string", + "description": "Operating system version.", + "x-example": "Mac" + }, + "clientType": { + "type": "string", + "description": "Client type.", + "x-example": "browser" + }, + "clientCode": { + "type": "string", + "description": "Client code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/clients.json).", + "x-example": "CM" + }, + "clientName": { + "type": "string", + "description": "Client name.", + "x-example": "Chrome Mobile iOS" + }, + "clientVersion": { + "type": "string", + "description": "Client version.", + "x-example": "84.0" + }, + "clientEngine": { + "type": "string", + "description": "Client engine name.", + "x-example": "WebKit" + }, + "clientEngineVersion": { + "type": "string", + "description": "Client engine name.", + "x-example": "605.1.15" + }, + "deviceName": { + "type": "string", + "description": "Device name.", + "x-example": "smartphone" + }, + "deviceBrand": { + "type": "string", + "description": "Device brand name.", + "x-example": "Google" + }, + "deviceModel": { + "type": "string", + "description": "Device model name.", + "x-example": "Nexus 5" + }, + "countryCode": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + }, + "countryName": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + } + }, + "required": [ + "event", + "userId", + "userEmail", + "userName", + "mode", + "ip", + "time", + "osCode", + "osName", + "osVersion", + "clientType", + "clientCode", + "clientName", + "clientVersion", + "clientEngine", + "clientEngineVersion", + "deviceName", + "deviceBrand", + "deviceModel", + "countryCode", + "countryName" + ] + }, + "user": { + "description": "User", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "User creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "User update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "User name.", + "x-example": "John Doe" + }, + "password": { + "type": "string", + "description": "Hashed user password.", + "x-example": "$argon2id$v=19$m=2048,t=4,p=3$aUZjLnliVWRINmFNTWMudg$5S+x+7uA31xFnrHFT47yFwcJeaP0w92L\/4LdgrVRXxE", + "nullable": true + }, + "hash": { + "type": "string", + "description": "Password hashing algorithm.", + "x-example": "argon2", + "nullable": true + }, + "hashOptions": { + "type": "object", + "description": "Password hashing algorithm configuration.", + "x-example": {}, + "items": { + "oneOf": [ + { + "$ref": "#\/components\/schemas\/algoArgon2" + }, + { + "$ref": "#\/components\/schemas\/algoScrypt" + }, + { + "$ref": "#\/components\/schemas\/algoScryptModified" + }, + { + "$ref": "#\/components\/schemas\/algoBcrypt" + }, + { + "$ref": "#\/components\/schemas\/algoPhpass" + }, + { + "$ref": "#\/components\/schemas\/algoSha" + }, + { + "$ref": "#\/components\/schemas\/algoMd5" + } + ] + }, + "nullable": true + }, + "registration": { + "type": "string", + "description": "User registration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "boolean", + "description": "User status. Pass `true` for enabled and `false` for disabled.", + "x-example": true + }, + "labels": { + "type": "array", + "description": "Labels for the user.", + "items": { + "type": "string" + }, + "x-example": [ + "vip" + ] + }, + "passwordUpdate": { + "type": "string", + "description": "Password update time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "email": { + "type": "string", + "description": "User email address.", + "x-example": "john@appwrite.io" + }, + "phone": { + "type": "string", + "description": "User phone number in E.164 format.", + "x-example": "+4930901820" + }, + "emailVerification": { + "type": "boolean", + "description": "Email verification status.", + "x-example": true + }, + "phoneVerification": { + "type": "boolean", + "description": "Phone verification status.", + "x-example": true + }, + "mfa": { + "type": "boolean", + "description": "Multi factor authentication status.", + "x-example": true + }, + "prefs": { + "type": "object", + "description": "User preferences as a key-value object", + "x-example": { + "theme": "pink", + "timezone": "UTC" + }, + "items": { + "$ref": "#\/components\/schemas\/preferences" + } + }, + "targets": { + "type": "array", + "description": "A user-owned message receiver. A single user may have multiple e.g. emails, phones, and a browser. Each target is registered with a single provider.", + "items": { + "$ref": "#\/components\/schemas\/target" + }, + "x-example": [] + }, + "accessedAt": { + "type": "string", + "description": "Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "registration", + "status", + "labels", + "passwordUpdate", + "email", + "phone", + "emailVerification", + "phoneVerification", + "mfa", + "prefs", + "targets", + "accessedAt" + ] + }, + "algoMd5": { + "description": "AlgoMD5", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "md5" + } + }, + "required": [ + "type" + ] + }, + "algoSha": { + "description": "AlgoSHA", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "sha" + } + }, + "required": [ + "type" + ] + }, + "algoPhpass": { + "description": "AlgoPHPass", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "phpass" + } + }, + "required": [ + "type" + ] + }, + "algoBcrypt": { + "description": "AlgoBcrypt", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "bcrypt" + } + }, + "required": [ + "type" + ] + }, + "algoScrypt": { + "description": "AlgoScrypt", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "scrypt" + }, + "costCpu": { + "type": "integer", + "description": "CPU complexity of computed hash.", + "x-example": 8, + "format": "int32" + }, + "costMemory": { + "type": "integer", + "description": "Memory complexity of computed hash.", + "x-example": 14, + "format": "int32" + }, + "costParallel": { + "type": "integer", + "description": "Parallelization of computed hash.", + "x-example": 1, + "format": "int32" + }, + "length": { + "type": "integer", + "description": "Length used to compute hash.", + "x-example": 64, + "format": "int32" + } + }, + "required": [ + "type", + "costCpu", + "costMemory", + "costParallel", + "length" + ] + }, + "algoScryptModified": { + "description": "AlgoScryptModified", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "scryptMod" + }, + "salt": { + "type": "string", + "description": "Salt used to compute hash.", + "x-example": "UxLMreBr6tYyjQ==" + }, + "saltSeparator": { + "type": "string", + "description": "Separator used to compute hash.", + "x-example": "Bw==" + }, + "signerKey": { + "type": "string", + "description": "Key used to compute hash.", + "x-example": "XyEKE9RcTDeLEsL\/RjwPDBv\/RqDl8fb3gpYEOQaPihbxf1ZAtSOHCjuAAa7Q3oHpCYhXSN9tizHgVOwn6krflQ==" + } + }, + "required": [ + "type", + "salt", + "saltSeparator", + "signerKey" + ] + }, + "algoArgon2": { + "description": "AlgoArgon2", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "argon2" + }, + "memoryCost": { + "type": "integer", + "description": "Memory used to compute hash.", + "x-example": 65536, + "format": "int32" + }, + "timeCost": { + "type": "integer", + "description": "Amount of time consumed to compute hash", + "x-example": 4, + "format": "int32" + }, + "threads": { + "type": "integer", + "description": "Number of threads used to compute hash.", + "x-example": 3, + "format": "int32" + } + }, + "required": [ + "type", + "memoryCost", + "timeCost", + "threads" + ] + }, + "preferences": { + "description": "Preferences", + "type": "object", + "additionalProperties": true + }, + "session": { + "description": "Session", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Session ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Session creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Session update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5bb8c16897e" + }, + "expire": { + "type": "string", + "description": "Session expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "provider": { + "type": "string", + "description": "Session Provider.", + "x-example": "email" + }, + "providerUid": { + "type": "string", + "description": "Session Provider User ID.", + "x-example": "user@example.com" + }, + "providerAccessToken": { + "type": "string", + "description": "Session Provider Access Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + }, + "providerAccessTokenExpiry": { + "type": "string", + "description": "The date of when the access token expires in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "providerRefreshToken": { + "type": "string", + "description": "Session Provider Refresh Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + }, + "ip": { + "type": "string", + "description": "IP in use when the session was created.", + "x-example": "127.0.0.1" + }, + "osCode": { + "type": "string", + "description": "Operating system code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/os.json).", + "x-example": "Mac" + }, + "osName": { + "type": "string", + "description": "Operating system name.", + "x-example": "Mac" + }, + "osVersion": { + "type": "string", + "description": "Operating system version.", + "x-example": "Mac" + }, + "clientType": { + "type": "string", + "description": "Client type.", + "x-example": "browser" + }, + "clientCode": { + "type": "string", + "description": "Client code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/clients.json).", + "x-example": "CM" + }, + "clientName": { + "type": "string", + "description": "Client name.", + "x-example": "Chrome Mobile iOS" + }, + "clientVersion": { + "type": "string", + "description": "Client version.", + "x-example": "84.0" + }, + "clientEngine": { + "type": "string", + "description": "Client engine name.", + "x-example": "WebKit" + }, + "clientEngineVersion": { + "type": "string", + "description": "Client engine name.", + "x-example": "605.1.15" + }, + "deviceName": { + "type": "string", + "description": "Device name.", + "x-example": "smartphone" + }, + "deviceBrand": { + "type": "string", + "description": "Device brand name.", + "x-example": "Google" + }, + "deviceModel": { + "type": "string", + "description": "Device model name.", + "x-example": "Nexus 5" + }, + "countryCode": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + }, + "countryName": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + }, + "current": { + "type": "boolean", + "description": "Returns true if this the current user session.", + "x-example": true + }, + "factors": { + "type": "array", + "description": "Returns a list of active session factors.", + "items": { + "type": "string" + }, + "x-example": [ + "email" + ] + }, + "secret": { + "type": "string", + "description": "Secret used to authenticate the user. Only included if the request was made with an API key", + "x-example": "5e5bb8c16897e" + }, + "mfaUpdatedAt": { + "type": "string", + "description": "Most recent date in ISO 8601 format when the session successfully passed MFA challenge.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "userId", + "expire", + "provider", + "providerUid", + "providerAccessToken", + "providerAccessTokenExpiry", + "providerRefreshToken", + "ip", + "osCode", + "osName", + "osVersion", + "clientType", + "clientCode", + "clientName", + "clientVersion", + "clientEngine", + "clientEngineVersion", + "deviceName", + "deviceBrand", + "deviceModel", + "countryCode", + "countryName", + "current", + "factors", + "secret", + "mfaUpdatedAt" + ] + }, + "identity": { + "description": "Identity", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Identity ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Identity creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Identity update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5bb8c16897e" + }, + "provider": { + "type": "string", + "description": "Identity Provider.", + "x-example": "email" + }, + "providerUid": { + "type": "string", + "description": "ID of the User in the Identity Provider.", + "x-example": "5e5bb8c16897e" + }, + "providerEmail": { + "type": "string", + "description": "Email of the User in the Identity Provider.", + "x-example": "user@example.com" + }, + "providerAccessToken": { + "type": "string", + "description": "Identity Provider Access Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + }, + "providerAccessTokenExpiry": { + "type": "string", + "description": "The date of when the access token expires in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "providerRefreshToken": { + "type": "string", + "description": "Identity Provider Refresh Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "userId", + "provider", + "providerUid", + "providerEmail", + "providerAccessToken", + "providerAccessTokenExpiry", + "providerRefreshToken" + ] + }, + "token": { + "description": "Token", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Token ID.", + "x-example": "bb8ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Token creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c168bb8" + }, + "secret": { + "type": "string", + "description": "Token secret key. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.", + "x-example": "" + }, + "expire": { + "type": "string", + "description": "Token expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "phrase": { + "type": "string", + "description": "Security phrase of a token. Empty if security phrase was not requested when creating a token. It includes randomly generated phrase which is also sent in the external resource such as email.", + "x-example": "Golden Fox" + } + }, + "required": [ + "$id", + "$createdAt", + "userId", + "secret", + "expire", + "phrase" + ] + }, + "jwt": { + "description": "JWT", + "type": "object", + "properties": { + "jwt": { + "type": "string", + "description": "JWT encoded string.", + "x-example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + } + }, + "required": [ + "jwt" + ] + }, + "locale": { + "description": "Locale", + "type": "object", + "properties": { + "ip": { + "type": "string", + "description": "User IP address.", + "x-example": "127.0.0.1" + }, + "countryCode": { + "type": "string", + "description": "Country code in [ISO 3166-1](http:\/\/en.wikipedia.org\/wiki\/ISO_3166-1) two-character format", + "x-example": "US" + }, + "country": { + "type": "string", + "description": "Country name. This field support localization.", + "x-example": "United States" + }, + "continentCode": { + "type": "string", + "description": "Continent code. A two character continent code \"AF\" for Africa, \"AN\" for Antarctica, \"AS\" for Asia, \"EU\" for Europe, \"NA\" for North America, \"OC\" for Oceania, and \"SA\" for South America.", + "x-example": "NA" + }, + "continent": { + "type": "string", + "description": "Continent name. This field support localization.", + "x-example": "North America" + }, + "eu": { + "type": "boolean", + "description": "True if country is part of the European Union.", + "x-example": false + }, + "currency": { + "type": "string", + "description": "Currency code in [ISO 4217-1](http:\/\/en.wikipedia.org\/wiki\/ISO_4217) three-character format", + "x-example": "USD" + } + }, + "required": [ + "ip", + "countryCode", + "country", + "continentCode", + "continent", + "eu", + "currency" + ] + }, + "localeCode": { + "description": "LocaleCode", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Locale codes in [ISO 639-1](https:\/\/en.wikipedia.org\/wiki\/List_of_ISO_639-1_codes)", + "x-example": "en-us" + }, + "name": { + "type": "string", + "description": "Locale name", + "x-example": "US" + } + }, + "required": [ + "code", + "name" + ] + }, + "file": { + "description": "File", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "File ID.", + "x-example": "5e5ea5c16897e" + }, + "bucketId": { + "type": "string", + "description": "Bucket ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "File creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "File update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "File permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + }, + "name": { + "type": "string", + "description": "File name.", + "x-example": "Pink.png" + }, + "signature": { + "type": "string", + "description": "File MD5 signature.", + "x-example": "5d529fd02b544198ae075bd57c1762bb" + }, + "mimeType": { + "type": "string", + "description": "File mime type.", + "x-example": "image\/png" + }, + "sizeOriginal": { + "type": "integer", + "description": "File original size in bytes.", + "x-example": 17890, + "format": "int32" + }, + "chunksTotal": { + "type": "integer", + "description": "Total number of chunks available", + "x-example": 17890, + "format": "int32" + }, + "chunksUploaded": { + "type": "integer", + "description": "Total number of chunks uploaded", + "x-example": 17890, + "format": "int32" + } + }, + "required": [ + "$id", + "bucketId", + "$createdAt", + "$updatedAt", + "$permissions", + "name", + "signature", + "mimeType", + "sizeOriginal", + "chunksTotal", + "chunksUploaded" + ] + }, + "team": { + "description": "Team", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Team ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Team creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Team update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Team name.", + "x-example": "VIP" + }, + "total": { + "type": "integer", + "description": "Total number of team members.", + "x-example": 7, + "format": "int32" + }, + "prefs": { + "type": "object", + "description": "Team preferences as a key-value object", + "x-example": { + "theme": "pink", + "timezone": "UTC" + }, + "items": { + "$ref": "#\/components\/schemas\/preferences" + } + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "total", + "prefs" + ] + }, + "membership": { + "description": "Membership", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Membership ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Membership creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Membership update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c16897e" + }, + "userName": { + "type": "string", + "description": "User name. Hide this attribute by toggling membership privacy in the Console.", + "x-example": "John Doe" + }, + "userEmail": { + "type": "string", + "description": "User email address. Hide this attribute by toggling membership privacy in the Console.", + "x-example": "john@appwrite.io" + }, + "teamId": { + "type": "string", + "description": "Team ID.", + "x-example": "5e5ea5c16897e" + }, + "teamName": { + "type": "string", + "description": "Team name.", + "x-example": "VIP" + }, + "invited": { + "type": "string", + "description": "Date, the user has been invited to join the team in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "joined": { + "type": "string", + "description": "Date, the user has accepted the invitation to join the team in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "confirm": { + "type": "boolean", + "description": "User confirmation status, true if the user has joined the team or false otherwise.", + "x-example": false + }, + "mfa": { + "type": "boolean", + "description": "Multi factor authentication status, true if the user has MFA enabled or false otherwise. Hide this attribute by toggling membership privacy in the Console.", + "x-example": false + }, + "roles": { + "type": "array", + "description": "User list of roles", + "items": { + "type": "string" + }, + "x-example": [ + "owner" + ] + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "userId", + "userName", + "userEmail", + "teamId", + "teamName", + "invited", + "joined", + "confirm", + "mfa", + "roles" + ] + }, + "execution": { + "description": "Execution", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Execution ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Execution creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Execution upate date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Execution roles.", + "items": { + "type": "string" + }, + "x-example": [ + "any" + ] + }, + "functionId": { + "type": "string", + "description": "Function ID.", + "x-example": "5e5ea6g16897e" + }, + "trigger": { + "type": "string", + "description": "The trigger that caused the function to execute. Possible values can be: `http`, `schedule`, or `event`.", + "x-example": "http" + }, + "status": { + "type": "string", + "description": "The status of the function execution. Possible values can be: `waiting`, `processing`, `completed`, or `failed`.", + "x-example": "processing" + }, + "requestMethod": { + "type": "string", + "description": "HTTP request method type.", + "x-example": "GET" + }, + "requestPath": { + "type": "string", + "description": "HTTP request path and query.", + "x-example": "\/articles?id=5" + }, + "requestHeaders": { + "type": "array", + "description": "HTTP response headers as a key-value object. This will return only whitelisted headers. All headers are returned if execution is created as synchronous.", + "items": { + "$ref": "#\/components\/schemas\/headers" + }, + "x-example": [ + { + "Content-Type": "application\/json" + } + ] + }, + "responseStatusCode": { + "type": "integer", + "description": "HTTP response status code.", + "x-example": 200, + "format": "int32" + }, + "responseBody": { + "type": "string", + "description": "HTTP response body. This will return empty unless execution is created as synchronous.", + "x-example": "" + }, + "responseHeaders": { + "type": "array", + "description": "HTTP response headers as a key-value object. This will return only whitelisted headers. All headers are returned if execution is created as synchronous.", + "items": { + "$ref": "#\/components\/schemas\/headers" + }, + "x-example": [ + { + "Content-Type": "application\/json" + } + ] + }, + "logs": { + "type": "string", + "description": "Function logs. Includes the last 4,000 characters. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.", + "x-example": "" + }, + "errors": { + "type": "string", + "description": "Function errors. Includes the last 4,000 characters. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.", + "x-example": "" + }, + "duration": { + "type": "number", + "description": "Resource(function\/site) execution duration in seconds.", + "x-example": 0.4, + "format": "double" + }, + "scheduledAt": { + "type": "string", + "description": "The scheduled time for execution. If left empty, execution will be queued immediately.", + "x-example": "2020-10-15T06:38:00.000+00:00", + "nullable": true + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "$permissions", + "functionId", + "trigger", + "status", + "requestMethod", + "requestPath", + "requestHeaders", + "responseStatusCode", + "responseBody", + "responseHeaders", + "logs", + "errors", + "duration" + ] + }, + "country": { + "description": "Country", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + }, + "code": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + } + }, + "required": [ + "name", + "code" + ] + }, + "continent": { + "description": "Continent", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Continent name.", + "x-example": "Europe" + }, + "code": { + "type": "string", + "description": "Continent two letter code.", + "x-example": "EU" + } + }, + "required": [ + "name", + "code" + ] + }, + "language": { + "description": "Language", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Language name.", + "x-example": "Italian" + }, + "code": { + "type": "string", + "description": "Language two-character ISO 639-1 codes.", + "x-example": "it" + }, + "nativeName": { + "type": "string", + "description": "Language native name.", + "x-example": "Italiano" + } + }, + "required": [ + "name", + "code", + "nativeName" + ] + }, + "currency": { + "description": "Currency", + "type": "object", + "properties": { + "symbol": { + "type": "string", + "description": "Currency symbol.", + "x-example": "$" + }, + "name": { + "type": "string", + "description": "Currency name.", + "x-example": "US dollar" + }, + "symbolNative": { + "type": "string", + "description": "Currency native symbol.", + "x-example": "$" + }, + "decimalDigits": { + "type": "integer", + "description": "Number of decimal digits.", + "x-example": 2, + "format": "int32" + }, + "rounding": { + "type": "number", + "description": "Currency digit rounding.", + "x-example": 0, + "format": "double" + }, + "code": { + "type": "string", + "description": "Currency code in [ISO 4217-1](http:\/\/en.wikipedia.org\/wiki\/ISO_4217) three-character format.", + "x-example": "USD" + }, + "namePlural": { + "type": "string", + "description": "Currency plural name", + "x-example": "US dollars" + } + }, + "required": [ + "symbol", + "name", + "symbolNative", + "decimalDigits", + "rounding", + "code", + "namePlural" + ] + }, + "phone": { + "description": "Phone", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Phone code.", + "x-example": "+1" + }, + "countryCode": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + }, + "countryName": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + } + }, + "required": [ + "code", + "countryCode", + "countryName" + ] + }, + "headers": { + "description": "Headers", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Header name.", + "x-example": "Content-Type" + }, + "value": { + "type": "string", + "description": "Header value.", + "x-example": "application\/json" + } + }, + "required": [ + "name", + "value" + ] + }, + "mfaChallenge": { + "description": "MFA Challenge", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Token ID.", + "x-example": "bb8ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Token creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c168bb8" + }, + "expire": { + "type": "string", + "description": "Token expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "userId", + "expire" + ] + }, + "mfaRecoveryCodes": { + "description": "MFA Recovery Codes", + "type": "object", + "properties": { + "recoveryCodes": { + "type": "array", + "description": "Recovery codes.", + "items": { + "type": "string" + }, + "x-example": [ + "a3kf0-s0cl2", + "s0co1-as98s" + ] + } + }, + "required": [ + "recoveryCodes" + ] + }, + "mfaType": { + "description": "MFAType", + "type": "object", + "properties": { + "secret": { + "type": "string", + "description": "Secret token used for TOTP factor.", + "x-example": true + }, + "uri": { + "type": "string", + "description": "URI for authenticator apps.", + "x-example": true + } + }, + "required": [ + "secret", + "uri" + ] + }, + "mfaFactors": { + "description": "MFAFactors", + "type": "object", + "properties": { + "totp": { + "type": "boolean", + "description": "Can TOTP be used for MFA challenge for this account.", + "x-example": true + }, + "phone": { + "type": "boolean", + "description": "Can phone (SMS) be used for MFA challenge for this account.", + "x-example": true + }, + "email": { + "type": "boolean", + "description": "Can email be used for MFA challenge for this account.", + "x-example": true + }, + "recoveryCode": { + "type": "boolean", + "description": "Can recovery code be used for MFA challenge for this account.", + "x-example": true + } + }, + "required": [ + "totp", + "phone", + "email", + "recoveryCode" + ] + }, + "subscriber": { + "description": "Subscriber", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Subscriber ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Subscriber creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Subscriber update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "targetId": { + "type": "string", + "description": "Target ID.", + "x-example": "259125845563242502" + }, + "target": { + "type": "object", + "description": "Target.", + "x-example": { + "$id": "259125845563242502", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "providerType": "email", + "providerId": "259125845563242502", + "name": "ageon-app-email", + "identifier": "random-mail@email.org", + "userId": "5e5ea5c16897e" + }, + "items": { + "$ref": "#\/components\/schemas\/target" + } + }, + "userId": { + "type": "string", + "description": "Topic ID.", + "x-example": "5e5ea5c16897e" + }, + "userName": { + "type": "string", + "description": "User Name.", + "x-example": "Aegon Targaryen" + }, + "topicId": { + "type": "string", + "description": "Topic ID.", + "x-example": "259125845563242502" + }, + "providerType": { + "type": "string", + "description": "The target provider type. Can be one of the following: `email`, `sms` or `push`.", + "x-example": "email" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "targetId", + "target", + "userId", + "userName", + "topicId", + "providerType" + ] + }, + "target": { + "description": "Target", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Target ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Target creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Target update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Target Name.", + "x-example": "Apple iPhone 12" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "259125845563242502" + }, + "providerId": { + "type": "string", + "description": "Provider ID.", + "x-example": "259125845563242502", + "nullable": true + }, + "providerType": { + "type": "string", + "description": "The target provider type. Can be one of the following: `email`, `sms` or `push`.", + "x-example": "email" + }, + "identifier": { + "type": "string", + "description": "The target identifier.", + "x-example": "token" + }, + "expired": { + "type": "boolean", + "description": "Is the target expired.", + "x-example": false + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "userId", + "providerType", + "identifier", + "expired" + ] + } + }, + "securitySchemes": { + "Project": { + "type": "apiKey", + "name": "X-Appwrite-Project", + "description": "Your project ID", + "in": "header", + "x-appwrite": { + "demo": "" + } + }, + "JWT": { + "type": "apiKey", + "name": "X-Appwrite-JWT", + "description": "Your secret JSON Web Token", + "in": "header" + }, + "Locale": { + "type": "apiKey", + "name": "X-Appwrite-Locale", + "description": "", + "in": "header", + "x-appwrite": { + "demo": "en" + } + }, + "Session": { + "type": "apiKey", + "name": "X-Appwrite-Session", + "description": "The user session to authenticate with", + "in": "header" + }, + "DevKey": { + "type": "apiKey", + "name": "X-Appwrite-Dev-Key", + "description": "Your secret dev API key", + "in": "header" + } + } + }, + "externalDocs": { + "description": "Full API docs, specs and tutorials", + "url": "https:\/\/appwrite.io\/docs" + } +} \ No newline at end of file diff --git a/app/config/specs/open-api3-1.8.x-console.json b/app/config/specs/open-api3-1.8.x-console.json new file mode 100644 index 0000000000..4372df4eb3 --- /dev/null +++ b/app/config/specs/open-api3-1.8.x-console.json @@ -0,0 +1,44048 @@ +{ + "openapi": "3.0.0", + "info": { + "version": "1.7.4", + "title": "Appwrite", + "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", + "termsOfService": "https:\/\/appwrite.io\/policy\/terms", + "contact": { + "name": "Appwrite Team", + "url": "https:\/\/appwrite.io\/support", + "email": "team@appwrite.io" + }, + "license": { + "name": "BSD-3-Clause", + "url": "https:\/\/raw.githubusercontent.com\/appwrite\/appwrite\/master\/LICENSE" + } + }, + "servers": [ + { + "url": "https:\/\/cloud.appwrite.io\/v1" + }, + { + "url": "https:\/\/.cloud.appwrite.io\/v1" + } + ], + "paths": { + "\/account": { + "get": { + "summary": "Get account", + "operationId": "accountGet", + "tags": [ + "account" + ], + "description": "Get the currently logged in user.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": "account", + "weight": 10, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + }, + "post": { + "summary": "Create account", + "operationId": "accountCreate", + "tags": [ + "account" + ], + "description": "Use this endpoint to allow a new user to register a new account in your project. After the user registration completes successfully, you can use the [\/account\/verfication](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createVerification) route to start verifying the user email address. To allow the new user to login to their new account, you need to create a new [account session](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createEmailSession).", + "responses": { + "201": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "create", + "group": "account", + "weight": 9, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "New user password. Must be between 8 and 256 chars.", + "x-example": null + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete account", + "operationId": "accountDelete", + "tags": [ + "account" + ], + "description": "Delete the currently logged in user.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "account", + "weight": 11, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ] + } + }, + "\/account\/email": { + "patch": { + "summary": "Update email", + "operationId": "accountUpdateEmail", + "tags": [ + "account" + ], + "description": "Update currently logged in user account email address. After changing user address, the user confirmation status will get reset. A new confirmation email is not sent automatically however you can use the send confirmation email endpoint again to send the confirmation email. For security measures, user password is required to complete this request.\nThis endpoint can also be used to convert an anonymous account to a normal one, by passing an email address and a new password.\n", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateEmail", + "group": "account", + "weight": 35, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-email.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password. Must be at least 8 chars.", + "x-example": "password" + } + }, + "required": [ + "email", + "password" + ] + } + } + } + } + } + }, + "\/account\/identities": { + "get": { + "summary": "List identities", + "operationId": "accountListIdentities", + "tags": [ + "account" + ], + "description": "Get the list of identities for the currently logged in user.", + "responses": { + "200": { + "description": "Identities List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/identityList" + } + } + } + } + }, + "x-appwrite": { + "method": "listIdentities", + "group": "identities", + "weight": 58, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-identities.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-identities.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, provider, providerUid, providerEmail, providerAccessTokenExpiry", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/account\/identities\/{identityId}": { + "delete": { + "summary": "Delete identity", + "operationId": "accountDeleteIdentity", + "tags": [ + "account" + ], + "description": "Delete an identity by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteIdentity", + "group": "identities", + "weight": 59, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-identity.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-identity.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "identityId", + "description": "Identity ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/account\/jwts": { + "post": { + "summary": "Create JWT", + "operationId": "accountCreateJWT", + "tags": [ + "account" + ], + "description": "Use this endpoint to create a JSON Web Token. You can use the resulting JWT to authenticate on behalf of the current user when working with the Appwrite server-side API and SDKs. The JWT secret is valid for 15 minutes from its creation and will be invalid if the user will logout in that time frame.", + "responses": { + "201": { + "description": "JWT", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/jwt" + } + } + } + } + }, + "x-appwrite": { + "method": "createJWT", + "group": "tokens", + "weight": 30, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-j-w-t.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-jwt.md", + "rate-limit": 100, + "rate-time": 3600, + "rate-key": "url:{url},userId:{userId}", + "scope": "account", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ] + } + }, + "\/account\/logs": { + "get": { + "summary": "List logs", + "operationId": "accountListLogs", + "tags": [ + "account" + ], + "description": "Get the list of latest security activity logs for the currently logged in user. Each log returns user IP address, location and date and time of log.", + "responses": { + "200": { + "description": "Logs List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/logList" + } + } + } + } + }, + "x-appwrite": { + "method": "listLogs", + "group": "logs", + "weight": 32, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/account\/mfa": { + "patch": { + "summary": "Update MFA", + "operationId": "accountUpdateMFA", + "tags": [ + "account" + ], + "description": "Enable or disable MFA on an account.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMFA", + "group": "mfa", + "weight": 45, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-m-f-a.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "mfa": { + "type": "boolean", + "description": "Enable or disable MFA.", + "x-example": false + } + }, + "required": [ + "mfa" + ] + } + } + } + } + } + }, + "\/account\/mfa\/authenticators\/{type}": { + "post": { + "summary": "Create authenticator", + "operationId": "accountCreateMfaAuthenticator", + "tags": [ + "account" + ], + "description": "Add an authenticator app to be used as an MFA factor. Verify the authenticator using the [verify authenticator](\/docs\/references\/cloud\/client-web\/account#updateMfaAuthenticator) method.", + "responses": { + "200": { + "description": "MFAType", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaType" + } + } + } + } + }, + "x-appwrite": { + "method": "createMfaAuthenticator", + "group": "mfa", + "weight": 47, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "type", + "description": "Type of authenticator. Must be `totp`", + "required": true, + "schema": { + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [] + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update authenticator (confirmation)", + "operationId": "accountUpdateMfaAuthenticator", + "tags": [ + "account" + ], + "description": "Verify an authenticator app after adding it using the [add authenticator](\/docs\/references\/cloud\/client-web\/account#createMfaAuthenticator) method.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMfaAuthenticator", + "group": "mfa", + "weight": 48, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "type", + "description": "Type of authenticator.", + "required": true, + "schema": { + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [] + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "otp": { + "type": "string", + "description": "Valid verification token.", + "x-example": "" + } + }, + "required": [ + "otp" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete authenticator", + "operationId": "accountDeleteMfaAuthenticator", + "tags": [ + "account" + ], + "description": "Delete an authenticator for a user by ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteMfaAuthenticator", + "group": "mfa", + "weight": 52, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "type", + "description": "Type of authenticator.", + "required": true, + "schema": { + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [] + }, + "in": "path" + } + ] + } + }, + "\/account\/mfa\/challenge": { + "post": { + "summary": "Create MFA challenge", + "operationId": "accountCreateMfaChallenge", + "tags": [ + "account" + ], + "description": "Begin the process of MFA verification after sign-in. Finish the flow with [updateMfaChallenge](\/docs\/references\/cloud\/client-web\/account#updateMfaChallenge) method.", + "responses": { + "201": { + "description": "MFA Challenge", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaChallenge" + } + } + } + } + }, + "x-appwrite": { + "method": "createMfaChallenge", + "group": "mfa", + "weight": 53, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-mfa-challenge.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-mfa-challenge.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{userId}", + "scope": "account", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "factor": { + "type": "string", + "description": "Factor used for verification. Must be one of following: `email`, `phone`, `totp`, `recoveryCode`.", + "x-example": "email", + "enum": [ + "email", + "phone", + "totp", + "recoverycode" + ], + "x-enum-name": "AuthenticationFactor", + "x-enum-keys": [] + } + }, + "required": [ + "factor" + ] + } + } + } + } + }, + "put": { + "summary": "Update MFA challenge (confirmation)", + "operationId": "accountUpdateMfaChallenge", + "tags": [ + "account" + ], + "description": "Complete the MFA challenge by providing the one-time password. Finish the process of MFA verification by providing the one-time password. To begin the flow, use [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method.", + "responses": { + "200": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMfaChallenge", + "group": "mfa", + "weight": 54, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-mfa-challenge.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa-challenge.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},challengeId:{param-challengeId}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "challengeId": { + "type": "string", + "description": "ID of the challenge.", + "x-example": "" + }, + "otp": { + "type": "string", + "description": "Valid verification token.", + "x-example": "" + } + }, + "required": [ + "challengeId", + "otp" + ] + } + } + } + } + } + }, + "\/account\/mfa\/factors": { + "get": { + "summary": "List factors", + "operationId": "accountListMfaFactors", + "tags": [ + "account" + ], + "description": "List the factors available on the account to be used as a MFA challange.", + "responses": { + "200": { + "description": "MFAFactors", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaFactors" + } + } + } + } + }, + "x-appwrite": { + "method": "listMfaFactors", + "group": "mfa", + "weight": 46, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-mfa-factors.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-mfa-factors.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + } + }, + "\/account\/mfa\/recovery-codes": { + "get": { + "summary": "List MFA recovery codes", + "operationId": "accountGetMfaRecoveryCodes", + "tags": [ + "account" + ], + "description": "Get recovery codes that can be used as backup for MFA flow. Before getting codes, they must be generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method. An OTP challenge is required to read recovery codes.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaRecoveryCodes" + } + } + } + } + }, + "x-appwrite": { + "method": "getMfaRecoveryCodes", + "group": "mfa", + "weight": 51, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + }, + "post": { + "summary": "Create MFA recovery codes", + "operationId": "accountCreateMfaRecoveryCodes", + "tags": [ + "account" + ], + "description": "Generate recovery codes as backup for MFA flow. It's recommended to generate and show then immediately after user successfully adds their authehticator. Recovery codes can be used as a MFA verification type in [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method.", + "responses": { + "201": { + "description": "MFA Recovery Codes", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaRecoveryCodes" + } + } + } + } + }, + "x-appwrite": { + "method": "createMfaRecoveryCodes", + "group": "mfa", + "weight": 49, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + }, + "patch": { + "summary": "Update MFA recovery codes (regenerate)", + "operationId": "accountUpdateMfaRecoveryCodes", + "tags": [ + "account" + ], + "description": "Regenerate recovery codes that can be used as backup for MFA flow. Before regenerating codes, they must be first generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method. An OTP challenge is required to regenreate recovery codes.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaRecoveryCodes" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMfaRecoveryCodes", + "group": "mfa", + "weight": 50, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + } + }, + "\/account\/name": { + "patch": { + "summary": "Update name", + "operationId": "accountUpdateName", + "tags": [ + "account" + ], + "description": "Update currently logged in user account name.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateName", + "group": "account", + "weight": 33, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-name.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-name.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "" + } + }, + "required": [ + "name" + ] + } + } + } + } + } + }, + "\/account\/password": { + "patch": { + "summary": "Update password", + "operationId": "accountUpdatePassword", + "tags": [ + "account" + ], + "description": "Update currently logged in user password. For validation, user is required to pass in the new password, and the old password. For users created with OAuth, Team Invites and Magic URL, oldPassword is optional.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePassword", + "group": "account", + "weight": 34, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-password.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-password.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "password": { + "type": "string", + "description": "New user password. Must be at least 8 chars.", + "x-example": null + }, + "oldPassword": { + "type": "string", + "description": "Current user password. Must be at least 8 chars.", + "x-example": "password" + } + }, + "required": [ + "password" + ] + } + } + } + } + } + }, + "\/account\/phone": { + "patch": { + "summary": "Update phone", + "operationId": "accountUpdatePhone", + "tags": [ + "account" + ], + "description": "Update the currently logged in user's phone number. After updating the phone number, the phone verification status will be reset. A confirmation SMS is not sent automatically, however you can use the [POST \/account\/verification\/phone](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createPhoneVerification) endpoint to send a confirmation SMS.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePhone", + "group": "account", + "weight": 36, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-phone.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-phone.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "x-example": "+12065550100" + }, + "password": { + "type": "string", + "description": "User password. Must be at least 8 chars.", + "x-example": "password" + } + }, + "required": [ + "phone", + "password" + ] + } + } + } + } + } + }, + "\/account\/prefs": { + "get": { + "summary": "Get account preferences", + "operationId": "accountGetPrefs", + "tags": [ + "account" + ], + "description": "Get the preferences as a key-value object for the currently logged in user.", + "responses": { + "200": { + "description": "Preferences", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/preferences" + } + } + } + } + }, + "x-appwrite": { + "method": "getPrefs", + "group": "account", + "weight": 31, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + }, + "patch": { + "summary": "Update preferences", + "operationId": "accountUpdatePrefs", + "tags": [ + "account" + ], + "description": "Update currently logged in user account preferences. The object you pass is stored as is, and replaces any previous value. The maximum allowed prefs size is 64kB and throws error if exceeded.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePrefs", + "group": "account", + "weight": 37, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "prefs": { + "type": "object", + "description": "Prefs key-value JSON object.", + "x-example": "{}" + } + }, + "required": [ + "prefs" + ] + } + } + } + } + } + }, + "\/account\/recovery": { + "post": { + "summary": "Create password recovery", + "operationId": "accountCreateRecovery", + "tags": [ + "account" + ], + "description": "Sends the user an email with a temporary secret key for password reset. When the user clicks the confirmation link he is redirected back to your app password reset URL with the secret key and email address values attached to the URL query string. Use the query string params to submit a request to the [PUT \/account\/recovery](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updateRecovery) endpoint to complete the process. The verification link sent to the user's email address is valid for 1 hour.", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createRecovery", + "group": "recovery", + "weight": 39, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-recovery.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-recovery.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},email:{param-email}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "x-example": "https:\/\/example.com" + } + }, + "required": [ + "email", + "url" + ] + } + } + } + } + }, + "put": { + "summary": "Update password recovery (confirmation)", + "operationId": "accountUpdateRecovery", + "tags": [ + "account" + ], + "description": "Use this endpoint to complete the user account password reset. Both the **userId** and **secret** arguments will be passed as query parameters to the redirect URL you have provided when sending your request to the [POST \/account\/recovery](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createRecovery) endpoint.\n\nPlease note that in order to avoid a [Redirect Attack](https:\/\/github.com\/OWASP\/CheatSheetSeries\/blob\/master\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) the only valid redirect URLs are the ones from domains you have set when adding your platforms in the console interface.", + "responses": { + "200": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "updateRecovery", + "group": "recovery", + "weight": 40, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-recovery.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-recovery.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "" + }, + "secret": { + "type": "string", + "description": "Valid reset token.", + "x-example": "" + }, + "password": { + "type": "string", + "description": "New user password. Must be between 8 and 256 chars.", + "x-example": null + } + }, + "required": [ + "userId", + "secret", + "password" + ] + } + } + } + } + } + }, + "\/account\/sessions": { + "get": { + "summary": "List sessions", + "operationId": "accountListSessions", + "tags": [ + "account" + ], + "description": "Get the list of active sessions across different devices for the currently logged in user.", + "responses": { + "200": { + "description": "Sessions List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/sessionList" + } + } + } + } + }, + "x-appwrite": { + "method": "listSessions", + "group": "sessions", + "weight": 12, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-sessions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + }, + "delete": { + "summary": "Delete sessions", + "operationId": "accountDeleteSessions", + "tags": [ + "account" + ], + "description": "Delete all sessions from the user account and remove any sessions cookies from the end client.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSessions", + "group": "sessions", + "weight": 13, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-sessions.md", + "rate-limit": 100, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + } + }, + "\/account\/sessions\/anonymous": { + "post": { + "summary": "Create anonymous session", + "operationId": "accountCreateAnonymousSession", + "tags": [ + "account" + ], + "description": "Use this endpoint to allow a new user to register an anonymous account in your project. This route will also create a new session for the user. To allow the new user to convert an anonymous account to a normal account, you need to update its [email and password](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updateEmail) or create an [OAuth2 session](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#CreateOAuth2Session).", + "responses": { + "201": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "createAnonymousSession", + "group": "sessions", + "weight": 18, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-anonymous-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session-anonymous.md", + "rate-limit": 50, + "rate-time": 3600, + "rate-key": "ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ] + } + }, + "\/account\/sessions\/email": { + "post": { + "summary": "Create email password session", + "operationId": "accountCreateEmailPasswordSession", + "tags": [ + "account" + ], + "description": "Allow the user to login into their account by providing a valid email and password combination. This route will create a new session for the user.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "201": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "createEmailPasswordSession", + "group": "sessions", + "weight": 17, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-email-password-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session-email-password.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},email:{param-email}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password. Must be at least 8 chars.", + "x-example": "password" + } + }, + "required": [ + "email", + "password" + ] + } + } + } + } + } + }, + "\/account\/sessions\/magic-url": { + "put": { + "summary": "Update magic URL session", + "operationId": "accountUpdateMagicURLSession", + "tags": [ + "account" + ], + "description": "Use this endpoint to create a session from token. Provide the **userId** and **secret** parameters from the successful response of authentication flows initiated by token creation. For example, magic URL and phone login.", + "responses": { + "201": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMagicURLSession", + "group": "sessions", + "weight": 27, + "cookies": false, + "type": "", + "deprecated": true, + "demo": "account\/update-magic-u-r-l-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "ip:{ip},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "x-example": "" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + } + } + } + }, + "\/account\/sessions\/oauth2\/{provider}": { + "get": { + "summary": "Create OAuth2 session", + "operationId": "accountCreateOAuth2Session", + "tags": [ + "account" + ], + "description": "Allow the user to login to their account using the OAuth2 provider of their choice. Each OAuth2 provider should be enabled from the Appwrite console first. Use the success and failure arguments to provide a redirect URL's back to your app when login is completed.\n\nIf there is already an active session, the new session will be attached to the logged-in account. If there are no active sessions, the server will attempt to look for a user with the same email address as the email received from the OAuth2 provider and attach the new session to the existing user. If no matching user is found - the server will create a new user.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "responses": { + "301": { + "description": "File" + } + }, + "x-appwrite": { + "method": "createOAuth2Session", + "group": "sessions", + "weight": 20, + "cookies": false, + "type": "webAuth", + "deprecated": false, + "demo": "account\/create-o-auth2session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session-oauth2.md", + "rate-limit": 50, + "rate-time": 3600, + "rate-key": "ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "provider", + "description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.", + "required": true, + "schema": { + "type": "string", + "x-example": "amazon", + "enum": [ + "amazon", + "apple", + "auth0", + "authentik", + "autodesk", + "bitbucket", + "bitly", + "box", + "dailymotion", + "discord", + "disqus", + "dropbox", + "etsy", + "facebook", + "figma", + "github", + "gitlab", + "google", + "linkedin", + "microsoft", + "notion", + "oidc", + "okta", + "paypal", + "paypalSandbox", + "podio", + "salesforce", + "slack", + "spotify", + "stripe", + "tradeshift", + "tradeshiftBox", + "twitch", + "wordpress", + "yahoo", + "yammer", + "yandex", + "zoho", + "zoom", + "mock" + ], + "x-enum-name": "OAuthProvider", + "x-enum-keys": [] + }, + "in": "path" + }, + { + "name": "success", + "description": "URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "schema": { + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "" + }, + "in": "query" + }, + { + "name": "failure", + "description": "URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "schema": { + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "" + }, + "in": "query" + }, + { + "name": "scopes", + "description": "A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of 100 scopes are allowed, each 4096 characters long.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/account\/sessions\/phone": { + "put": { + "summary": "Update phone session", + "operationId": "accountUpdatePhoneSession", + "tags": [ + "account" + ], + "description": "Use this endpoint to create a session from token. Provide the **userId** and **secret** parameters from the successful response of authentication flows initiated by token creation. For example, magic URL and phone login.", + "responses": { + "201": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePhoneSession", + "group": "sessions", + "weight": 28, + "cookies": false, + "type": "", + "deprecated": true, + "demo": "account\/update-phone-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "ip:{ip},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "x-example": "" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + } + } + } + }, + "\/account\/sessions\/token": { + "post": { + "summary": "Create session", + "operationId": "accountCreateSession", + "tags": [ + "account" + ], + "description": "Use this endpoint to create a session from token. Provide the **userId** and **secret** parameters from the successful response of authentication flows initiated by token creation. For example, magic URL and phone login.", + "responses": { + "201": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "createSession", + "group": "sessions", + "weight": 19, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "ip:{ip},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "secret": { + "type": "string", + "description": "Secret of a token generated by login methods. For example, the `createMagicURLToken` or `createPhoneToken` methods.", + "x-example": "" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + } + } + } + }, + "\/account\/sessions\/{sessionId}": { + "get": { + "summary": "Get session", + "operationId": "accountGetSession", + "tags": [ + "account" + ], + "description": "Use this endpoint to get a logged in user's session using a Session ID. Inputting 'current' will return the current session being used.", + "responses": { + "200": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "getSession", + "group": "sessions", + "weight": 14, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get-session.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "description": "Session ID. Use the string 'current' to get the current device session.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update session", + "operationId": "accountUpdateSession", + "tags": [ + "account" + ], + "description": "Use this endpoint to extend a session's length. Extending a session is useful when session expiry is short. If the session was created using an OAuth provider, this endpoint refreshes the access token from the provider.", + "responses": { + "200": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "updateSession", + "group": "sessions", + "weight": 16, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "description": "Session ID. Use the string 'current' to update the current device session.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete session", + "operationId": "accountDeleteSession", + "tags": [ + "account" + ], + "description": "Logout the user. Use 'current' as the session ID to logout on this device, use a session ID to logout on another device. If you're looking to logout the user on all devices, use [Delete Sessions](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#deleteSessions) instead.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSession", + "group": "sessions", + "weight": 15, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-session.md", + "rate-limit": 100, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "description": "Session ID. Use the string 'current' to delete the current device session.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/account\/status": { + "patch": { + "summary": "Update status", + "operationId": "accountUpdateStatus", + "tags": [ + "account" + ], + "description": "Block the currently logged in user account. Behind the scene, the user record is not deleted but permanently blocked from any access. To completely delete a user, use the Users API instead.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateStatus", + "group": "account", + "weight": 38, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + } + }, + "\/account\/targets\/push": { + "post": { + "summary": "Create push target", + "operationId": "accountCreatePushTarget", + "tags": [ + "account" + ], + "description": "Use this endpoint to register a device for push notifications. Provide a target ID (custom or generated using ID.unique()), a device identifier (usually a device token), and optionally specify which provider should send notifications to this target. The target is automatically linked to the current session and includes device information like brand and model.", + "responses": { + "201": { + "description": "Target", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/target" + } + } + } + } + }, + "x-appwrite": { + "method": "createPushTarget", + "group": "pushTargets", + "weight": 55, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-push-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-push-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "targetId": { + "type": "string", + "description": "Target ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "identifier": { + "type": "string", + "description": "The target identifier (token, email, phone etc.)", + "x-example": "" + }, + "providerId": { + "type": "string", + "description": "Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.", + "x-example": "" + } + }, + "required": [ + "targetId", + "identifier" + ] + } + } + } + } + } + }, + "\/account\/targets\/{targetId}\/push": { + "put": { + "summary": "Update push target", + "operationId": "accountUpdatePushTarget", + "tags": [ + "account" + ], + "description": "Update the currently logged in user's push notification target. You can modify the target's identifier (device token) and provider ID (token, email, phone etc.). The target must exist and belong to the current user. If you change the provider ID, notifications will be sent through the new messaging provider instead.", + "responses": { + "200": { + "description": "Target", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/target" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePushTarget", + "group": "pushTargets", + "weight": 56, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-push-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-push-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "description": "The target identifier (token, email, phone etc.)", + "x-example": "" + } + }, + "required": [ + "identifier" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete push target", + "operationId": "accountDeletePushTarget", + "tags": [ + "account" + ], + "description": "Delete a push notification target for the currently logged in user. After deletion, the device will no longer receive push notifications. The target must exist and belong to the current user.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deletePushTarget", + "group": "pushTargets", + "weight": 57, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-push-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-push-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/account\/tokens\/email": { + "post": { + "summary": "Create email token (OTP)", + "operationId": "accountCreateEmailToken", + "tags": [ + "account" + ], + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not be registered, a new user will be created. Use the returned user ID and secret and submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The secret sent to the user's email is valid for 15 minutes.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createEmailToken", + "group": "tokens", + "weight": 26, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-email-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-email.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},email:{param-email}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "phrase": { + "type": "boolean", + "description": "Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.", + "x-example": false + } + }, + "required": [ + "userId", + "email" + ] + } + } + } + } + } + }, + "\/account\/tokens\/magic-url": { + "post": { + "summary": "Create magic URL token", + "operationId": "accountCreateMagicURLToken", + "tags": [ + "account" + ], + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createMagicURLToken", + "group": "tokens", + "weight": 25, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-magic-u-r-l-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-magic-url.md", + "rate-limit": 60, + "rate-time": 3600, + "rate-key": [ + "url:{url},email:{param-email}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "x-example": "https:\/\/example.com" + }, + "phrase": { + "type": "boolean", + "description": "Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.", + "x-example": false + } + }, + "required": [ + "userId", + "email" + ] + } + } + } + } + } + }, + "\/account\/tokens\/oauth2\/{provider}": { + "get": { + "summary": "Create OAuth2 token", + "operationId": "accountCreateOAuth2Token", + "tags": [ + "account" + ], + "description": "Allow the user to login to their account using the OAuth2 provider of their choice. Each OAuth2 provider should be enabled from the Appwrite console first. Use the success and failure arguments to provide a redirect URL's back to your app when login is completed. \n\nIf authentication succeeds, `userId` and `secret` of a token will be appended to the success URL as query parameters. These can be used to create a new session using the [Create session](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "301": { + "description": "File" + } + }, + "x-appwrite": { + "method": "createOAuth2Token", + "group": "tokens", + "weight": 24, + "cookies": false, + "type": "webAuth", + "deprecated": false, + "demo": "account\/create-o-auth2token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-oauth2.md", + "rate-limit": 50, + "rate-time": 3600, + "rate-key": "ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "provider", + "description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.", + "required": true, + "schema": { + "type": "string", + "x-example": "amazon", + "enum": [ + "amazon", + "apple", + "auth0", + "authentik", + "autodesk", + "bitbucket", + "bitly", + "box", + "dailymotion", + "discord", + "disqus", + "dropbox", + "etsy", + "facebook", + "figma", + "github", + "gitlab", + "google", + "linkedin", + "microsoft", + "notion", + "oidc", + "okta", + "paypal", + "paypalSandbox", + "podio", + "salesforce", + "slack", + "spotify", + "stripe", + "tradeshift", + "tradeshiftBox", + "twitch", + "wordpress", + "yahoo", + "yammer", + "yandex", + "zoho", + "zoom", + "mock" + ], + "x-enum-name": "OAuthProvider", + "x-enum-keys": [] + }, + "in": "path" + }, + { + "name": "success", + "description": "URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "schema": { + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "" + }, + "in": "query" + }, + { + "name": "failure", + "description": "URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "schema": { + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "" + }, + "in": "query" + }, + { + "name": "scopes", + "description": "A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of 100 scopes are allowed, each 4096 characters long.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/account\/tokens\/phone": { + "post": { + "summary": "Create phone token", + "operationId": "accountCreatePhoneToken", + "tags": [ + "account" + ], + "description": "Sends the user an SMS with a secret key for creating a session. If the provided user ID has not be registered, a new user will be created. Use the returned user ID and secret and submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The secret sent to the user's phone is valid for 15 minutes.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createPhoneToken", + "group": "tokens", + "weight": 29, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-phone-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-phone.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},phone:{param-phone}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "x-example": "+12065550100" + } + }, + "required": [ + "userId", + "phone" + ] + } + } + } + } + } + }, + "\/account\/verification": { + "post": { + "summary": "Create email verification", + "operationId": "accountCreateVerification", + "tags": [ + "account" + ], + "description": "Use this endpoint to send a verification message to your user email address to confirm they are the valid owners of that address. Both the **userId** and **secret** arguments will be passed as query parameters to the URL you have provided to be attached to the verification email. The provided URL should redirect the user back to your app and allow you to complete the verification process by verifying both the **userId** and **secret** parameters. Learn more about how to [complete the verification process](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updateVerification). The verification link sent to the user's email address is valid for 7 days.\n\nPlease note that in order to avoid a [Redirect Attack](https:\/\/github.com\/OWASP\/CheatSheetSeries\/blob\/master\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md), the only valid redirect URLs are the ones from domains you have set when adding your platforms in the console interface.\n", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createVerification", + "group": "verification", + "weight": 41, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-email-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{userId}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "x-example": "https:\/\/example.com" + } + }, + "required": [ + "url" + ] + } + } + } + } + }, + "put": { + "summary": "Update email verification (confirmation)", + "operationId": "accountUpdateVerification", + "tags": [ + "account" + ], + "description": "Use this endpoint to complete the user email verification process. Use both the **userId** and **secret** parameters that were attached to your app URL to verify the user email ownership. If confirmed this route will return a 200 status code.", + "responses": { + "200": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "updateVerification", + "group": "verification", + "weight": 42, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-email-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{param-userId}", + "scope": "public", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "x-example": "" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + } + } + } + }, + "\/account\/verification\/phone": { + "post": { + "summary": "Create phone verification", + "operationId": "accountCreatePhoneVerification", + "tags": [ + "account" + ], + "description": "Use this endpoint to send a verification SMS to the currently logged in user. This endpoint is meant for use after updating a user's phone number using the [accountUpdatePhone](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updatePhone) endpoint. Learn more about how to [complete the verification process](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updatePhoneVerification). The verification code sent to the user's phone number is valid for 15 minutes.", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createPhoneVerification", + "group": "verification", + "weight": 43, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-phone-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-phone-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},userId:{userId}", + "url:{url},ip:{ip}" + ], + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + }, + "put": { + "summary": "Update phone verification (confirmation)", + "operationId": "accountUpdatePhoneVerification", + "tags": [ + "account" + ], + "description": "Use this endpoint to complete the user phone verification process. Use the **userId** and **secret** that were sent to your user's phone number to verify the user email ownership. If confirmed this route will return a 200 status code.", + "responses": { + "200": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePhoneVerification", + "group": "verification", + "weight": 44, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-phone-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-phone-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "userId:{param-userId}", + "scope": "public", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "x-example": "" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + } + } + } + }, + "\/avatars\/browsers\/{code}": { + "get": { + "summary": "Get browser icon", + "operationId": "avatarsGetBrowser", + "tags": [ + "avatars" + ], + "description": "You can use this endpoint to show different browser icons to your users. The code argument receives the browser code as it appears in your user [GET \/account\/sessions](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#getSessions) endpoint. Use width, height and quality arguments to change the output settings.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getBrowser", + "group": null, + "weight": 61, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-browser.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-browser.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "code", + "description": "Browser Code.", + "required": true, + "schema": { + "type": "string", + "x-example": "aa", + "enum": [ + "aa", + "an", + "ch", + "ci", + "cm", + "cr", + "ff", + "sf", + "mf", + "ps", + "oi", + "om", + "op", + "on" + ], + "x-enum-name": "Browser", + "x-enum-keys": [ + "Avant Browser", + "Android WebView Beta", + "Google Chrome", + "Google Chrome (iOS)", + "Google Chrome (Mobile)", + "Chromium", + "Mozilla Firefox", + "Safari", + "Mobile Safari", + "Microsoft Edge", + "Microsoft Edge (iOS)", + "Opera Mini", + "Opera", + "Opera (Next)" + ] + }, + "in": "path" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "in": "query" + }, + { + "name": "quality", + "description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1 + }, + "in": "query" + } + ] + } + }, + "\/avatars\/credit-cards\/{code}": { + "get": { + "summary": "Get credit card icon", + "operationId": "avatarsGetCreditCard", + "tags": [ + "avatars" + ], + "description": "The credit card endpoint will return you the icon of the credit card provider you need. Use width, height and quality arguments to change the output settings.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.\n", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getCreditCard", + "group": null, + "weight": 60, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-credit-card.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-credit-card.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "code", + "description": "Credit Card Code. Possible values: amex, argencard, cabal, cencosud, diners, discover, elo, hipercard, jcb, mastercard, naranja, targeta-shopping, union-china-pay, visa, mir, maestro, rupay.", + "required": true, + "schema": { + "type": "string", + "x-example": "amex", + "enum": [ + "amex", + "argencard", + "cabal", + "cencosud", + "diners", + "discover", + "elo", + "hipercard", + "jcb", + "mastercard", + "naranja", + "targeta-shopping", + "union-china-pay", + "visa", + "mir", + "maestro", + "rupay" + ], + "x-enum-name": "CreditCard", + "x-enum-keys": [ + "American Express", + "Argencard", + "Cabal", + "Cencosud", + "Diners Club", + "Discover", + "Elo", + "Hipercard", + "JCB", + "Mastercard", + "Naranja", + "Tarjeta Shopping", + "Union China Pay", + "Visa", + "MIR", + "Maestro", + "Rupay" + ] + }, + "in": "path" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "in": "query" + }, + { + "name": "quality", + "description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1 + }, + "in": "query" + } + ] + } + }, + "\/avatars\/favicon": { + "get": { + "summary": "Get favicon", + "operationId": "avatarsGetFavicon", + "tags": [ + "avatars" + ], + "description": "Use this endpoint to fetch the favorite icon (AKA favicon) of any remote website URL.\n\nThis endpoint does not follow HTTP redirects.", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getFavicon", + "group": null, + "weight": 64, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-favicon.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-favicon.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "url", + "description": "Website URL which you want to fetch the favicon from.", + "required": true, + "schema": { + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com" + }, + "in": "query" + } + ] + } + }, + "\/avatars\/flags\/{code}": { + "get": { + "summary": "Get country flag", + "operationId": "avatarsGetFlag", + "tags": [ + "avatars" + ], + "description": "You can use this endpoint to show different country flags icons to your users. The code argument receives the 2 letter country code. Use width, height and quality arguments to change the output settings. Country codes follow the [ISO 3166-1](https:\/\/en.wikipedia.org\/wiki\/ISO_3166-1) standard.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.\n", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getFlag", + "group": null, + "weight": 62, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-flag.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-flag.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "code", + "description": "Country Code. ISO Alpha-2 country code format.", + "required": true, + "schema": { + "type": "string", + "x-example": "af", + "enum": [ + "af", + "ao", + "al", + "ad", + "ae", + "ar", + "am", + "ag", + "au", + "at", + "az", + "bi", + "be", + "bj", + "bf", + "bd", + "bg", + "bh", + "bs", + "ba", + "by", + "bz", + "bo", + "br", + "bb", + "bn", + "bt", + "bw", + "cf", + "ca", + "ch", + "cl", + "cn", + "ci", + "cm", + "cd", + "cg", + "co", + "km", + "cv", + "cr", + "cu", + "cy", + "cz", + "de", + "dj", + "dm", + "dk", + "do", + "dz", + "ec", + "eg", + "er", + "es", + "ee", + "et", + "fi", + "fj", + "fr", + "fm", + "ga", + "gb", + "ge", + "gh", + "gn", + "gm", + "gw", + "gq", + "gr", + "gd", + "gt", + "gy", + "hn", + "hr", + "ht", + "hu", + "id", + "in", + "ie", + "ir", + "iq", + "is", + "il", + "it", + "jm", + "jo", + "jp", + "kz", + "ke", + "kg", + "kh", + "ki", + "kn", + "kr", + "kw", + "la", + "lb", + "lr", + "ly", + "lc", + "li", + "lk", + "ls", + "lt", + "lu", + "lv", + "ma", + "mc", + "md", + "mg", + "mv", + "mx", + "mh", + "mk", + "ml", + "mt", + "mm", + "me", + "mn", + "mz", + "mr", + "mu", + "mw", + "my", + "na", + "ne", + "ng", + "ni", + "nl", + "no", + "np", + "nr", + "nz", + "om", + "pk", + "pa", + "pe", + "ph", + "pw", + "pg", + "pl", + "pf", + "kp", + "pt", + "py", + "qa", + "ro", + "ru", + "rw", + "sa", + "sd", + "sn", + "sg", + "sb", + "sl", + "sv", + "sm", + "so", + "rs", + "ss", + "st", + "sr", + "sk", + "si", + "se", + "sz", + "sc", + "sy", + "td", + "tg", + "th", + "tj", + "tm", + "tl", + "to", + "tt", + "tn", + "tr", + "tv", + "tz", + "ug", + "ua", + "uy", + "us", + "uz", + "va", + "vc", + "ve", + "vn", + "vu", + "ws", + "ye", + "za", + "zm", + "zw" + ], + "x-enum-name": "Flag", + "x-enum-keys": [ + "Afghanistan", + "Angola", + "Albania", + "Andorra", + "United Arab Emirates", + "Argentina", + "Armenia", + "Antigua and Barbuda", + "Australia", + "Austria", + "Azerbaijan", + "Burundi", + "Belgium", + "Benin", + "Burkina Faso", + "Bangladesh", + "Bulgaria", + "Bahrain", + "Bahamas", + "Bosnia and Herzegovina", + "Belarus", + "Belize", + "Bolivia", + "Brazil", + "Barbados", + "Brunei Darussalam", + "Bhutan", + "Botswana", + "Central African Republic", + "Canada", + "Switzerland", + "Chile", + "China", + "C\u00f4te d'Ivoire", + "Cameroon", + "Democratic Republic of the Congo", + "Republic of the Congo", + "Colombia", + "Comoros", + "Cape Verde", + "Costa Rica", + "Cuba", + "Cyprus", + "Czech Republic", + "Germany", + "Djibouti", + "Dominica", + "Denmark", + "Dominican Republic", + "Algeria", + "Ecuador", + "Egypt", + "Eritrea", + "Spain", + "Estonia", + "Ethiopia", + "Finland", + "Fiji", + "France", + "Micronesia (Federated States of)", + "Gabon", + "United Kingdom", + "Georgia", + "Ghana", + "Guinea", + "Gambia", + "Guinea-Bissau", + "Equatorial Guinea", + "Greece", + "Grenada", + "Guatemala", + "Guyana", + "Honduras", + "Croatia", + "Haiti", + "Hungary", + "Indonesia", + "India", + "Ireland", + "Iran (Islamic Republic of)", + "Iraq", + "Iceland", + "Israel", + "Italy", + "Jamaica", + "Jordan", + "Japan", + "Kazakhstan", + "Kenya", + "Kyrgyzstan", + "Cambodia", + "Kiribati", + "Saint Kitts and Nevis", + "South Korea", + "Kuwait", + "Lao People's Democratic Republic", + "Lebanon", + "Liberia", + "Libya", + "Saint Lucia", + "Liechtenstein", + "Sri Lanka", + "Lesotho", + "Lithuania", + "Luxembourg", + "Latvia", + "Morocco", + "Monaco", + "Moldova", + "Madagascar", + "Maldives", + "Mexico", + "Marshall Islands", + "North Macedonia", + "Mali", + "Malta", + "Myanmar", + "Montenegro", + "Mongolia", + "Mozambique", + "Mauritania", + "Mauritius", + "Malawi", + "Malaysia", + "Namibia", + "Niger", + "Nigeria", + "Nicaragua", + "Netherlands", + "Norway", + "Nepal", + "Nauru", + "New Zealand", + "Oman", + "Pakistan", + "Panama", + "Peru", + "Philippines", + "Palau", + "Papua New Guinea", + "Poland", + "French Polynesia", + "North Korea", + "Portugal", + "Paraguay", + "Qatar", + "Romania", + "Russia", + "Rwanda", + "Saudi Arabia", + "Sudan", + "Senegal", + "Singapore", + "Solomon Islands", + "Sierra Leone", + "El Salvador", + "San Marino", + "Somalia", + "Serbia", + "South Sudan", + "Sao Tome and Principe", + "Suriname", + "Slovakia", + "Slovenia", + "Sweden", + "Eswatini", + "Seychelles", + "Syria", + "Chad", + "Togo", + "Thailand", + "Tajikistan", + "Turkmenistan", + "Timor-Leste", + "Tonga", + "Trinidad and Tobago", + "Tunisia", + "Turkey", + "Tuvalu", + "Tanzania", + "Uganda", + "Ukraine", + "Uruguay", + "United States", + "Uzbekistan", + "Vatican City", + "Saint Vincent and the Grenadines", + "Venezuela", + "Vietnam", + "Vanuatu", + "Samoa", + "Yemen", + "South Africa", + "Zambia", + "Zimbabwe" + ] + }, + "in": "path" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "in": "query" + }, + { + "name": "quality", + "description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1 + }, + "in": "query" + } + ] + } + }, + "\/avatars\/image": { + "get": { + "summary": "Get image from URL", + "operationId": "avatarsGetImage", + "tags": [ + "avatars" + ], + "description": "Use this endpoint to fetch a remote image URL and crop it to any image size you want. This endpoint is very useful if you need to crop and display remote images in your app or in case you want to make sure a 3rd party image is properly served using a TLS protocol.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 400x400px.\n\nThis endpoint does not follow HTTP redirects.", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getImage", + "group": null, + "weight": 63, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-image.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-image.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "url", + "description": "Image URL which you want to crop.", + "required": true, + "schema": { + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com" + }, + "in": "query" + }, + { + "name": "width", + "description": "Resize preview image width, Pass an integer between 0 to 2000. Defaults to 400.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 400 + }, + "in": "query" + }, + { + "name": "height", + "description": "Resize preview image height, Pass an integer between 0 to 2000. Defaults to 400.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 400 + }, + "in": "query" + } + ] + } + }, + "\/avatars\/initials": { + "get": { + "summary": "Get user initials", + "operationId": "avatarsGetInitials", + "tags": [ + "avatars" + ], + "description": "Use this endpoint to show your user initials avatar icon on your website or app. By default, this route will try to print your logged-in user name or email initials. You can also overwrite the user name if you pass the 'name' parameter. If no name is given and no user is logged, an empty avatar will be returned.\n\nYou can use the color and background params to change the avatar colors. By default, a random theme will be selected. The random theme will persist for the user's initials when reloading the same theme will always return for the same initials.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.\n", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getInitials", + "group": null, + "weight": 66, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-initials.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-initials.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "name", + "description": "Full Name. When empty, current user name or email will be used. Max length: 128 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "", + "default": "" + }, + "in": "query" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 500 + }, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 500 + }, + "in": "query" + }, + { + "name": "background", + "description": "Changes background color. By default a random color will be picked and stay will persistent to the given name.", + "required": false, + "schema": { + "type": "string", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/avatars\/qr": { + "get": { + "summary": "Get QR code", + "operationId": "avatarsGetQR", + "tags": [ + "avatars" + ], + "description": "Converts a given plain text to a QR code image. You can use the query parameters to change the size and style of the resulting image.\n", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getQR", + "group": null, + "weight": 65, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-q-r.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-qr.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "text", + "description": "Plain text to be converted to QR code image.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" + }, + { + "name": "size", + "description": "QR code size. Pass an integer between 1 to 1000. Defaults to 400.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 1, + "default": 400 + }, + "in": "query" + }, + { + "name": "margin", + "description": "Margin from edge. Pass an integer between 0 to 10. Defaults to 1.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 1 + }, + "in": "query" + }, + { + "name": "download", + "description": "Return resulting image with 'Content-Disposition: attachment ' headers for the browser to start downloading it. Pass 0 for no header, or 1 for otherwise. Default value is set to 0.", + "required": false, + "schema": { + "type": "boolean", + "x-example": false, + "default": false + }, + "in": "query" + } + ] + } + }, + "\/console\/assistant": { + "post": { + "summary": "Create assistant query", + "operationId": "assistantChat", + "tags": [ + "assistant" + ], + "description": "Send a prompt to the AI assistant and receive a response. This endpoint allows you to interact with Appwrite's AI assistant by sending questions or prompts and receiving helpful responses in real-time through a server-sent events stream. ", + "responses": { + "200": { + "description": "File" + } + }, + "x-appwrite": { + "method": "chat", + "group": "console", + "weight": 310, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "assistant\/chat.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/assistant\/chat.md", + "rate-limit": 15, + "rate-time": 3600, + "rate-key": "userId:{userId}", + "scope": "assistant.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "prompt": { + "type": "string", + "description": "Prompt. A string containing questions asked to the AI assistant.", + "x-example": "" + } + }, + "required": [ + "prompt" + ] + } + } + } + } + } + }, + "\/console\/resources": { + "get": { + "summary": "Check resource ID availability", + "operationId": "consoleGetResource", + "tags": [ + "console" + ], + "description": "Check if a resource ID is available.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "getResource", + "group": null, + "weight": 434, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "console\/get-resource.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCheck if a resource ID is available.", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "userId:{userId}, url:{url}", + "scope": "rules.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "value", + "description": "Resource value.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "query" + }, + { + "name": "type", + "description": "Resource type.", + "required": true, + "schema": { + "type": "string", + "x-example": "rules", + "enum": [ + "rules" + ], + "x-enum-name": "ConsoleResourceType", + "x-enum-keys": [] + }, + "in": "query" + } + ] + } + }, + "\/console\/variables": { + "get": { + "summary": "Get variables", + "operationId": "consoleVariables", + "tags": [ + "console" + ], + "description": "Get all Environment Variables that are relevant for the console.", + "responses": { + "200": { + "description": "Console Variables", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/consoleVariables" + } + } + } + } + }, + "x-appwrite": { + "method": "variables", + "group": "console", + "weight": 309, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "console\/variables.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/console\/variables.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ] + } + }, + "\/databases": { + "get": { + "summary": "List databases", + "operationId": "databasesList", + "tags": [ + "databases" + ], + "description": "Get a list of all databases from the current Appwrite project. You can use the search parameter to filter your results.", + "responses": { + "200": { + "description": "Databases List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/databaseList" + } + } + } + } + }, + "x-appwrite": { + "method": "list", + "group": "databases", + "weight": 71, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create database", + "operationId": "databasesCreate", + "tags": [ + "databases" + ], + "description": "Create a new Database.\n", + "responses": { + "201": { + "description": "Database", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/database" + } + } + } + } + }, + "x-appwrite": { + "method": "create", + "group": "databases", + "weight": 70, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "databaseId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "name": { + "type": "string", + "description": "Database name. Max length: 128 chars.", + "x-example": "" + }, + "enabled": { + "type": "boolean", + "description": "Is the database enabled? When set to 'disabled', users cannot access the database but Server SDKs with an API key can still read and write to the database. No data is lost when this is toggled.", + "x-example": false + } + }, + "required": [ + "databaseId", + "name" + ] + } + } + } + } + } + }, + "\/databases\/usage": { + "get": { + "summary": "Get databases usage stats", + "operationId": "databasesGetUsage", + "tags": [ + "databases" + ], + "description": "Get usage metrics and statistics for all databases in the project. You can view the total number of databases, collections, documents, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.", + "responses": { + "200": { + "description": "UsageDatabases", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/usageDatabases" + } + } + } + } + }, + "x-appwrite": { + "method": "getUsage", + "group": null, + "weight": 121, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-usage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "range", + "description": "`Date range.", + "required": false, + "schema": { + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "DatabaseUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d" + }, + "in": "query" + } + ] + } + }, + "\/databases\/{databaseId}": { + "get": { + "summary": "Get database", + "operationId": "databasesGet", + "tags": [ + "databases" + ], + "description": "Get a database by its unique ID. This endpoint response returns a JSON object with the database metadata.", + "responses": { + "200": { + "description": "Database", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/database" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": "databases", + "weight": 72, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update database", + "operationId": "databasesUpdate", + "tags": [ + "databases" + ], + "description": "Update a database by its unique ID.", + "responses": { + "200": { + "description": "Database", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/database" + } + } + } + } + }, + "x-appwrite": { + "method": "update", + "group": "databases", + "weight": 74, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Database name. Max length: 128 chars.", + "x-example": "" + }, + "enabled": { + "type": "boolean", + "description": "Is database enabled? When set to 'disabled', users cannot access the database but Server SDKs with an API key can still read and write to the database. No data is lost when this is toggled.", + "x-example": false + } + }, + "required": [ + "name" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete database", + "operationId": "databasesDelete", + "tags": [ + "databases" + ], + "description": "Delete a database by its unique ID. Only API keys with with databases.write scope can delete a database.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "databases", + "weight": 75, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections": { + "get": { + "summary": "List collections", + "operationId": "databasesListCollections", + "tags": [ + "databases" + ], + "description": "Get a list of all collections that belong to the provided databaseId. You can use the search parameter to filter your results.", + "responses": { + "200": { + "description": "Collections List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/collectionList" + } + } + } + } + }, + "x-appwrite": { + "method": "listCollections", + "group": "collections", + "weight": 77, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-collections.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-collections.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, enabled, documentSecurity", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create collection", + "operationId": "databasesCreateCollection", + "tags": [ + "databases" + ], + "description": "Create a new Collection. Before using this route, you should create a new database resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "201": { + "description": "Collection", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/collection" + } + } + } + } + }, + "x-appwrite": { + "method": "createCollection", + "group": "collections", + "weight": 76, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-collection.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-collection.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "collectionId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "name": { + "type": "string", + "description": "Collection name. Max length: 128 chars.", + "x-example": "" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "documentSecurity": { + "type": "boolean", + "description": "Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Is collection enabled? When set to 'disabled', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.", + "x-example": false + } + }, + "required": [ + "collectionId", + "name" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}": { + "get": { + "summary": "Get collection", + "operationId": "databasesGetCollection", + "tags": [ + "databases" + ], + "description": "Get a collection by its unique ID. This endpoint response returns a JSON object with the collection metadata.", + "responses": { + "200": { + "description": "Collection", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/collection" + } + } + } + } + }, + "x-appwrite": { + "method": "getCollection", + "group": "collections", + "weight": 78, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-collection.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-collection.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update collection", + "operationId": "databasesUpdateCollection", + "tags": [ + "databases" + ], + "description": "Update a collection by its unique ID.", + "responses": { + "200": { + "description": "Collection", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/collection" + } + } + } + } + }, + "x-appwrite": { + "method": "updateCollection", + "group": "collections", + "weight": 80, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-collection.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-collection.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Collection name. Max length: 128 chars.", + "x-example": "" + }, + "permissions": { + "type": "array", + "description": "An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "documentSecurity": { + "type": "boolean", + "description": "Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Is collection enabled? When set to 'disabled', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.", + "x-example": false + } + }, + "required": [ + "name" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete collection", + "operationId": "databasesDeleteCollection", + "tags": [ + "databases" + ], + "description": "Delete a collection by its unique ID. Only users with write permissions have access to delete this resource.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteCollection", + "group": "collections", + "weight": 81, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-collection.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-collection.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes": { + "get": { + "summary": "List attributes", + "operationId": "databasesListAttributes", + "tags": [ + "databases" + ], + "description": "List attributes in the collection.", + "responses": { + "200": { + "description": "Attributes List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeList" + } + } + } + } + }, + "x-appwrite": { + "method": "listAttributes", + "group": "attributes", + "weight": 92, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-attributes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-attributes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: key, type, size, required, array, status, error", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/boolean": { + "post": { + "summary": "Create boolean attribute", + "operationId": "databasesCreateBooleanAttribute", + "tags": [ + "databases" + ], + "description": "Create a boolean attribute.\n", + "responses": { + "202": { + "description": "AttributeBoolean", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeBoolean" + } + } + } + } + }, + "x-appwrite": { + "method": "createBooleanAttribute", + "group": "attributes", + "weight": 89, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-boolean-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-boolean-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "boolean", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": false + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/boolean\/{key}": { + "patch": { + "summary": "Update boolean attribute", + "operationId": "databasesUpdateBooleanAttribute", + "tags": [ + "databases" + ], + "description": "Update a boolean attribute. Changing the `default` value will not update already existing documents.", + "responses": { + "200": { + "description": "AttributeBoolean", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeBoolean" + } + } + } + } + }, + "x-appwrite": { + "method": "updateBooleanAttribute", + "group": "attributes", + "weight": 101, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-boolean-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-boolean-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "boolean", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": false, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/datetime": { + "post": { + "summary": "Create datetime attribute", + "operationId": "databasesCreateDatetimeAttribute", + "tags": [ + "databases" + ], + "description": "Create a date time attribute according to the ISO 8601 standard.", + "responses": { + "202": { + "description": "AttributeDatetime", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeDatetime" + } + } + } + } + }, + "x-appwrite": { + "method": "createDatetimeAttribute", + "group": "attributes", + "weight": 90, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-datetime-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-datetime-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for the attribute in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when attribute is required.", + "x-example": null + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/datetime\/{key}": { + "patch": { + "summary": "Update dateTime attribute", + "operationId": "databasesUpdateDatetimeAttribute", + "tags": [ + "databases" + ], + "description": "Update a date time attribute. Changing the `default` value will not update already existing documents.", + "responses": { + "200": { + "description": "AttributeDatetime", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeDatetime" + } + } + } + } + }, + "x-appwrite": { + "method": "updateDatetimeAttribute", + "group": "attributes", + "weight": 102, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-datetime-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-datetime-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": null, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/email": { + "post": { + "summary": "Create email attribute", + "operationId": "databasesCreateEmailAttribute", + "tags": [ + "databases" + ], + "description": "Create an email attribute.\n", + "responses": { + "202": { + "description": "AttributeEmail", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeEmail" + } + } + } + } + }, + "x-appwrite": { + "method": "createEmailAttribute", + "group": "attributes", + "weight": 83, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-email-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-email-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "email@example.com" + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/email\/{key}": { + "patch": { + "summary": "Update email attribute", + "operationId": "databasesUpdateEmailAttribute", + "tags": [ + "databases" + ], + "description": "Update an email attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeEmail", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeEmail" + } + } + } + } + }, + "x-appwrite": { + "method": "updateEmailAttribute", + "group": "attributes", + "weight": 95, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-email-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-email-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "email@example.com", + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/enum": { + "post": { + "summary": "Create enum attribute", + "operationId": "databasesCreateEnumAttribute", + "tags": [ + "databases" + ], + "description": "Create an enumeration attribute. The `elements` param acts as a white-list of accepted values for this attribute. \n", + "responses": { + "202": { + "description": "AttributeEnum", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeEnum" + } + } + } + } + }, + "x-appwrite": { + "method": "createEnumAttribute", + "group": "attributes", + "weight": 84, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-enum-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-attribute-enum.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "elements": { + "type": "array", + "description": "Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of 100 elements are allowed, each 255 characters long.", + "x-example": null, + "items": { + "type": "string" + } + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "" + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false + } + }, + "required": [ + "key", + "elements", + "required" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/enum\/{key}": { + "patch": { + "summary": "Update enum attribute", + "operationId": "databasesUpdateEnumAttribute", + "tags": [ + "databases" + ], + "description": "Update an enum attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeEnum", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeEnum" + } + } + } + } + }, + "x-appwrite": { + "method": "updateEnumAttribute", + "group": "attributes", + "weight": 96, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-enum-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-enum-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "elements": { + "type": "array", + "description": "Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of 100 elements are allowed, each 255 characters long.", + "x-example": null, + "items": { + "type": "string" + } + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "", + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + }, + "required": [ + "elements", + "required", + "default" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/float": { + "post": { + "summary": "Create float attribute", + "operationId": "databasesCreateFloatAttribute", + "tags": [ + "databases" + ], + "description": "Create a float attribute. Optionally, minimum and maximum values can be provided.\n", + "responses": { + "202": { + "description": "AttributeFloat", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeFloat" + } + } + } + } + }, + "x-appwrite": { + "method": "createFloatAttribute", + "group": "attributes", + "weight": 88, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-float-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-float-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "min": { + "type": "number", + "description": "Minimum value to enforce on new documents", + "x-example": null + }, + "max": { + "type": "number", + "description": "Maximum value to enforce on new documents", + "x-example": null + }, + "default": { + "type": "number", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": null + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/float\/{key}": { + "patch": { + "summary": "Update float attribute", + "operationId": "databasesUpdateFloatAttribute", + "tags": [ + "databases" + ], + "description": "Update a float attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeFloat", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeFloat" + } + } + } + } + }, + "x-appwrite": { + "method": "updateFloatAttribute", + "group": "attributes", + "weight": 100, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-float-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-float-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "min": { + "type": "number", + "description": "Minimum value to enforce on new documents", + "x-example": null + }, + "max": { + "type": "number", + "description": "Maximum value to enforce on new documents", + "x-example": null + }, + "default": { + "type": "number", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": null, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/integer": { + "post": { + "summary": "Create integer attribute", + "operationId": "databasesCreateIntegerAttribute", + "tags": [ + "databases" + ], + "description": "Create an integer attribute. Optionally, minimum and maximum values can be provided.\n", + "responses": { + "202": { + "description": "AttributeInteger", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeInteger" + } + } + } + } + }, + "x-appwrite": { + "method": "createIntegerAttribute", + "group": "attributes", + "weight": 87, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-integer-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-integer-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "min": { + "type": "integer", + "description": "Minimum value to enforce on new documents", + "x-example": null + }, + "max": { + "type": "integer", + "description": "Maximum value to enforce on new documents", + "x-example": null + }, + "default": { + "type": "integer", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": null + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/integer\/{key}": { + "patch": { + "summary": "Update integer attribute", + "operationId": "databasesUpdateIntegerAttribute", + "tags": [ + "databases" + ], + "description": "Update an integer attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeInteger", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeInteger" + } + } + } + } + }, + "x-appwrite": { + "method": "updateIntegerAttribute", + "group": "attributes", + "weight": 99, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-integer-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-integer-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "min": { + "type": "integer", + "description": "Minimum value to enforce on new documents", + "x-example": null + }, + "max": { + "type": "integer", + "description": "Maximum value to enforce on new documents", + "x-example": null + }, + "default": { + "type": "integer", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": null, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/ip": { + "post": { + "summary": "Create IP address attribute", + "operationId": "databasesCreateIpAttribute", + "tags": [ + "databases" + ], + "description": "Create IP address attribute.\n", + "responses": { + "202": { + "description": "AttributeIP", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeIp" + } + } + } + } + }, + "x-appwrite": { + "method": "createIpAttribute", + "group": "attributes", + "weight": 85, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-ip-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-ip-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": null + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/ip\/{key}": { + "patch": { + "summary": "Update IP address attribute", + "operationId": "databasesUpdateIpAttribute", + "tags": [ + "databases" + ], + "description": "Update an ip attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeIP", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeIp" + } + } + } + } + }, + "x-appwrite": { + "method": "updateIpAttribute", + "group": "attributes", + "weight": 97, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-ip-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-ip-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": null, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/relationship": { + "post": { + "summary": "Create relationship attribute", + "operationId": "databasesCreateRelationshipAttribute", + "tags": [ + "databases" + ], + "description": "Create relationship attribute. [Learn more about relationship attributes](https:\/\/appwrite.io\/docs\/databases-relationships#relationship-attributes).\n", + "responses": { + "202": { + "description": "AttributeRelationship", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeRelationship" + } + } + } + } + }, + "x-appwrite": { + "method": "createRelationshipAttribute", + "group": "attributes", + "weight": 91, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-relationship-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-relationship-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "relatedCollectionId": { + "type": "string", + "description": "Related Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "x-example": "" + }, + "type": { + "type": "string", + "description": "Relation type", + "x-example": "oneToOne", + "enum": [ + "oneToOne", + "manyToOne", + "manyToMany", + "oneToMany" + ], + "x-enum-name": "RelationshipType", + "x-enum-keys": [] + }, + "twoWay": { + "type": "boolean", + "description": "Is Two Way?", + "x-example": false + }, + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "twoWayKey": { + "type": "string", + "description": "Two Way Attribute Key.", + "x-example": null + }, + "onDelete": { + "type": "string", + "description": "Constraints option", + "x-example": "cascade", + "enum": [ + "cascade", + "restrict", + "setNull" + ], + "x-enum-name": "RelationMutate", + "x-enum-keys": [] + } + }, + "required": [ + "relatedCollectionId", + "type" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/string": { + "post": { + "summary": "Create string attribute", + "operationId": "databasesCreateStringAttribute", + "tags": [ + "databases" + ], + "description": "Create a string attribute.\n", + "responses": { + "202": { + "description": "AttributeString", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeString" + } + } + } + } + }, + "x-appwrite": { + "method": "createStringAttribute", + "group": "attributes", + "weight": 82, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-string-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-string-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "size": { + "type": "integer", + "description": "Attribute size for text attributes, in number of characters.", + "x-example": 1 + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "" + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false + }, + "encrypt": { + "type": "boolean", + "description": "Toggle encryption for the attribute. Encryption enhances security by not storing any plain text values in the database. However, encrypted attributes cannot be queried.", + "x-example": false + } + }, + "required": [ + "key", + "size", + "required" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/string\/{key}": { + "patch": { + "summary": "Update string attribute", + "operationId": "databasesUpdateStringAttribute", + "tags": [ + "databases" + ], + "description": "Update a string attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeString", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeString" + } + } + } + } + }, + "x-appwrite": { + "method": "updateStringAttribute", + "group": "attributes", + "weight": 94, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-string-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-string-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "", + "x-nullable": true + }, + "size": { + "type": "integer", + "description": "Maximum size of the string attribute.", + "x-example": 1 + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/url": { + "post": { + "summary": "Create URL attribute", + "operationId": "databasesCreateUrlAttribute", + "tags": [ + "databases" + ], + "description": "Create a URL attribute.\n", + "responses": { + "202": { + "description": "AttributeURL", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeUrl" + } + } + } + } + }, + "x-appwrite": { + "method": "createUrlAttribute", + "group": "attributes", + "weight": 86, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-url-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-url-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "https:\/\/example.com" + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/url\/{key}": { + "patch": { + "summary": "Update URL attribute", + "operationId": "databasesUpdateUrlAttribute", + "tags": [ + "databases" + ], + "description": "Update an url attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeURL", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeUrl" + } + } + } + } + }, + "x-appwrite": { + "method": "updateUrlAttribute", + "group": "attributes", + "weight": 98, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-url-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-url-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "https:\/\/example.com", + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/{key}": { + "get": { + "summary": "Get attribute", + "operationId": "databasesGetAttribute", + "tags": [ + "databases" + ], + "description": "Get attribute by ID.", + "responses": { + "200": { + "description": "AttributeBoolean, or AttributeInteger, or AttributeFloat, or AttributeEmail, or AttributeEnum, or AttributeURL, or AttributeIP, or AttributeDatetime, or AttributeRelationship, or AttributeString", + "content": { + "application\/json": { + "schema": { + "oneOf": [ + { + "$ref": "#\/components\/schemas\/attributeBoolean" + }, + { + "$ref": "#\/components\/schemas\/attributeInteger" + }, + { + "$ref": "#\/components\/schemas\/attributeFloat" + }, + { + "$ref": "#\/components\/schemas\/attributeEmail" + }, + { + "$ref": "#\/components\/schemas\/attributeEnum" + }, + { + "$ref": "#\/components\/schemas\/attributeUrl" + }, + { + "$ref": "#\/components\/schemas\/attributeIp" + }, + { + "$ref": "#\/components\/schemas\/attributeDatetime" + }, + { + "$ref": "#\/components\/schemas\/attributeRelationship" + }, + { + "$ref": "#\/components\/schemas\/attributeString" + } + ] + } + } + } + } + }, + "x-appwrite": { + "method": "getAttribute", + "group": "attributes", + "weight": 93, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete attribute", + "operationId": "databasesDeleteAttribute", + "tags": [ + "databases" + ], + "description": "Deletes an attribute.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteAttribute", + "group": "attributes", + "weight": 104, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/{key}\/relationship": { + "patch": { + "summary": "Update relationship attribute", + "operationId": "databasesUpdateRelationshipAttribute", + "tags": [ + "databases" + ], + "description": "Update relationship attribute. [Learn more about relationship attributes](https:\/\/appwrite.io\/docs\/databases-relationships#relationship-attributes).\n", + "responses": { + "200": { + "description": "AttributeRelationship", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeRelationship" + } + } + } + } + }, + "x-appwrite": { + "method": "updateRelationshipAttribute", + "group": "attributes", + "weight": 103, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-relationship-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-relationship-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "onDelete": { + "type": "string", + "description": "Constraints option", + "x-example": "cascade", + "enum": [ + "cascade", + "restrict", + "setNull" + ], + "x-enum-name": "RelationMutate", + "x-enum-keys": [] + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + } + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents": { + "get": { + "summary": "List documents", + "operationId": "databasesListDocuments", + "tags": [ + "databases" + ], + "description": "Get a list of all the user's documents in a given collection. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Documents List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/documentList" + } + } + } + } + }, + "x-appwrite": { + "method": "listDocuments", + "group": "documents", + "weight": 110, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-documents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-documents.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create document", + "operationId": "databasesCreateDocument", + "tags": [ + "databases" + ], + "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "201": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "createDocument", + "group": "documents", + "weight": 109, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "methods": [ + { + "name": "createDocument", + "auth": { + "Session": [], + "Key": [], + "JWT": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documentId", + "data", + "permissions" + ], + "required": [ + "databaseId", + "collectionId", + "documentId", + "data" + ], + "responses": [ + { + "code": 201, + "model": "#\/components\/schemas\/document" + } + ], + "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/components\/schemas\/documentList" + } + ], + "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + } + ], + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection). Make sure to define attributes before creating documents.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "documentId": { + "type": "string", + "description": "Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "data": { + "type": "object", + "description": "Document data as JSON object.", + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "documents": { + "type": "array", + "description": "Array of documents data as JSON objects.", + "x-example": null, + "items": { + "type": "object" + } + } + } + } + } + } + } + }, + "put": { + "summary": "Create or update documents", + "operationId": "databasesUpsertDocuments", + "tags": [ + "databases" + ], + "description": "Create or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n", + "responses": { + "200": { + "description": "Documents List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/documentList" + } + } + } + } + }, + "x-appwrite": { + "method": "upsertDocuments", + "group": "documents", + "weight": 118, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-documents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-documents.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "documents": { + "type": "array", + "description": "Array of document data as JSON objects. May contain partial documents.", + "x-example": null, + "items": { + "type": "object" + } + } + }, + "required": [ + "documents" + ] + } + } + } + } + }, + "patch": { + "summary": "Update documents", + "operationId": "databasesUpdateDocuments", + "tags": [ + "databases" + ], + "description": "Update all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", + "responses": { + "200": { + "description": "Documents List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/documentList" + } + } + } + } + }, + "x-appwrite": { + "method": "updateDocuments", + "group": "documents", + "weight": 117, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-documents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-documents.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include only attribute and value pairs to be updated.", + "x-example": "{}" + }, + "queries": { + "type": "array", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "x-example": null, + "items": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete documents", + "operationId": "databasesDeleteDocuments", + "tags": [ + "databases" + ], + "description": "Bulk delete documents using queries, if no queries are passed then all documents are deleted.", + "responses": { + "200": { + "description": "Documents List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/documentList" + } + } + } + } + }, + "x-appwrite": { + "method": "deleteDocuments", + "group": "documents", + "weight": 120, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-documents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-documents.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "queries": { + "type": "array", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "x-example": null, + "items": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}": { + "get": { + "summary": "Get document", + "operationId": "databasesGetDocument", + "tags": [ + "databases" + ], + "description": "Get a document by its unique ID. This endpoint response returns a JSON object with the document data.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "getDocument", + "group": "documents", + "weight": 111, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-document.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "put": { + "summary": "Upsert document", + "operationId": "databasesUpsertDocument", + "tags": [ + "databases" + ], + "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "upsertDocument", + "group": "documents", + "weight": 114, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include all required attributes of the document to be created or updated.", + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "data" + ] + } + } + } + } + }, + "patch": { + "summary": "Update document", + "operationId": "databasesUpdateDocument", + "tags": [ + "databases" + ], + "description": "Update a document by its unique ID. Using the patch method you can pass only specific fields that will get updated.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "updateDocument", + "group": "documents", + "weight": 113, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include only attribute and value pairs to be updated.", + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete document", + "operationId": "databasesDeleteDocument", + "tags": [ + "databases" + ], + "description": "Delete a document by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDocument", + "group": "documents", + "weight": 119, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-document.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/logs": { + "get": { + "summary": "List document logs", + "operationId": "databasesListDocumentLogs", + "tags": [ + "databases" + ], + "description": "Get the document activity logs list by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/logList" + } + } + } + } + }, + "x-appwrite": { + "method": "listDocumentLogs", + "group": "logs", + "weight": 112, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-document-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-document-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/decrement": { + "patch": { + "summary": "Decrement document attribute", + "operationId": "databasesDecrementDocumentAttribute", + "tags": [ + "databases" + ], + "description": "Decrement a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "decrementDocumentAttribute", + "group": "documents", + "weight": 116, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/decrement-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/decrement-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to decrement the attribute by. The value must be a number.", + "x-example": null + }, + "min": { + "type": "mixed", + "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", + "x-example": null + } + } + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/increment": { + "patch": { + "summary": "Increment document attribute", + "operationId": "databasesIncrementDocumentAttribute", + "tags": [ + "databases" + ], + "description": "Increment a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "incrementDocumentAttribute", + "group": "documents", + "weight": 115, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/increment-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/increment-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to increment the attribute by. The value must be a number.", + "x-example": null + }, + "max": { + "type": "mixed", + "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", + "x-example": null + } + } + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/indexes": { + "get": { + "summary": "List indexes", + "operationId": "databasesListIndexes", + "tags": [ + "databases" + ], + "description": "List indexes in the collection.", + "responses": { + "200": { + "description": "Indexes List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/indexList" + } + } + } + } + }, + "x-appwrite": { + "method": "listIndexes", + "group": "indexes", + "weight": 106, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-indexes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-indexes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: key, type, status, attributes, error", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create index", + "operationId": "databasesCreateIndex", + "tags": [ + "databases" + ], + "description": "Creates an index on the attributes listed. Your index should include all the attributes you will query in a single request.\nAttributes can be `key`, `fulltext`, and `unique`.", + "responses": { + "202": { + "description": "Index", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/index" + } + } + } + } + }, + "x-appwrite": { + "method": "createIndex", + "group": "collections", + "weight": 105, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-index.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-index.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Index Key.", + "x-example": null + }, + "type": { + "type": "string", + "description": "Index type.", + "x-example": "key", + "enum": [ + "key", + "fulltext", + "unique" + ], + "x-enum-name": "IndexType", + "x-enum-keys": [] + }, + "attributes": { + "type": "array", + "description": "Array of attributes to index. Maximum of 100 attributes are allowed, each 32 characters long.", + "x-example": null, + "items": { + "type": "string" + } + }, + "orders": { + "type": "array", + "description": "Array of index orders. Maximum of 100 orders are allowed.", + "x-example": null, + "items": { + "type": "string" + } + }, + "lengths": { + "type": "array", + "description": "Length of index. Maximum of 100", + "x-example": null, + "items": { + "type": "integer" + } + } + }, + "required": [ + "key", + "type", + "attributes" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/indexes\/{key}": { + "get": { + "summary": "Get index", + "operationId": "databasesGetIndex", + "tags": [ + "databases" + ], + "description": "Get index by ID.", + "responses": { + "200": { + "description": "Index", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/index" + } + } + } + } + }, + "x-appwrite": { + "method": "getIndex", + "group": "indexes", + "weight": 107, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-index.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-index.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "key", + "description": "Index Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete index", + "operationId": "databasesDeleteIndex", + "tags": [ + "databases" + ], + "description": "Delete an index.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteIndex", + "group": "indexes", + "weight": 108, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-index.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-index.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "key", + "description": "Index Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/logs": { + "get": { + "summary": "List collection logs", + "operationId": "databasesListCollectionLogs", + "tags": [ + "databases" + ], + "description": "Get the collection activity logs list by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/logList" + } + } + } + } + }, + "x-appwrite": { + "method": "listCollectionLogs", + "group": "collections", + "weight": 79, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-collection-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-collection-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/usage": { + "get": { + "summary": "Get collection usage stats", + "operationId": "databasesGetCollectionUsage", + "tags": [ + "databases" + ], + "description": "Get usage metrics and statistics for a collection. Returning the total number of documents. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.", + "responses": { + "200": { + "description": "UsageCollection", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/usageCollection" + } + } + } + } + }, + "x-appwrite": { + "method": "getCollectionUsage", + "group": null, + "weight": 123, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-collection-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-collection-usage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "range", + "description": "Date range.", + "required": false, + "schema": { + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "DatabaseUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d" + }, + "in": "query" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/logs": { + "get": { + "summary": "List database logs", + "operationId": "databasesListLogs", + "tags": [ + "databases" + ], + "description": "Get the database activity logs list by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/logList" + } + } + } + } + }, + "x-appwrite": { + "method": "listLogs", + "group": "logs", + "weight": 73, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/databases\/{databaseId}\/usage": { + "get": { + "summary": "Get database usage stats", + "operationId": "databasesGetDatabaseUsage", + "tags": [ + "databases" + ], + "description": "Get usage metrics and statistics for a database. You can view the total number of collections, documents, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.", + "responses": { + "200": { + "description": "UsageDatabase", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/usageDatabase" + } + } + } + } + }, + "x-appwrite": { + "method": "getDatabaseUsage", + "group": null, + "weight": 122, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-database-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-database-usage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "range", + "description": "`Date range.", + "required": false, + "schema": { + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "DatabaseUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d" + }, + "in": "query" + } + ] + } + }, + "\/functions": { + "get": { + "summary": "List functions", + "operationId": "functionsList", + "tags": [ + "functions" + ], + "description": "Get a list of all the project's functions. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Functions List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/functionList" + } + } + } + } + }, + "x-appwrite": { + "method": "list", + "group": "functions", + "weight": 378, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the project's functions. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, enabled, runtime, deploymentId, schedule, scheduleNext, schedulePrevious, timeout, entrypoint, commands, installationId", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create function", + "operationId": "functionsCreate", + "tags": [ + "functions" + ], + "description": "Create a new function. You can pass a list of [permissions](https:\/\/appwrite.io\/docs\/permissions) to allow different project users or team with access to execute the function using the client API.", + "responses": { + "201": { + "description": "Function", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/function" + } + } + } + } + }, + "x-appwrite": { + "method": "create", + "group": "functions", + "weight": 375, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new function. You can pass a list of [permissions](https:\/\/appwrite.io\/docs\/permissions) to allow different project users or team with access to execute the function using the client API.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "functionId": { + "type": "string", + "description": "Function ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "name": { + "type": "string", + "description": "Function name. Max length: 128 chars.", + "x-example": "" + }, + "runtime": { + "type": "string", + "description": "Execution runtime.", + "x-example": "node-14.5", + "enum": [ + "node-14.5", + "node-16.0", + "node-18.0", + "node-19.0", + "node-20.0", + "node-21.0", + "node-22", + "php-8.0", + "php-8.1", + "php-8.2", + "php-8.3", + "ruby-3.0", + "ruby-3.1", + "ruby-3.2", + "ruby-3.3", + "python-3.8", + "python-3.9", + "python-3.10", + "python-3.11", + "python-3.12", + "python-ml-3.11", + "python-ml-3.12", + "deno-1.21", + "deno-1.24", + "deno-1.35", + "deno-1.40", + "deno-1.46", + "deno-2.0", + "dart-2.15", + "dart-2.16", + "dart-2.17", + "dart-2.18", + "dart-2.19", + "dart-3.0", + "dart-3.1", + "dart-3.3", + "dart-3.5", + "dart-3.8", + "dotnet-6.0", + "dotnet-7.0", + "dotnet-8.0", + "java-8.0", + "java-11.0", + "java-17.0", + "java-18.0", + "java-21.0", + "java-22", + "swift-5.5", + "swift-5.8", + "swift-5.9", + "swift-5.10", + "kotlin-1.6", + "kotlin-1.8", + "kotlin-1.9", + "kotlin-2.0", + "cpp-17", + "cpp-20", + "bun-1.0", + "bun-1.1", + "go-1.23", + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29", + "flutter-3.32" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "execute": { + "type": "array", + "description": "An array of role strings with execution permissions. By default no user is granted with any execute permissions. [learn more about roles](https:\/\/appwrite.io\/docs\/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.", + "x-example": "[\"any\"]", + "items": { + "type": "string" + } + }, + "events": { + "type": "array", + "description": "Events list. Maximum of 100 events are allowed.", + "x-example": null, + "items": { + "type": "string" + } + }, + "schedule": { + "type": "string", + "description": "Schedule CRON syntax.", + "x-example": null + }, + "timeout": { + "type": "integer", + "description": "Function maximum execution time in seconds.", + "x-example": 1 + }, + "enabled": { + "type": "boolean", + "description": "Is function enabled? When set to 'disabled', users cannot access the function but Server SDKs with and API key can still access the function. No data is lost when this is toggled.", + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", + "x-example": false + }, + "entrypoint": { + "type": "string", + "description": "Entrypoint File. This path is relative to the \"providerRootDirectory\".", + "x-example": "" + }, + "commands": { + "type": "string", + "description": "Build Commands.", + "x-example": "" + }, + "scopes": { + "type": "array", + "description": "List of scopes allowed for API key auto-generated for every execution. Maximum of 100 scopes are allowed.", + "x-example": null, + "items": { + "type": "string" + } + }, + "installationId": { + "type": "string", + "description": "Appwrite Installation ID for VCS (Version Control System) deployment.", + "x-example": "" + }, + "providerRepositoryId": { + "type": "string", + "description": "Repository ID of the repo linked to the function.", + "x-example": "" + }, + "providerBranch": { + "type": "string", + "description": "Production branch for the repo linked to the function.", + "x-example": "" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is the VCS (Version Control System) connection in silent mode for the repo linked to the function? In silent mode, comments will not be made on commits and pull requests.", + "x-example": false + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to function code in the linked repo.", + "x-example": "" + }, + "specification": { + "type": "string", + "description": "Runtime specification for the function and builds.", + "x-example": null + } + }, + "required": [ + "functionId", + "name", + "runtime" + ] + } + } + } + } + } + }, + "\/functions\/runtimes": { + "get": { + "summary": "List runtimes", + "operationId": "functionsListRuntimes", + "tags": [ + "functions" + ], + "description": "Get a list of all runtimes that are currently active on your instance.", + "responses": { + "200": { + "description": "Runtimes List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/runtimeList" + } + } + } + } + }, + "x-appwrite": { + "method": "listRuntimes", + "group": "runtimes", + "weight": 380, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-runtimes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all runtimes that are currently active on your instance.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/functions\/specifications": { + "get": { + "summary": "List specifications", + "operationId": "functionsListSpecifications", + "tags": [ + "functions" + ], + "description": "List allowed function specifications for this instance.", + "responses": { + "200": { + "description": "Specifications List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/specificationList" + } + } + } + } + }, + "x-appwrite": { + "method": "listSpecifications", + "group": "runtimes", + "weight": 381, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-specifications.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList allowed function specifications for this instance.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/functions\/templates": { + "get": { + "summary": "List templates", + "operationId": "functionsListTemplates", + "tags": [ + "functions" + ], + "description": "List available function templates. You can use template details in [createFunction](\/docs\/references\/cloud\/server-nodejs\/functions#create) method.", + "responses": { + "200": { + "description": "Function Templates List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/templateFunctionList" + } + } + } + } + }, + "x-appwrite": { + "method": "listTemplates", + "group": "templates", + "weight": 404, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-templates.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList available function templates. You can use template details in [createFunction](\/docs\/references\/cloud\/server-nodejs\/functions#create) method.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "runtimes", + "description": "List of runtimes allowed for filtering function templates. Maximum of 100 runtimes are allowed.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "useCases", + "description": "List of use cases allowed for filtering function templates. Maximum of 100 use cases are allowed.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "limit", + "description": "Limit the number of templates returned in the response. Default limit is 25, and maximum limit is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 1, + "default": 25 + }, + "in": "query" + }, + { + "name": "offset", + "description": "Offset the list of returned templates. Maximum offset is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0 + }, + "in": "query" + } + ] + } + }, + "\/functions\/templates\/{templateId}": { + "get": { + "summary": "Get function template", + "operationId": "functionsGetTemplate", + "tags": [ + "functions" + ], + "description": "Get a function template using ID. You can use template details in [createFunction](\/docs\/references\/cloud\/server-nodejs\/functions#create) method.", + "responses": { + "200": { + "description": "Template Function", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/templateFunction" + } + } + } + } + }, + "x-appwrite": { + "method": "getTemplate", + "group": "templates", + "weight": 403, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get-template.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function template using ID. You can use template details in [createFunction](\/docs\/references\/cloud\/server-nodejs\/functions#create) method.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "templateId", + "description": "Template ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/functions\/usage": { + "get": { + "summary": "Get functions usage", + "operationId": "functionsListUsage", + "tags": [ + "functions" + ], + "description": "Get usage metrics and statistics for all functions in the project. View statistics including total deployments, builds, logs, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", + "responses": { + "200": { + "description": "UsageFunctions", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/usageFunctions" + } + } + } + } + }, + "x-appwrite": { + "method": "listUsage", + "group": null, + "weight": 397, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet usage metrics and statistics for all functions in the project. View statistics including total deployments, builds, logs, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "range", + "description": "Date range.", + "required": false, + "schema": { + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "FunctionUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d" + }, + "in": "query" + } + ] + } + }, + "\/functions\/{functionId}": { + "get": { + "summary": "Get function", + "operationId": "functionsGet", + "tags": [ + "functions" + ], + "description": "Get a function by its unique ID.", + "responses": { + "200": { + "description": "Function", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/function" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": "functions", + "weight": 376, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update function", + "operationId": "functionsUpdate", + "tags": [ + "functions" + ], + "description": "Update function by its unique ID.", + "responses": { + "200": { + "description": "Function", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/function" + } + } + } + } + }, + "x-appwrite": { + "method": "update", + "group": "functions", + "weight": 377, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/update.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate function by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Function name. Max length: 128 chars.", + "x-example": "" + }, + "runtime": { + "type": "string", + "description": "Execution runtime.", + "x-example": "node-14.5", + "enum": [ + "node-14.5", + "node-16.0", + "node-18.0", + "node-19.0", + "node-20.0", + "node-21.0", + "node-22", + "php-8.0", + "php-8.1", + "php-8.2", + "php-8.3", + "ruby-3.0", + "ruby-3.1", + "ruby-3.2", + "ruby-3.3", + "python-3.8", + "python-3.9", + "python-3.10", + "python-3.11", + "python-3.12", + "python-ml-3.11", + "python-ml-3.12", + "deno-1.21", + "deno-1.24", + "deno-1.35", + "deno-1.40", + "deno-1.46", + "deno-2.0", + "dart-2.15", + "dart-2.16", + "dart-2.17", + "dart-2.18", + "dart-2.19", + "dart-3.0", + "dart-3.1", + "dart-3.3", + "dart-3.5", + "dart-3.8", + "dotnet-6.0", + "dotnet-7.0", + "dotnet-8.0", + "java-8.0", + "java-11.0", + "java-17.0", + "java-18.0", + "java-21.0", + "java-22", + "swift-5.5", + "swift-5.8", + "swift-5.9", + "swift-5.10", + "kotlin-1.6", + "kotlin-1.8", + "kotlin-1.9", + "kotlin-2.0", + "cpp-17", + "cpp-20", + "bun-1.0", + "bun-1.1", + "go-1.23", + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29", + "flutter-3.32" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "execute": { + "type": "array", + "description": "An array of role strings with execution permissions. By default no user is granted with any execute permissions. [learn more about roles](https:\/\/appwrite.io\/docs\/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.", + "x-example": "[\"any\"]", + "items": { + "type": "string" + } + }, + "events": { + "type": "array", + "description": "Events list. Maximum of 100 events are allowed.", + "x-example": null, + "items": { + "type": "string" + } + }, + "schedule": { + "type": "string", + "description": "Schedule CRON syntax.", + "x-example": null + }, + "timeout": { + "type": "integer", + "description": "Maximum execution time in seconds.", + "x-example": 1 + }, + "enabled": { + "type": "boolean", + "description": "Is function enabled? When set to 'disabled', users cannot access the function but Server SDKs with and API key can still access the function. No data is lost when this is toggled.", + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", + "x-example": false + }, + "entrypoint": { + "type": "string", + "description": "Entrypoint File. This path is relative to the \"providerRootDirectory\".", + "x-example": "" + }, + "commands": { + "type": "string", + "description": "Build Commands.", + "x-example": "" + }, + "scopes": { + "type": "array", + "description": "List of scopes allowed for API Key auto-generated for every execution. Maximum of 100 scopes are allowed.", + "x-example": null, + "items": { + "type": "string" + } + }, + "installationId": { + "type": "string", + "description": "Appwrite Installation ID for VCS (Version Controle System) deployment.", + "x-example": "" + }, + "providerRepositoryId": { + "type": "string", + "description": "Repository ID of the repo linked to the function", + "x-example": "", + "x-nullable": true + }, + "providerBranch": { + "type": "string", + "description": "Production branch for the repo linked to the function", + "x-example": "" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is the VCS (Version Control System) connection in silent mode for the repo linked to the function? In silent mode, comments will not be made on commits and pull requests.", + "x-example": false + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to function code in the linked repo.", + "x-example": "" + }, + "specification": { + "type": "string", + "description": "Runtime specification for the function and builds.", + "x-example": null + } + }, + "required": [ + "name" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete function", + "operationId": "functionsDelete", + "tags": [ + "functions" + ], + "description": "Delete a function by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "functions", + "weight": 379, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a function by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/functions\/{functionId}\/deployment": { + "patch": { + "summary": "Update function's deployment", + "operationId": "functionsUpdateFunctionDeployment", + "tags": [ + "functions" + ], + "description": "Update the function active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your function.", + "responses": { + "200": { + "description": "Function", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/function" + } + } + } + } + }, + "x-appwrite": { + "method": "updateFunctionDeployment", + "group": "functions", + "weight": 384, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/update-function-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate the function active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your function.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "deploymentId": { + "type": "string", + "description": "Deployment ID.", + "x-example": "" + } + }, + "required": [ + "deploymentId" + ] + } + } + } + } + } + }, + "\/functions\/{functionId}\/deployments": { + "get": { + "summary": "List deployments", + "operationId": "functionsListDeployments", + "tags": [ + "functions" + ], + "description": "Get a list of all the function's code deployments. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Deployments List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deploymentList" + } + } + } + } + }, + "x-appwrite": { + "method": "listDeployments", + "group": "deployments", + "weight": 385, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-deployments.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the function's code deployments. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create deployment", + "operationId": "functionsCreateDeployment", + "tags": [ + "functions" + ], + "description": "Create a new function code deployment. Use this endpoint to upload a new version of your code function. To execute your newly uploaded code, you'll need to update the function's deployment to use your new deployment UID.\n\nThis endpoint accepts a tar.gz file compressed with your code. Make sure to include any dependencies your code has within the compressed file. You can learn more about code packaging in the [Appwrite Cloud Functions tutorial](https:\/\/appwrite.io\/docs\/functions).\n\nUse the \"command\" param to set the entrypoint used to execute your code.", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createDeployment", + "group": "deployments", + "weight": 382, + "cookies": false, + "type": "upload", + "deprecated": false, + "demo": "functions\/create-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new function code deployment. Use this endpoint to upload a new version of your code function. To execute your newly uploaded code, you'll need to update the function's deployment to use your new deployment UID.\n\nThis endpoint accepts a tar.gz file compressed with your code. Make sure to include any dependencies your code has within the compressed file. You can learn more about code packaging in the [Appwrite Cloud Functions tutorial](https:\/\/appwrite.io\/docs\/functions).\n\nUse the \"command\" param to set the entrypoint used to execute your code.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": true, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "multipart\/form-data": { + "schema": { + "type": "object", + "properties": { + "entrypoint": { + "type": "string", + "description": "Entrypoint File.", + "x-example": "" + }, + "commands": { + "type": "string", + "description": "Build Commands.", + "x-example": "" + }, + "code": { + "type": "string", + "description": "Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.", + "x-example": null + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "x-example": false + } + }, + "required": [ + "code", + "activate" + ] + } + } + } + } + } + }, + "\/functions\/{functionId}\/deployments\/duplicate": { + "post": { + "summary": "Create duplicate deployment", + "operationId": "functionsCreateDuplicateDeployment", + "tags": [ + "functions" + ], + "description": "Create a new build for an existing function deployment. This endpoint allows you to rebuild a deployment with the updated function configuration, including its entrypoint and build commands if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createDuplicateDeployment", + "group": "deployments", + "weight": 390, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-duplicate-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new build for an existing function deployment. This endpoint allows you to rebuild a deployment with the updated function configuration, including its entrypoint and build commands if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "deploymentId": { + "type": "string", + "description": "Deployment ID.", + "x-example": "" + }, + "buildId": { + "type": "string", + "description": "Build unique ID.", + "x-example": "" + } + }, + "required": [ + "deploymentId" + ] + } + } + } + } + } + }, + "\/functions\/{functionId}\/deployments\/template": { + "post": { + "summary": "Create template deployment", + "operationId": "functionsCreateTemplateDeployment", + "tags": [ + "functions" + ], + "description": "Create a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/functions#listTemplates) to find the template details.", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createTemplateDeployment", + "group": "deployments", + "weight": 387, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-template-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/functions#listTemplates) to find the template details.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "repository": { + "type": "string", + "description": "Repository name of the template.", + "x-example": "" + }, + "owner": { + "type": "string", + "description": "The name of the owner of the template.", + "x-example": "" + }, + "rootDirectory": { + "type": "string", + "description": "Path to function code in the template repo.", + "x-example": "" + }, + "version": { + "type": "string", + "description": "Version (tag) for the repo linked to the function template.", + "x-example": "" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "x-example": false + } + }, + "required": [ + "repository", + "owner", + "rootDirectory", + "version" + ] + } + } + } + } + } + }, + "\/functions\/{functionId}\/deployments\/vcs": { + "post": { + "summary": "Create VCS deployment", + "operationId": "functionsCreateVcsDeployment", + "tags": [ + "functions" + ], + "description": "Create a deployment when a function is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createVcsDeployment", + "group": "deployments", + "weight": 388, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-vcs-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment when a function is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Type of reference passed. Allowed values are: branch, commit", + "x-example": "branch", + "enum": [ + "branch", + "commit" + ], + "x-enum-name": "VCSDeploymentType", + "x-enum-keys": [] + }, + "reference": { + "type": "string", + "description": "VCS reference to create deployment from. Depending on type this can be: branch name, commit hash", + "x-example": "" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "x-example": false + } + }, + "required": [ + "type", + "reference" + ] + } + } + } + } + } + }, + "\/functions\/{functionId}\/deployments\/{deploymentId}": { + "get": { + "summary": "Get deployment", + "operationId": "functionsGetDeployment", + "tags": [ + "functions" + ], + "description": "Get a function deployment by its unique ID.", + "responses": { + "200": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "getDeployment", + "group": "deployments", + "weight": 383, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function deployment by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete deployment", + "operationId": "functionsDeleteDeployment", + "tags": [ + "functions" + ], + "description": "Delete a code deployment by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDeployment", + "group": "deployments", + "weight": 386, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/delete-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a code deployment by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/functions\/{functionId}\/deployments\/{deploymentId}\/download": { + "get": { + "summary": "Get deployment download", + "operationId": "functionsGetDeploymentDownload", + "tags": [ + "functions" + ], + "description": "Get a function deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "responses": { + "200": { + "description": "File" + } + }, + "x-appwrite": { + "method": "getDeploymentDownload", + "group": "deployments", + "weight": 389, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "functions\/get-deployment-download.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "type", + "description": "Deployment file to download. Can be: \"source\", \"output\".", + "required": false, + "schema": { + "type": "string", + "x-example": "source", + "enum": [ + "source", + "output" + ], + "x-enum-name": "DeploymentDownloadType", + "x-enum-keys": [], + "default": "source" + }, + "in": "query" + } + ] + } + }, + "\/functions\/{functionId}\/deployments\/{deploymentId}\/status": { + "patch": { + "summary": "Update deployment status", + "operationId": "functionsUpdateDeploymentStatus", + "tags": [ + "functions" + ], + "description": "Cancel an ongoing function deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", + "responses": { + "200": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "updateDeploymentStatus", + "group": "deployments", + "weight": 391, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/update-deployment-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCancel an ongoing function deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/functions\/{functionId}\/executions": { + "get": { + "summary": "List executions", + "operationId": "functionsListExecutions", + "tags": [ + "functions" + ], + "description": "Get a list of all the current user function execution logs. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Executions List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/executionList" + } + } + } + } + }, + "x-appwrite": { + "method": "listExecutions", + "group": "executions", + "weight": 394, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-executions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the current user function execution logs. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: trigger, status, responseStatusCode, duration, requestMethod, requestPath, deploymentId", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create execution", + "operationId": "functionsCreateExecution", + "tags": [ + "functions" + ], + "description": "Trigger a function execution. The returned object will return you the current execution status. You can ping the `Get Execution` endpoint to get updates on the current execution status. Once this endpoint is called, your function execution process will start asynchronously.", + "responses": { + "201": { + "description": "Execution", + "content": { + "multipart\/form-data": { + "schema": { + "$ref": "#\/components\/schemas\/execution" + } + } + } + } + }, + "x-appwrite": { + "method": "createExecution", + "group": "executions", + "weight": 392, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-execution.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterTrigger a function execution. The returned object will return you the current execution status. You can ping the `Get Execution` endpoint to get updates on the current execution status. Once this endpoint is called, your function execution process will start asynchronously.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "body": { + "type": "string", + "description": "HTTP body of execution. Default value is empty string.", + "x-example": "" + }, + "async": { + "type": "boolean", + "description": "Execute code in the background. Default value is false.", + "x-example": false + }, + "path": { + "type": "string", + "description": "HTTP path of execution. Path can include query params. Default value is \/", + "x-example": "" + }, + "method": { + "type": "string", + "description": "HTTP method of execution. Default value is GET.", + "x-example": "GET", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE", + "OPTIONS" + ], + "x-enum-name": "ExecutionMethod", + "x-enum-keys": [] + }, + "headers": { + "type": "string", + "description": "HTTP headers of execution. Defaults to empty.", + "x-example": null + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled execution time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes.", + "x-example": null + } + } + } + } + } + } + } + }, + "\/functions\/{functionId}\/executions\/{executionId}": { + "get": { + "summary": "Get execution", + "operationId": "functionsGetExecution", + "tags": [ + "functions" + ], + "description": "Get a function execution log by its unique ID.", + "responses": { + "200": { + "description": "Execution", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/execution" + } + } + } + } + }, + "x-appwrite": { + "method": "getExecution", + "group": "executions", + "weight": 393, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get-execution.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function execution log by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "executionId", + "description": "Execution ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete execution", + "operationId": "functionsDeleteExecution", + "tags": [ + "functions" + ], + "description": "Delete a function execution by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteExecution", + "group": "executions", + "weight": 395, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/delete-execution.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a function execution by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "executionId", + "description": "Execution ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/functions\/{functionId}\/usage": { + "get": { + "summary": "Get function usage", + "operationId": "functionsGetUsage", + "tags": [ + "functions" + ], + "description": "Get usage metrics and statistics for a for a specific function. View statistics including total deployments, builds, executions, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", + "responses": { + "200": { + "description": "UsageFunction", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/usageFunction" + } + } + } + } + }, + "x-appwrite": { + "method": "getUsage", + "group": null, + "weight": 396, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet usage metrics and statistics for a for a specific function. View statistics including total deployments, builds, executions, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "range", + "description": "Date range.", + "required": false, + "schema": { + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "FunctionUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d" + }, + "in": "query" + } + ] + } + }, + "\/functions\/{functionId}\/variables": { + "get": { + "summary": "List variables", + "operationId": "functionsListVariables", + "tags": [ + "functions" + ], + "description": "Get a list of all variables of a specific function.", + "responses": { + "200": { + "description": "Variables List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variableList" + } + } + } + } + }, + "x-appwrite": { + "method": "listVariables", + "group": "variables", + "weight": 400, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-variables.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all variables of a specific function.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "post": { + "summary": "Create variable", + "operationId": "functionsCreateVariable", + "tags": [ + "functions" + ], + "description": "Create a new function environment variable. These variables can be accessed in the function at runtime as environment variables.", + "responses": { + "201": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "createVariable", + "group": "variables", + "weight": 398, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new function environment variable. These variables can be accessed in the function at runtime as environment variables.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "x-example": "" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "x-example": "" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only functions can read them during build and runtime.", + "x-example": false + } + }, + "required": [ + "key", + "value" + ] + } + } + } + } + } + }, + "\/functions\/{functionId}\/variables\/{variableId}": { + "get": { + "summary": "Get variable", + "operationId": "functionsGetVariable", + "tags": [ + "functions" + ], + "description": "Get a variable by its unique ID.", + "responses": { + "200": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "getVariable", + "group": "variables", + "weight": 399, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update variable", + "operationId": "functionsUpdateVariable", + "tags": [ + "functions" + ], + "description": "Update variable by its unique ID.", + "responses": { + "200": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "updateVariable", + "group": "variables", + "weight": 401, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/update-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "x-example": "" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "x-example": "" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only functions can read them during build and runtime.", + "x-example": false + } + }, + "required": [ + "key" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete variable", + "operationId": "functionsDeleteVariable", + "tags": [ + "functions" + ], + "description": "Delete a variable by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteVariable", + "group": "variables", + "weight": 402, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/delete-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ] + } + }, + "\/graphql": { + "post": { + "summary": "GraphQL endpoint", + "operationId": "graphqlQuery", + "tags": [ + "graphql" + ], + "description": "Execute a GraphQL mutation.", + "responses": { + "200": { + "description": "Any", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/any" + } + } + } + } + }, + "x-appwrite": { + "method": "query", + "group": "graphql", + "weight": 308, + "cookies": false, + "type": "graphql", + "deprecated": false, + "demo": "graphql\/query.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/graphql\/post.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "url:{url},ip:{ip}", + "scope": "graphql", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/graphql\/mutation": { + "post": { + "summary": "GraphQL endpoint", + "operationId": "graphqlMutation", + "tags": [ + "graphql" + ], + "description": "Execute a GraphQL mutation.", + "responses": { + "200": { + "description": "Any", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/any" + } + } + } + } + }, + "x-appwrite": { + "method": "mutation", + "group": "graphql", + "weight": 307, + "cookies": false, + "type": "graphql", + "deprecated": false, + "demo": "graphql\/mutation.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/graphql\/post.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "url:{url},ip:{ip}", + "scope": "graphql", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/health": { + "get": { + "summary": "Get HTTP", + "operationId": "healthGet", + "tags": [ + "health" + ], + "description": "Check the Appwrite HTTP server is up and responsive.", + "responses": { + "200": { + "description": "Health Status", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthStatus" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": "health", + "weight": 132, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/anti-virus": { + "get": { + "summary": "Get antivirus", + "operationId": "healthGetAntivirus", + "tags": [ + "health" + ], + "description": "Check the Appwrite Antivirus server is up and connection is successful.", + "responses": { + "200": { + "description": "Health Antivirus", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthAntivirus" + } + } + } + } + }, + "x-appwrite": { + "method": "getAntivirus", + "group": "health", + "weight": 153, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-antivirus.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-storage-anti-virus.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/cache": { + "get": { + "summary": "Get cache", + "operationId": "healthGetCache", + "tags": [ + "health" + ], + "description": "Check the Appwrite in-memory cache servers are up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthStatus" + } + } + } + } + }, + "x-appwrite": { + "method": "getCache", + "group": "health", + "weight": 135, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-cache.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-cache.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/certificate": { + "get": { + "summary": "Get the SSL certificate for a domain", + "operationId": "healthGetCertificate", + "tags": [ + "health" + ], + "description": "Get the SSL certificate for a domain", + "responses": { + "200": { + "description": "Health Certificate", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthCertificate" + } + } + } + } + }, + "x-appwrite": { + "method": "getCertificate", + "group": "health", + "weight": 140, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-certificate.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-certificate.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "domain", + "description": "string", + "required": false, + "schema": { + "type": "string" + }, + "in": "query" + } + ] + } + }, + "\/health\/db": { + "get": { + "summary": "Get DB", + "operationId": "healthGetDB", + "tags": [ + "health" + ], + "description": "Check the Appwrite database servers are up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthStatus" + } + } + } + } + }, + "x-appwrite": { + "method": "getDB", + "group": "health", + "weight": 134, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-d-b.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-db.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/pubsub": { + "get": { + "summary": "Get pubsub", + "operationId": "healthGetPubSub", + "tags": [ + "health" + ], + "description": "Check the Appwrite pub-sub servers are up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthStatus" + } + } + } + } + }, + "x-appwrite": { + "method": "getPubSub", + "group": "health", + "weight": 136, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-pub-sub.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-pubsub.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/queue\/builds": { + "get": { + "summary": "Get builds queue", + "operationId": "healthGetQueueBuilds", + "tags": [ + "health" + ], + "description": "Get the number of builds that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueBuilds", + "group": "queue", + "weight": 142, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-builds.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-builds.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/certificates": { + "get": { + "summary": "Get certificates queue", + "operationId": "healthGetQueueCertificates", + "tags": [ + "health" + ], + "description": "Get the number of certificates that are waiting to be issued against [Letsencrypt](https:\/\/letsencrypt.org\/) in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueCertificates", + "group": "queue", + "weight": 141, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-certificates.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-certificates.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/databases": { + "get": { + "summary": "Get databases queue", + "operationId": "healthGetQueueDatabases", + "tags": [ + "health" + ], + "description": "Get the number of database changes that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueDatabases", + "group": "queue", + "weight": 143, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-databases.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-databases.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "name", + "description": "Queue name for which to check the queue size", + "required": false, + "schema": { + "type": "string", + "x-example": "", + "default": "database_db_main" + }, + "in": "query" + }, + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/deletes": { + "get": { + "summary": "Get deletes queue", + "operationId": "healthGetQueueDeletes", + "tags": [ + "health" + ], + "description": "Get the number of background destructive changes that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueDeletes", + "group": "queue", + "weight": 144, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-deletes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-deletes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/failed\/{name}": { + "get": { + "summary": "Get number of failed queue jobs", + "operationId": "healthGetFailedJobs", + "tags": [ + "health" + ], + "description": "Returns the amount of failed jobs in a given queue.\n", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getFailedJobs", + "group": "queue", + "weight": 154, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-failed-jobs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-failed-queue-jobs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "name", + "description": "The name of the queue", + "required": true, + "schema": { + "type": "string", + "x-example": "v1-database", + "enum": [ + "v1-database", + "v1-deletes", + "v1-audits", + "v1-mails", + "v1-functions", + "v1-stats-resources", + "v1-stats-usage", + "v1-webhooks", + "v1-certificates", + "v1-builds", + "v1-messaging", + "v1-migrations" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "in": "path" + }, + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/functions": { + "get": { + "summary": "Get functions queue", + "operationId": "healthGetQueueFunctions", + "tags": [ + "health" + ], + "description": "Get the number of function executions that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueFunctions", + "group": "queue", + "weight": 148, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-functions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-functions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/logs": { + "get": { + "summary": "Get logs queue", + "operationId": "healthGetQueueLogs", + "tags": [ + "health" + ], + "description": "Get the number of logs that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueLogs", + "group": "queue", + "weight": 139, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/mails": { + "get": { + "summary": "Get mails queue", + "operationId": "healthGetQueueMails", + "tags": [ + "health" + ], + "description": "Get the number of mails that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueMails", + "group": "queue", + "weight": 145, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-mails.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-mails.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/messaging": { + "get": { + "summary": "Get messaging queue", + "operationId": "healthGetQueueMessaging", + "tags": [ + "health" + ], + "description": "Get the number of messages that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueMessaging", + "group": "queue", + "weight": 146, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-messaging.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-messaging.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/migrations": { + "get": { + "summary": "Get migrations queue", + "operationId": "healthGetQueueMigrations", + "tags": [ + "health" + ], + "description": "Get the number of migrations that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueMigrations", + "group": "queue", + "weight": 147, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-migrations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-migrations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/stats-resources": { + "get": { + "summary": "Get stats resources queue", + "operationId": "healthGetQueueStatsResources", + "tags": [ + "health" + ], + "description": "Get the number of metrics that are waiting to be processed in the Appwrite stats resources queue.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueStatsResources", + "group": "queue", + "weight": 149, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-stats-resources.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-resources.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/stats-usage": { + "get": { + "summary": "Get stats usage queue", + "operationId": "healthGetQueueUsage", + "tags": [ + "health" + ], + "description": "Get the number of metrics that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueUsage", + "group": "queue", + "weight": 150, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-usage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/webhooks": { + "get": { + "summary": "Get webhooks queue", + "operationId": "healthGetQueueWebhooks", + "tags": [ + "health" + ], + "description": "Get the number of webhooks that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueWebhooks", + "group": "queue", + "weight": 138, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-webhooks.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-webhooks.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/storage": { + "get": { + "summary": "Get storage", + "operationId": "healthGetStorage", + "tags": [ + "health" + ], + "description": "Check the Appwrite storage device is up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthStatus" + } + } + } + } + }, + "x-appwrite": { + "method": "getStorage", + "group": "storage", + "weight": 152, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-storage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-storage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/storage\/local": { + "get": { + "summary": "Get local storage", + "operationId": "healthGetStorageLocal", + "tags": [ + "health" + ], + "description": "Check the Appwrite local storage device is up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthStatus" + } + } + } + } + }, + "x-appwrite": { + "method": "getStorageLocal", + "group": "storage", + "weight": 151, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-storage-local.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-storage-local.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/time": { + "get": { + "summary": "Get time", + "operationId": "healthGetTime", + "tags": [ + "health" + ], + "description": "Check the Appwrite server time is synced with Google remote NTP server. We use this technology to smoothly handle leap seconds with no disruptive events. The [Network Time Protocol](https:\/\/en.wikipedia.org\/wiki\/Network_Time_Protocol) (NTP) is used by hundreds of millions of computers and devices to synchronize their clocks over the Internet. If your computer sets its own clock, it likely uses NTP.", + "responses": { + "200": { + "description": "Health Time", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthTime" + } + } + } + } + }, + "x-appwrite": { + "method": "getTime", + "group": "health", + "weight": 137, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-time.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-time.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/locale": { + "get": { + "summary": "Get user locale", + "operationId": "localeGet", + "tags": [ + "locale" + ], + "description": "Get the current user location based on IP. Returns an object with user country code, country name, continent name, continent code, ip address and suggested currency. You can use the locale header to get the data in a supported language.\n\n([IP Geolocation by DB-IP](https:\/\/db-ip.com))", + "responses": { + "200": { + "description": "Locale", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/locale" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": null, + "weight": 124, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/get-locale.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/codes": { + "get": { + "summary": "List locale codes", + "operationId": "localeListCodes", + "tags": [ + "locale" + ], + "description": "List of all locale codes in [ISO 639-1](https:\/\/en.wikipedia.org\/wiki\/List_of_ISO_639-1_codes).", + "responses": { + "200": { + "description": "Locale codes list", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/localeCodeList" + } + } + } + } + }, + "x-appwrite": { + "method": "listCodes", + "group": null, + "weight": 125, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-locale-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/continents": { + "get": { + "summary": "List continents", + "operationId": "localeListContinents", + "tags": [ + "locale" + ], + "description": "List of all continents. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Continents List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/continentList" + } + } + } + } + }, + "x-appwrite": { + "method": "listContinents", + "group": null, + "weight": 129, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-continents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-continents.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/countries": { + "get": { + "summary": "List countries", + "operationId": "localeListCountries", + "tags": [ + "locale" + ], + "description": "List of all countries. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Countries List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/countryList" + } + } + } + } + }, + "x-appwrite": { + "method": "listCountries", + "group": null, + "weight": 126, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-countries.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-countries.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/countries\/eu": { + "get": { + "summary": "List EU countries", + "operationId": "localeListCountriesEU", + "tags": [ + "locale" + ], + "description": "List of all countries that are currently members of the EU. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Countries List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/countryList" + } + } + } + } + }, + "x-appwrite": { + "method": "listCountriesEU", + "group": null, + "weight": 127, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-countries-e-u.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-countries-eu.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/countries\/phones": { + "get": { + "summary": "List countries phone codes", + "operationId": "localeListCountriesPhones", + "tags": [ + "locale" + ], + "description": "List of all countries phone codes. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Phones List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/phoneList" + } + } + } + } + }, + "x-appwrite": { + "method": "listCountriesPhones", + "group": null, + "weight": 128, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-countries-phones.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-countries-phones.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/currencies": { + "get": { + "summary": "List currencies", + "operationId": "localeListCurrencies", + "tags": [ + "locale" + ], + "description": "List of all currencies, including currency symbol, name, plural, and decimal digits for all major and minor currencies. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Currencies List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/currencyList" + } + } + } + } + }, + "x-appwrite": { + "method": "listCurrencies", + "group": null, + "weight": 130, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-currencies.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-currencies.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/languages": { + "get": { + "summary": "List languages", + "operationId": "localeListLanguages", + "tags": [ + "locale" + ], + "description": "List of all languages classified by ISO 639-1 including 2-letter code, name in English, and name in the respective language.", + "responses": { + "200": { + "description": "Languages List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/languageList" + } + } + } + } + }, + "x-appwrite": { + "method": "listLanguages", + "group": null, + "weight": 131, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-languages.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-languages.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/messaging\/messages": { + "get": { + "summary": "List messages", + "operationId": "messagingListMessages", + "tags": [ + "messaging" + ], + "description": "Get a list of all messages from the current Appwrite project.", + "responses": { + "200": { + "description": "Message list", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/messageList" + } + } + } + } + }, + "x-appwrite": { + "method": "listMessages", + "group": "messages", + "weight": 362, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-messages.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-messages.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: scheduledAt, deliveredAt, deliveredTotal, status, description, providerType", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/messaging\/messages\/email": { + "post": { + "summary": "Create email", + "operationId": "messagingCreateEmail", + "tags": [ + "messaging" + ], + "description": "Create a new email message.", + "responses": { + "201": { + "description": "Message", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/message" + } + } + } + } + }, + "x-appwrite": { + "method": "createEmail", + "group": "messages", + "weight": 359, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-email.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "messageId": { + "type": "string", + "description": "Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "subject": { + "type": "string", + "description": "Email Subject.", + "x-example": "" + }, + "content": { + "type": "string", + "description": "Email Content.", + "x-example": "" + }, + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "cc": { + "type": "array", + "description": "Array of target IDs to be added as CC.", + "x-example": null, + "items": { + "type": "string" + } + }, + "bcc": { + "type": "array", + "description": "Array of target IDs to be added as BCC.", + "x-example": null, + "items": { + "type": "string" + } + }, + "attachments": { + "type": "array", + "description": "Array of compound ID strings of bucket IDs and file IDs to be attached to the email. They should be formatted as :.", + "x-example": null, + "items": { + "type": "string" + } + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "x-example": false + }, + "html": { + "type": "boolean", + "description": "Is content of type HTML", + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "x-example": null + } + }, + "required": [ + "messageId", + "subject", + "content" + ] + } + } + } + } + } + }, + "\/messaging\/messages\/email\/{messageId}": { + "patch": { + "summary": "Update email", + "operationId": "messagingUpdateEmail", + "tags": [ + "messaging" + ], + "description": "Update an email message by its unique ID. This endpoint only works on messages that are in draft status. Messages that are already processing, sent, or failed cannot be updated.\n", + "responses": { + "200": { + "description": "Message", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/message" + } + } + } + } + }, + "x-appwrite": { + "method": "updateEmail", + "group": "messages", + "weight": 366, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-email.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "subject": { + "type": "string", + "description": "Email Subject.", + "x-example": "" + }, + "content": { + "type": "string", + "description": "Email Content.", + "x-example": "" + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "x-example": false + }, + "html": { + "type": "boolean", + "description": "Is content of type HTML", + "x-example": false + }, + "cc": { + "type": "array", + "description": "Array of target IDs to be added as CC.", + "x-example": null, + "items": { + "type": "string" + } + }, + "bcc": { + "type": "array", + "description": "Array of target IDs to be added as BCC.", + "x-example": null, + "items": { + "type": "string" + } + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "x-example": null + }, + "attachments": { + "type": "array", + "description": "Array of compound ID strings of bucket IDs and file IDs to be attached to the email. They should be formatted as :.", + "x-example": null, + "items": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "\/messaging\/messages\/push": { + "post": { + "summary": "Create push notification", + "operationId": "messagingCreatePush", + "tags": [ + "messaging" + ], + "description": "Create a new push notification.", + "responses": { + "201": { + "description": "Message", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/message" + } + } + } + } + }, + "x-appwrite": { + "method": "createPush", + "group": "messages", + "weight": 361, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-push.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-push.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "messageId": { + "type": "string", + "description": "Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "" + }, + "title": { + "type": "string", + "description": "Title for push notification.", + "x-example": "" + }, + "body": { + "type": "string", + "description": "Body for push notification.", + "x-example": "<BODY>" + }, + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "data": { + "type": "object", + "description": "Additional key-value pair data for push notification.", + "x-example": "{}" + }, + "action": { + "type": "string", + "description": "Action for push notification.", + "x-example": "<ACTION>" + }, + "image": { + "type": "string", + "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as <BUCKET_ID>:<FILE_ID>.", + "x-example": "[ID1:ID2]" + }, + "icon": { + "type": "string", + "description": "Icon for push notification. Available only for Android and Web Platform.", + "x-example": "<ICON>" + }, + "sound": { + "type": "string", + "description": "Sound for push notification. Available only for Android and iOS Platform.", + "x-example": "<SOUND>" + }, + "color": { + "type": "string", + "description": "Color for push notification. Available only for Android Platform.", + "x-example": "<COLOR>" + }, + "tag": { + "type": "string", + "description": "Tag for push notification. Available only for Android Platform.", + "x-example": "<TAG>" + }, + "badge": { + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "x-example": null + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device state and may not deliver notifications immediately. \"high\" will always attempt to immediately deliver the notification.", + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": "MessagePriority", + "x-enum-keys": [] + } + }, + "required": [ + "messageId" + ] + } + } + } + } + } + }, + "\/messaging\/messages\/push\/{messageId}": { + "patch": { + "summary": "Update push notification", + "operationId": "messagingUpdatePush", + "tags": [ + "messaging" + ], + "description": "Update a push notification by its unique ID. This endpoint only works on messages that are in draft status. Messages that are already processing, sent, or failed cannot be updated.\n", + "responses": { + "200": { + "description": "Message", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/message" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePush", + "group": "messages", + "weight": 368, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-push.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-push.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MESSAGE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "title": { + "type": "string", + "description": "Title for push notification.", + "x-example": "<TITLE>" + }, + "body": { + "type": "string", + "description": "Body for push notification.", + "x-example": "<BODY>" + }, + "data": { + "type": "object", + "description": "Additional Data for push notification.", + "x-example": "{}" + }, + "action": { + "type": "string", + "description": "Action for push notification.", + "x-example": "<ACTION>" + }, + "image": { + "type": "string", + "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as <BUCKET_ID>:<FILE_ID>.", + "x-example": "[ID1:ID2]" + }, + "icon": { + "type": "string", + "description": "Icon for push notification. Available only for Android and Web platforms.", + "x-example": "<ICON>" + }, + "sound": { + "type": "string", + "description": "Sound for push notification. Available only for Android and iOS platforms.", + "x-example": "<SOUND>" + }, + "color": { + "type": "string", + "description": "Color for push notification. Available only for Android platforms.", + "x-example": "<COLOR>" + }, + "tag": { + "type": "string", + "description": "Tag for push notification. Available only for Android platforms.", + "x-example": "<TAG>" + }, + "badge": { + "type": "integer", + "description": "Badge for push notification. Available only for iOS platforms.", + "x-example": null + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": "MessagePriority", + "x-enum-keys": [] + } + } + } + } + } + } + } + }, + "\/messaging\/messages\/sms": { + "post": { + "summary": "Create SMS", + "operationId": "messagingCreateSms", + "tags": [ + "messaging" + ], + "description": "Create a new SMS message.", + "responses": { + "201": { + "description": "Message", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/message" + } + } + } + } + }, + "x-appwrite": { + "method": "createSms", + "group": "messages", + "weight": 360, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-sms.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-sms.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "messageId": { + "type": "string", + "description": "Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<MESSAGE_ID>" + }, + "content": { + "type": "string", + "description": "SMS Content.", + "x-example": "<CONTENT>" + }, + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "x-example": null + } + }, + "required": [ + "messageId", + "content" + ] + } + } + } + } + } + }, + "\/messaging\/messages\/sms\/{messageId}": { + "patch": { + "summary": "Update SMS", + "operationId": "messagingUpdateSms", + "tags": [ + "messaging" + ], + "description": "Update an SMS message by its unique ID. This endpoint only works on messages that are in draft status. Messages that are already processing, sent, or failed cannot be updated.\n", + "responses": { + "200": { + "description": "Message", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/message" + } + } + } + } + }, + "x-appwrite": { + "method": "updateSms", + "group": "messages", + "weight": 367, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-sms.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-sms.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MESSAGE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "content": { + "type": "string", + "description": "Email Content.", + "x-example": "<CONTENT>" + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "x-example": null + } + } + } + } + } + } + } + }, + "\/messaging\/messages\/{messageId}": { + "get": { + "summary": "Get message", + "operationId": "messagingGetMessage", + "tags": [ + "messaging" + ], + "description": "Get a message by its unique ID.\n", + "responses": { + "200": { + "description": "Message", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/message" + } + } + } + } + }, + "x-appwrite": { + "method": "getMessage", + "group": "messages", + "weight": 365, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/get-message.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/get-message.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MESSAGE_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete message", + "operationId": "messagingDelete", + "tags": [ + "messaging" + ], + "description": "Delete a message. If the message is not a draft or scheduled, but has been sent, this will not recall the message.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "messages", + "weight": 369, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/delete-message.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MESSAGE_ID>" + }, + "in": "path" + } + ] + } + }, + "\/messaging\/messages\/{messageId}\/logs": { + "get": { + "summary": "List message logs", + "operationId": "messagingListMessageLogs", + "tags": [ + "messaging" + ], + "description": "Get the message activity logs listed by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/logList" + } + } + } + } + }, + "x-appwrite": { + "method": "listMessageLogs", + "group": "logs", + "weight": 363, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-message-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-message-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MESSAGE_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/messaging\/messages\/{messageId}\/targets": { + "get": { + "summary": "List message targets", + "operationId": "messagingListTargets", + "tags": [ + "messaging" + ], + "description": "Get a list of the targets associated with a message.", + "responses": { + "200": { + "description": "Target list", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/targetList" + } + } + } + } + }, + "x-appwrite": { + "method": "listTargets", + "group": "messages", + "weight": 364, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-targets.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-message-targets.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MESSAGE_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, providerId, identifier, providerType", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/messaging\/providers": { + "get": { + "summary": "List providers", + "operationId": "messagingListProviders", + "tags": [ + "messaging" + ], + "description": "Get a list of all providers from the current Appwrite project.", + "responses": { + "200": { + "description": "Provider list", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/providerList" + } + } + } + } + }, + "x-appwrite": { + "method": "listProviders", + "group": "providers", + "weight": 334, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-providers.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-providers.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, provider, type, enabled", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/messaging\/providers\/apns": { + "post": { + "summary": "Create APNS provider", + "operationId": "messagingCreateApnsProvider", + "tags": [ + "messaging" + ], + "description": "Create a new Apple Push Notification service provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createApnsProvider", + "group": "providers", + "weight": 333, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-apns-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-apns-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "authKey": { + "type": "string", + "description": "APNS authentication key.", + "x-example": "<AUTH_KEY>" + }, + "authKeyId": { + "type": "string", + "description": "APNS authentication key ID.", + "x-example": "<AUTH_KEY_ID>" + }, + "teamId": { + "type": "string", + "description": "APNS team ID.", + "x-example": "<TEAM_ID>" + }, + "bundleId": { + "type": "string", + "description": "APNS bundle ID.", + "x-example": "<BUNDLE_ID>" + }, + "sandbox": { + "type": "boolean", + "description": "Use APNS sandbox environment.", + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/apns\/{providerId}": { + "patch": { + "summary": "Update APNS provider", + "operationId": "messagingUpdateApnsProvider", + "tags": [ + "messaging" + ], + "description": "Update a Apple Push Notification service provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateApnsProvider", + "group": "providers", + "weight": 346, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-apns-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-apns-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + }, + "authKey": { + "type": "string", + "description": "APNS authentication key.", + "x-example": "<AUTH_KEY>" + }, + "authKeyId": { + "type": "string", + "description": "APNS authentication key ID.", + "x-example": "<AUTH_KEY_ID>" + }, + "teamId": { + "type": "string", + "description": "APNS team ID.", + "x-example": "<TEAM_ID>" + }, + "bundleId": { + "type": "string", + "description": "APNS bundle ID.", + "x-example": "<BUNDLE_ID>" + }, + "sandbox": { + "type": "boolean", + "description": "Use APNS sandbox environment.", + "x-example": false + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/fcm": { + "post": { + "summary": "Create FCM provider", + "operationId": "messagingCreateFcmProvider", + "tags": [ + "messaging" + ], + "description": "Create a new Firebase Cloud Messaging provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createFcmProvider", + "group": "providers", + "weight": 332, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-fcm-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-fcm-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "serviceAccountJSON": { + "type": "object", + "description": "FCM service account JSON.", + "x-example": "{}" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/fcm\/{providerId}": { + "patch": { + "summary": "Update FCM provider", + "operationId": "messagingUpdateFcmProvider", + "tags": [ + "messaging" + ], + "description": "Update a Firebase Cloud Messaging provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateFcmProvider", + "group": "providers", + "weight": 345, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-fcm-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-fcm-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + }, + "serviceAccountJSON": { + "type": "object", + "description": "FCM service account JSON.", + "x-example": "{}" + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/mailgun": { + "post": { + "summary": "Create Mailgun provider", + "operationId": "messagingCreateMailgunProvider", + "tags": [ + "messaging" + ], + "description": "Create a new Mailgun provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createMailgunProvider", + "group": "providers", + "weight": 324, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-mailgun-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-mailgun-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "apiKey": { + "type": "string", + "description": "Mailgun API Key.", + "x-example": "<API_KEY>" + }, + "domain": { + "type": "string", + "description": "Mailgun Domain.", + "x-example": "<DOMAIN>" + }, + "isEuRegion": { + "type": "boolean", + "description": "Set as EU region.", + "x-example": false + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the reply to field for the mail. Default value is sender name. Reply to name must have reply to email as well.", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the reply to field for the mail. Default value is sender email. Reply to email must have reply to name as well.", + "x-example": "email@example.com" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/mailgun\/{providerId}": { + "patch": { + "summary": "Update Mailgun provider", + "operationId": "messagingUpdateMailgunProvider", + "tags": [ + "messaging" + ], + "description": "Update a Mailgun provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMailgunProvider", + "group": "providers", + "weight": 337, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-mailgun-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-mailgun-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "apiKey": { + "type": "string", + "description": "Mailgun API Key.", + "x-example": "<API_KEY>" + }, + "domain": { + "type": "string", + "description": "Mailgun Domain.", + "x-example": "<DOMAIN>" + }, + "isEuRegion": { + "type": "boolean", + "description": "Set as EU region.", + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the reply to field for the mail. Default value is sender name.", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the reply to field for the mail. Default value is sender email.", + "x-example": "<REPLY_TO_EMAIL>" + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/msg91": { + "post": { + "summary": "Create Msg91 provider", + "operationId": "messagingCreateMsg91Provider", + "tags": [ + "messaging" + ], + "description": "Create a new MSG91 provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createMsg91Provider", + "group": "providers", + "weight": 327, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-msg91provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-msg91-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "templateId": { + "type": "string", + "description": "Msg91 template ID", + "x-example": "<TEMPLATE_ID>" + }, + "senderId": { + "type": "string", + "description": "Msg91 sender ID.", + "x-example": "<SENDER_ID>" + }, + "authKey": { + "type": "string", + "description": "Msg91 auth key.", + "x-example": "<AUTH_KEY>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/msg91\/{providerId}": { + "patch": { + "summary": "Update Msg91 provider", + "operationId": "messagingUpdateMsg91Provider", + "tags": [ + "messaging" + ], + "description": "Update a MSG91 provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMsg91Provider", + "group": "providers", + "weight": 340, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-msg91provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-msg91-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + }, + "templateId": { + "type": "string", + "description": "Msg91 template ID.", + "x-example": "<TEMPLATE_ID>" + }, + "senderId": { + "type": "string", + "description": "Msg91 sender ID.", + "x-example": "<SENDER_ID>" + }, + "authKey": { + "type": "string", + "description": "Msg91 auth key.", + "x-example": "<AUTH_KEY>" + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/sendgrid": { + "post": { + "summary": "Create Sendgrid provider", + "operationId": "messagingCreateSendgridProvider", + "tags": [ + "messaging" + ], + "description": "Create a new Sendgrid provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createSendgridProvider", + "group": "providers", + "weight": 325, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-sendgrid-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-sendgrid-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "apiKey": { + "type": "string", + "description": "Sendgrid API key.", + "x-example": "<API_KEY>" + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the reply to field for the mail. Default value is sender name.", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the reply to field for the mail. Default value is sender email.", + "x-example": "email@example.com" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/sendgrid\/{providerId}": { + "patch": { + "summary": "Update Sendgrid provider", + "operationId": "messagingUpdateSendgridProvider", + "tags": [ + "messaging" + ], + "description": "Update a Sendgrid provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateSendgridProvider", + "group": "providers", + "weight": 338, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-sendgrid-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-sendgrid-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + }, + "apiKey": { + "type": "string", + "description": "Sendgrid API key.", + "x-example": "<API_KEY>" + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the Reply To field for the mail. Default value is Sender Name.", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the Reply To field for the mail. Default value is Sender Email.", + "x-example": "<REPLY_TO_EMAIL>" + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/smtp": { + "post": { + "summary": "Create SMTP provider", + "operationId": "messagingCreateSmtpProvider", + "tags": [ + "messaging" + ], + "description": "Create a new SMTP provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createSmtpProvider", + "group": "providers", + "weight": 326, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-smtp-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-smtp-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "host": { + "type": "string", + "description": "SMTP hosts. Either a single hostname or multiple semicolon-delimited hostnames. You can also specify a different port for each host such as `smtp1.example.com:25;smtp2.example.com`. You can also specify encryption type, for example: `tls:\/\/smtp1.example.com:587;ssl:\/\/smtp2.example.com:465\"`. Hosts will be tried in order.", + "x-example": "<HOST>" + }, + "port": { + "type": "integer", + "description": "The default SMTP server port.", + "x-example": 1 + }, + "username": { + "type": "string", + "description": "Authentication username.", + "x-example": "<USERNAME>" + }, + "password": { + "type": "string", + "description": "Authentication password.", + "x-example": "<PASSWORD>" + }, + "encryption": { + "type": "string", + "description": "Encryption type. Can be omitted, 'ssl', or 'tls'", + "x-example": "none", + "enum": [ + "none", + "ssl", + "tls" + ], + "x-enum-name": "SmtpEncryption", + "x-enum-keys": [] + }, + "autoTLS": { + "type": "boolean", + "description": "Enable SMTP AutoTLS feature.", + "x-example": false + }, + "mailer": { + "type": "string", + "description": "The value to use for the X-Mailer header.", + "x-example": "<MAILER>" + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the reply to field for the mail. Default value is sender name.", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the reply to field for the mail. Default value is sender email.", + "x-example": "email@example.com" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name", + "host" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/smtp\/{providerId}": { + "patch": { + "summary": "Update SMTP provider", + "operationId": "messagingUpdateSmtpProvider", + "tags": [ + "messaging" + ], + "description": "Update a SMTP provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateSmtpProvider", + "group": "providers", + "weight": 339, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-smtp-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-smtp-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "host": { + "type": "string", + "description": "SMTP hosts. Either a single hostname or multiple semicolon-delimited hostnames. You can also specify a different port for each host such as `smtp1.example.com:25;smtp2.example.com`. You can also specify encryption type, for example: `tls:\/\/smtp1.example.com:587;ssl:\/\/smtp2.example.com:465\"`. Hosts will be tried in order.", + "x-example": "<HOST>" + }, + "port": { + "type": "integer", + "description": "SMTP port.", + "x-example": 1 + }, + "username": { + "type": "string", + "description": "Authentication username.", + "x-example": "<USERNAME>" + }, + "password": { + "type": "string", + "description": "Authentication password.", + "x-example": "<PASSWORD>" + }, + "encryption": { + "type": "string", + "description": "Encryption type. Can be 'ssl' or 'tls'", + "x-example": "none", + "enum": [ + "none", + "ssl", + "tls" + ], + "x-enum-name": "SmtpEncryption", + "x-enum-keys": [] + }, + "autoTLS": { + "type": "boolean", + "description": "Enable SMTP AutoTLS feature.", + "x-example": false + }, + "mailer": { + "type": "string", + "description": "The value to use for the X-Mailer header.", + "x-example": "<MAILER>" + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the Reply To field for the mail. Default value is Sender Name.", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the Reply To field for the mail. Default value is Sender Email.", + "x-example": "<REPLY_TO_EMAIL>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/telesign": { + "post": { + "summary": "Create Telesign provider", + "operationId": "messagingCreateTelesignProvider", + "tags": [ + "messaging" + ], + "description": "Create a new Telesign provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createTelesignProvider", + "group": "providers", + "weight": 328, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-telesign-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-telesign-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "from": { + "type": "string", + "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "x-example": "+12065550100" + }, + "customerId": { + "type": "string", + "description": "Telesign customer ID.", + "x-example": "<CUSTOMER_ID>" + }, + "apiKey": { + "type": "string", + "description": "Telesign API key.", + "x-example": "<API_KEY>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/telesign\/{providerId}": { + "patch": { + "summary": "Update Telesign provider", + "operationId": "messagingUpdateTelesignProvider", + "tags": [ + "messaging" + ], + "description": "Update a Telesign provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateTelesignProvider", + "group": "providers", + "weight": 341, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-telesign-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-telesign-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + }, + "customerId": { + "type": "string", + "description": "Telesign customer ID.", + "x-example": "<CUSTOMER_ID>" + }, + "apiKey": { + "type": "string", + "description": "Telesign API key.", + "x-example": "<API_KEY>" + }, + "from": { + "type": "string", + "description": "Sender number.", + "x-example": "<FROM>" + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/textmagic": { + "post": { + "summary": "Create Textmagic provider", + "operationId": "messagingCreateTextmagicProvider", + "tags": [ + "messaging" + ], + "description": "Create a new Textmagic provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createTextmagicProvider", + "group": "providers", + "weight": 329, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-textmagic-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-textmagic-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "from": { + "type": "string", + "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "x-example": "+12065550100" + }, + "username": { + "type": "string", + "description": "Textmagic username.", + "x-example": "<USERNAME>" + }, + "apiKey": { + "type": "string", + "description": "Textmagic apiKey.", + "x-example": "<API_KEY>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/textmagic\/{providerId}": { + "patch": { + "summary": "Update Textmagic provider", + "operationId": "messagingUpdateTextmagicProvider", + "tags": [ + "messaging" + ], + "description": "Update a Textmagic provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateTextmagicProvider", + "group": "providers", + "weight": 342, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-textmagic-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-textmagic-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + }, + "username": { + "type": "string", + "description": "Textmagic username.", + "x-example": "<USERNAME>" + }, + "apiKey": { + "type": "string", + "description": "Textmagic apiKey.", + "x-example": "<API_KEY>" + }, + "from": { + "type": "string", + "description": "Sender number.", + "x-example": "<FROM>" + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/twilio": { + "post": { + "summary": "Create Twilio provider", + "operationId": "messagingCreateTwilioProvider", + "tags": [ + "messaging" + ], + "description": "Create a new Twilio provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createTwilioProvider", + "group": "providers", + "weight": 330, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-twilio-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-twilio-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "from": { + "type": "string", + "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "x-example": "+12065550100" + }, + "accountSid": { + "type": "string", + "description": "Twilio account secret ID.", + "x-example": "<ACCOUNT_SID>" + }, + "authToken": { + "type": "string", + "description": "Twilio authentication token.", + "x-example": "<AUTH_TOKEN>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/twilio\/{providerId}": { + "patch": { + "summary": "Update Twilio provider", + "operationId": "messagingUpdateTwilioProvider", + "tags": [ + "messaging" + ], + "description": "Update a Twilio provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateTwilioProvider", + "group": "providers", + "weight": 343, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-twilio-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-twilio-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + }, + "accountSid": { + "type": "string", + "description": "Twilio account secret ID.", + "x-example": "<ACCOUNT_SID>" + }, + "authToken": { + "type": "string", + "description": "Twilio authentication token.", + "x-example": "<AUTH_TOKEN>" + }, + "from": { + "type": "string", + "description": "Sender number.", + "x-example": "<FROM>" + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/vonage": { + "post": { + "summary": "Create Vonage provider", + "operationId": "messagingCreateVonageProvider", + "tags": [ + "messaging" + ], + "description": "Create a new Vonage provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createVonageProvider", + "group": "providers", + "weight": 331, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-vonage-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-vonage-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "from": { + "type": "string", + "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "x-example": "+12065550100" + }, + "apiKey": { + "type": "string", + "description": "Vonage API key.", + "x-example": "<API_KEY>" + }, + "apiSecret": { + "type": "string", + "description": "Vonage API secret.", + "x-example": "<API_SECRET>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/vonage\/{providerId}": { + "patch": { + "summary": "Update Vonage provider", + "operationId": "messagingUpdateVonageProvider", + "tags": [ + "messaging" + ], + "description": "Update a Vonage provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateVonageProvider", + "group": "providers", + "weight": 344, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-vonage-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-vonage-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + }, + "apiKey": { + "type": "string", + "description": "Vonage API key.", + "x-example": "<API_KEY>" + }, + "apiSecret": { + "type": "string", + "description": "Vonage API secret.", + "x-example": "<API_SECRET>" + }, + "from": { + "type": "string", + "description": "Sender number.", + "x-example": "<FROM>" + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/{providerId}": { + "get": { + "summary": "Get provider", + "operationId": "messagingGetProvider", + "tags": [ + "messaging" + ], + "description": "Get a provider by its unique ID.\n", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "getProvider", + "group": "providers", + "weight": 336, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/get-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/get-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete provider", + "operationId": "messagingDeleteProvider", + "tags": [ + "messaging" + ], + "description": "Delete a provider by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteProvider", + "group": "providers", + "weight": 347, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/delete-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/delete-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ] + } + }, + "\/messaging\/providers\/{providerId}\/logs": { + "get": { + "summary": "List provider logs", + "operationId": "messagingListProviderLogs", + "tags": [ + "messaging" + ], + "description": "Get the provider activity logs listed by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/logList" + } + } + } + } + }, + "x-appwrite": { + "method": "listProviderLogs", + "group": "providers", + "weight": 335, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-provider-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-provider-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/messaging\/subscribers\/{subscriberId}\/logs": { + "get": { + "summary": "List subscriber logs", + "operationId": "messagingListSubscriberLogs", + "tags": [ + "messaging" + ], + "description": "Get the subscriber activity logs listed by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/logList" + } + } + } + } + }, + "x-appwrite": { + "method": "listSubscriberLogs", + "group": "subscribers", + "weight": 356, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-subscriber-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-subscriber-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "subscriberId", + "description": "Subscriber ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SUBSCRIBER_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/messaging\/topics": { + "get": { + "summary": "List topics", + "operationId": "messagingListTopics", + "tags": [ + "messaging" + ], + "description": "Get a list of all topics from the current Appwrite project.", + "responses": { + "200": { + "description": "Topic list", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/topicList" + } + } + } + } + }, + "x-appwrite": { + "method": "listTopics", + "group": "topics", + "weight": 349, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-topics.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-topics.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, description, emailTotal, smsTotal, pushTotal", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create topic", + "operationId": "messagingCreateTopic", + "tags": [ + "messaging" + ], + "description": "Create a new topic.", + "responses": { + "201": { + "description": "Topic", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/topic" + } + } + } + } + }, + "x-appwrite": { + "method": "createTopic", + "group": "topics", + "weight": 348, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-topic.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-topic.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "topicId": { + "type": "string", + "description": "Topic ID. Choose a custom Topic ID or a new Topic ID.", + "x-example": "<TOPIC_ID>" + }, + "name": { + "type": "string", + "description": "Topic Name.", + "x-example": "<NAME>" + }, + "subscribe": { + "type": "array", + "description": "An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https:\/\/appwrite.io\/docs\/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.", + "x-example": "[\"any\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "topicId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/topics\/{topicId}": { + "get": { + "summary": "Get topic", + "operationId": "messagingGetTopic", + "tags": [ + "messaging" + ], + "description": "Get a topic by its unique ID.\n", + "responses": { + "200": { + "description": "Topic", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/topic" + } + } + } + } + }, + "x-appwrite": { + "method": "getTopic", + "group": "topics", + "weight": 351, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/get-topic.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/get-topic.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOPIC_ID>" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update topic", + "operationId": "messagingUpdateTopic", + "tags": [ + "messaging" + ], + "description": "Update a topic by its unique ID.\n", + "responses": { + "200": { + "description": "Topic", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/topic" + } + } + } + } + }, + "x-appwrite": { + "method": "updateTopic", + "group": "topics", + "weight": 352, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-topic.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-topic.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOPIC_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Topic Name.", + "x-example": "<NAME>" + }, + "subscribe": { + "type": "array", + "description": "An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https:\/\/appwrite.io\/docs\/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.", + "x-example": "[\"any\"]", + "items": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete topic", + "operationId": "messagingDeleteTopic", + "tags": [ + "messaging" + ], + "description": "Delete a topic by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteTopic", + "group": "topics", + "weight": 353, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/delete-topic.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/delete-topic.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOPIC_ID>" + }, + "in": "path" + } + ] + } + }, + "\/messaging\/topics\/{topicId}\/logs": { + "get": { + "summary": "List topic logs", + "operationId": "messagingListTopicLogs", + "tags": [ + "messaging" + ], + "description": "Get the topic activity logs listed by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/logList" + } + } + } + } + }, + "x-appwrite": { + "method": "listTopicLogs", + "group": "topics", + "weight": 350, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-topic-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-topic-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOPIC_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/messaging\/topics\/{topicId}\/subscribers": { + "get": { + "summary": "List subscribers", + "operationId": "messagingListSubscribers", + "tags": [ + "messaging" + ], + "description": "Get a list of all subscribers from the current Appwrite project.", + "responses": { + "200": { + "description": "Subscriber list", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/subscriberList" + } + } + } + } + }, + "x-appwrite": { + "method": "listSubscribers", + "group": "subscribers", + "weight": 355, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-subscribers.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-subscribers.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID subscribed to.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOPIC_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, provider, type, enabled", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create subscriber", + "operationId": "messagingCreateSubscriber", + "tags": [ + "messaging" + ], + "description": "Create a new subscriber.", + "responses": { + "201": { + "description": "Subscriber", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/subscriber" + } + } + } + } + }, + "x-appwrite": { + "method": "createSubscriber", + "group": "subscribers", + "weight": 354, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-subscriber.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-subscriber.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.write", + "platforms": [ + "server", + "client", + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID to subscribe to.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOPIC_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "subscriberId": { + "type": "string", + "description": "Subscriber ID. Choose a custom Subscriber ID or a new Subscriber ID.", + "x-example": "<SUBSCRIBER_ID>" + }, + "targetId": { + "type": "string", + "description": "Target ID. The target ID to link to the specified Topic ID.", + "x-example": "<TARGET_ID>" + } + }, + "required": [ + "subscriberId", + "targetId" + ] + } + } + } + } + } + }, + "\/messaging\/topics\/{topicId}\/subscribers\/{subscriberId}": { + "get": { + "summary": "Get subscriber", + "operationId": "messagingGetSubscriber", + "tags": [ + "messaging" + ], + "description": "Get a subscriber by its unique ID.\n", + "responses": { + "200": { + "description": "Subscriber", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/subscriber" + } + } + } + } + }, + "x-appwrite": { + "method": "getSubscriber", + "group": "subscribers", + "weight": 357, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/get-subscriber.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/get-subscriber.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID subscribed to.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOPIC_ID>" + }, + "in": "path" + }, + { + "name": "subscriberId", + "description": "Subscriber ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SUBSCRIBER_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete subscriber", + "operationId": "messagingDeleteSubscriber", + "tags": [ + "messaging" + ], + "description": "Delete a subscriber by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSubscriber", + "group": "subscribers", + "weight": 358, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/delete-subscriber.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/delete-subscriber.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.write", + "platforms": [ + "server", + "client", + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID subscribed to.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOPIC_ID>" + }, + "in": "path" + }, + { + "name": "subscriberId", + "description": "Subscriber ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SUBSCRIBER_ID>" + }, + "in": "path" + } + ] + } + }, + "\/migrations": { + "get": { + "summary": "List migrations", + "operationId": "migrationsList", + "tags": [ + "migrations" + ], + "description": "List all migrations in the current project. This endpoint returns a list of all migrations including their status, progress, and any errors that occurred during the migration process.", + "responses": { + "200": { + "description": "Migrations List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/migrationList" + } + } + } + } + }, + "x-appwrite": { + "method": "list", + "group": null, + "weight": 316, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/list-migrations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/databases#querying-documents). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: status, stage, source, destination, resources, statusCounters, resourceData, errors", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/migrations\/appwrite": { + "post": { + "summary": "Create Appwrite migration", + "operationId": "migrationsCreateAppwriteMigration", + "tags": [ + "migrations" + ], + "description": "Migrate data from another Appwrite project to your current project. This endpoint allows you to migrate resources like databases, collections, documents, users, and files from an existing Appwrite project. ", + "responses": { + "202": { + "description": "Migration", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/migration" + } + } + } + } + }, + "x-appwrite": { + "method": "createAppwriteMigration", + "group": null, + "weight": 311, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/create-appwrite-migration.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-appwrite.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "resources": { + "type": "array", + "description": "List of resources to migrate", + "x-example": null, + "items": { + "type": "string" + } + }, + "endpoint": { + "type": "string", + "description": "Source Appwrite endpoint", + "x-example": "https:\/\/example.com" + }, + "projectId": { + "type": "string", + "description": "Source Project ID", + "x-example": "<PROJECT_ID>" + }, + "apiKey": { + "type": "string", + "description": "Source API Key", + "x-example": "<API_KEY>" + } + }, + "required": [ + "resources", + "endpoint", + "projectId", + "apiKey" + ] + } + } + } + } + } + }, + "\/migrations\/appwrite\/report": { + "get": { + "summary": "Get Appwrite migration report", + "operationId": "migrationsGetAppwriteReport", + "tags": [ + "migrations" + ], + "description": "Generate a report of the data in an Appwrite project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated.", + "responses": { + "200": { + "description": "Migration Report", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/migrationReport" + } + } + } + } + }, + "x-appwrite": { + "method": "getAppwriteReport", + "group": null, + "weight": 318, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/get-appwrite-report.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-appwrite-report.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "resources", + "description": "List of resources to migrate", + "required": true, + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "in": "query" + }, + { + "name": "endpoint", + "description": "Source's Appwrite Endpoint", + "required": true, + "schema": { + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com" + }, + "in": "query" + }, + { + "name": "projectID", + "description": "Source's Project ID", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "query" + }, + { + "name": "key", + "description": "Source's API Key", + "required": true, + "schema": { + "type": "string", + "x-example": "<KEY>" + }, + "in": "query" + } + ] + } + }, + "\/migrations\/csv": { + "post": { + "summary": "Import documents from a CSV", + "operationId": "migrationsCreateCsvMigration", + "tags": [ + "migrations" + ], + "description": "Import documents from a CSV file into your Appwrite database. This endpoint allows you to import documents from a CSV file uploaded to Appwrite Storage bucket.", + "responses": { + "202": { + "description": "Migration", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/migration" + } + } + } + } + }, + "x-appwrite": { + "method": "createCsvMigration", + "group": null, + "weight": 315, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/create-csv-migration.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-csv.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "bucketId": { + "type": "string", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "x-example": "<BUCKET_ID>" + }, + "fileId": { + "type": "string", + "description": "File ID.", + "x-example": "<FILE_ID>" + }, + "resourceId": { + "type": "string", + "description": "Composite ID in the format {databaseId:collectionId}, identifying a collection within a database.", + "x-example": "[ID1:ID2]" + } + }, + "required": [ + "bucketId", + "fileId", + "resourceId" + ] + } + } + } + } + } + }, + "\/migrations\/firebase": { + "post": { + "summary": "Create Firebase migration", + "operationId": "migrationsCreateFirebaseMigration", + "tags": [ + "migrations" + ], + "description": "Migrate data from a Firebase project to your Appwrite project. This endpoint allows you to migrate resources like authentication and other supported services from a Firebase project. ", + "responses": { + "202": { + "description": "Migration", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/migration" + } + } + } + } + }, + "x-appwrite": { + "method": "createFirebaseMigration", + "group": null, + "weight": 312, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/create-firebase-migration.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-firebase.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "resources": { + "type": "array", + "description": "List of resources to migrate", + "x-example": null, + "items": { + "type": "string" + } + }, + "serviceAccount": { + "type": "string", + "description": "JSON of the Firebase service account credentials", + "x-example": "<SERVICE_ACCOUNT>" + } + }, + "required": [ + "resources", + "serviceAccount" + ] + } + } + } + } + } + }, + "\/migrations\/firebase\/report": { + "get": { + "summary": "Get Firebase migration report", + "operationId": "migrationsGetFirebaseReport", + "tags": [ + "migrations" + ], + "description": "Generate a report of the data in a Firebase project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated.", + "responses": { + "200": { + "description": "Migration Report", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/migrationReport" + } + } + } + } + }, + "x-appwrite": { + "method": "getFirebaseReport", + "group": null, + "weight": 319, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/get-firebase-report.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-firebase-report.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "resources", + "description": "List of resources to migrate", + "required": true, + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "in": "query" + }, + { + "name": "serviceAccount", + "description": "JSON of the Firebase service account credentials", + "required": true, + "schema": { + "type": "string", + "x-example": "<SERVICE_ACCOUNT>" + }, + "in": "query" + } + ] + } + }, + "\/migrations\/nhost": { + "post": { + "summary": "Create NHost migration", + "operationId": "migrationsCreateNHostMigration", + "tags": [ + "migrations" + ], + "description": "Migrate data from an NHost project to your Appwrite project. This endpoint allows you to migrate resources like authentication, databases, and other supported services from an NHost project. ", + "responses": { + "202": { + "description": "Migration", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/migration" + } + } + } + } + }, + "x-appwrite": { + "method": "createNHostMigration", + "group": null, + "weight": 314, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/create-n-host-migration.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-nhost.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "resources": { + "type": "array", + "description": "List of resources to migrate", + "x-example": null, + "items": { + "type": "string" + } + }, + "subdomain": { + "type": "string", + "description": "Source's Subdomain", + "x-example": "<SUBDOMAIN>" + }, + "region": { + "type": "string", + "description": "Source's Region", + "x-example": "<REGION>" + }, + "adminSecret": { + "type": "string", + "description": "Source's Admin Secret", + "x-example": "<ADMIN_SECRET>" + }, + "database": { + "type": "string", + "description": "Source's Database Name", + "x-example": "<DATABASE>" + }, + "username": { + "type": "string", + "description": "Source's Database Username", + "x-example": "<USERNAME>" + }, + "password": { + "type": "string", + "description": "Source's Database Password", + "x-example": "<PASSWORD>" + }, + "port": { + "type": "integer", + "description": "Source's Database Port", + "x-example": null + } + }, + "required": [ + "resources", + "subdomain", + "region", + "adminSecret", + "database", + "username", + "password" + ] + } + } + } + } + } + }, + "\/migrations\/nhost\/report": { + "get": { + "summary": "Get NHost migration report", + "operationId": "migrationsGetNHostReport", + "tags": [ + "migrations" + ], + "description": "Generate a detailed report of the data in an NHost project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated. ", + "responses": { + "200": { + "description": "Migration Report", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/migrationReport" + } + } + } + } + }, + "x-appwrite": { + "method": "getNHostReport", + "group": null, + "weight": 321, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/get-n-host-report.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-nhost-report.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "resources", + "description": "List of resources to migrate.", + "required": true, + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "in": "query" + }, + { + "name": "subdomain", + "description": "Source's Subdomain.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SUBDOMAIN>" + }, + "in": "query" + }, + { + "name": "region", + "description": "Source's Region.", + "required": true, + "schema": { + "type": "string", + "x-example": "<REGION>" + }, + "in": "query" + }, + { + "name": "adminSecret", + "description": "Source's Admin Secret.", + "required": true, + "schema": { + "type": "string", + "x-example": "<ADMIN_SECRET>" + }, + "in": "query" + }, + { + "name": "database", + "description": "Source's Database Name.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE>" + }, + "in": "query" + }, + { + "name": "username", + "description": "Source's Database Username.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USERNAME>" + }, + "in": "query" + }, + { + "name": "password", + "description": "Source's Database Password.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PASSWORD>" + }, + "in": "query" + }, + { + "name": "port", + "description": "Source's Database Port.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5432 + }, + "in": "query" + } + ] + } + }, + "\/migrations\/supabase": { + "post": { + "summary": "Create Supabase migration", + "operationId": "migrationsCreateSupabaseMigration", + "tags": [ + "migrations" + ], + "description": "Migrate data from a Supabase project to your Appwrite project. This endpoint allows you to migrate resources like authentication, databases, and other supported services from a Supabase project. ", + "responses": { + "202": { + "description": "Migration", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/migration" + } + } + } + } + }, + "x-appwrite": { + "method": "createSupabaseMigration", + "group": null, + "weight": 313, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/create-supabase-migration.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-supabase.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "resources": { + "type": "array", + "description": "List of resources to migrate", + "x-example": null, + "items": { + "type": "string" + } + }, + "endpoint": { + "type": "string", + "description": "Source's Supabase Endpoint", + "x-example": "https:\/\/example.com" + }, + "apiKey": { + "type": "string", + "description": "Source's API Key", + "x-example": "<API_KEY>" + }, + "databaseHost": { + "type": "string", + "description": "Source's Database Host", + "x-example": "<DATABASE_HOST>" + }, + "username": { + "type": "string", + "description": "Source's Database Username", + "x-example": "<USERNAME>" + }, + "password": { + "type": "string", + "description": "Source's Database Password", + "x-example": "<PASSWORD>" + }, + "port": { + "type": "integer", + "description": "Source's Database Port", + "x-example": null + } + }, + "required": [ + "resources", + "endpoint", + "apiKey", + "databaseHost", + "username", + "password" + ] + } + } + } + } + } + }, + "\/migrations\/supabase\/report": { + "get": { + "summary": "Get Supabase migration report", + "operationId": "migrationsGetSupabaseReport", + "tags": [ + "migrations" + ], + "description": "Generate a report of the data in a Supabase project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated. ", + "responses": { + "200": { + "description": "Migration Report", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/migrationReport" + } + } + } + } + }, + "x-appwrite": { + "method": "getSupabaseReport", + "group": null, + "weight": 320, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/get-supabase-report.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-supabase-report.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "resources", + "description": "List of resources to migrate", + "required": true, + "schema": { + "type": "array", + "items": { + "type": "string" + } + }, + "in": "query" + }, + { + "name": "endpoint", + "description": "Source's Supabase Endpoint.", + "required": true, + "schema": { + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com" + }, + "in": "query" + }, + { + "name": "apiKey", + "description": "Source's API Key.", + "required": true, + "schema": { + "type": "string", + "x-example": "<API_KEY>" + }, + "in": "query" + }, + { + "name": "databaseHost", + "description": "Source's Database Host.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_HOST>" + }, + "in": "query" + }, + { + "name": "username", + "description": "Source's Database Username.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USERNAME>" + }, + "in": "query" + }, + { + "name": "password", + "description": "Source's Database Password.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PASSWORD>" + }, + "in": "query" + }, + { + "name": "port", + "description": "Source's Database Port.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5432 + }, + "in": "query" + } + ] + } + }, + "\/migrations\/{migrationId}": { + "get": { + "summary": "Get migration", + "operationId": "migrationsGet", + "tags": [ + "migrations" + ], + "description": "Get a migration by its unique ID. This endpoint returns detailed information about a specific migration including its current status, progress, and any errors that occurred during the migration process. ", + "responses": { + "200": { + "description": "Migration", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/migration" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": null, + "weight": 317, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/get-migration.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "migrationId", + "description": "Migration unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MIGRATION_ID>" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update retry migration", + "operationId": "migrationsRetry", + "tags": [ + "migrations" + ], + "description": "Retry a failed migration. This endpoint allows you to retry a migration that has previously failed.", + "responses": { + "202": { + "description": "Migration", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/migration" + } + } + } + } + }, + "x-appwrite": { + "method": "retry", + "group": null, + "weight": 322, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/retry.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/retry-migration.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "migrationId", + "description": "Migration unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MIGRATION_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete migration", + "operationId": "migrationsDelete", + "tags": [ + "migrations" + ], + "description": "Delete a migration by its unique ID. This endpoint allows you to remove a migration from your project's migration history. ", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": null, + "weight": 323, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/delete-migration.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "migrationId", + "description": "Migration ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MIGRATION_ID>" + }, + "in": "path" + } + ] + } + }, + "\/project\/usage": { + "get": { + "summary": "Get project usage stats", + "operationId": "projectGetUsage", + "tags": [ + "project" + ], + "description": "Get comprehensive usage statistics for your project. View metrics including network requests, bandwidth, storage, function executions, database usage, and user activity. Specify a time range with startDate and endDate, and optionally set the data granularity with period (1h or 1d). The response includes both total counts and detailed breakdowns by resource, along with historical data over the specified period.", + "responses": { + "200": { + "description": "UsageProject", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/usageProject" + } + } + } + } + }, + "x-appwrite": { + "method": "getUsage", + "group": null, + "weight": 202, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "project\/get-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/project\/get-usage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "startDate", + "description": "Starting date for the usage", + "required": true, + "schema": { + "type": "string" + }, + "in": "query" + }, + { + "name": "endDate", + "description": "End date for the usage", + "required": true, + "schema": { + "type": "string" + }, + "in": "query" + }, + { + "name": "period", + "description": "Period used", + "required": false, + "schema": { + "type": "string", + "x-example": "1h", + "enum": [ + "1h", + "1d" + ], + "x-enum-name": "ProjectUsageRange", + "x-enum-keys": [ + "One Hour", + "One Day" + ], + "default": "1d" + }, + "in": "query" + } + ] + } + }, + "\/project\/variables": { + "get": { + "summary": "List variables", + "operationId": "projectListVariables", + "tags": [ + "project" + ], + "description": "Get a list of all project variables. These variables will be accessible in all Appwrite Functions at runtime.", + "responses": { + "200": { + "description": "Variables List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variableList" + } + } + } + } + }, + "x-appwrite": { + "method": "listVariables", + "group": null, + "weight": 204, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "project\/list-variables.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/project\/list-variables.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ] + }, + "post": { + "summary": "Create variable", + "operationId": "projectCreateVariable", + "tags": [ + "project" + ], + "description": "Create a new project variable. This variable will be accessible in all Appwrite Functions at runtime.", + "responses": { + "201": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "createVariable", + "group": null, + "weight": 203, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "project\/create-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/project\/create-variable.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "x-example": "<KEY>" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "x-example": "<VALUE>" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only projects can read them during build and runtime.", + "x-example": false + } + }, + "required": [ + "key", + "value" + ] + } + } + } + } + } + }, + "\/project\/variables\/{variableId}": { + "get": { + "summary": "Get variable", + "operationId": "projectGetVariable", + "tags": [ + "project" + ], + "description": "Get a project variable by its unique ID.", + "responses": { + "200": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "getVariable", + "group": null, + "weight": 205, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "project\/get-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/project\/get-variable.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<VARIABLE_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update variable", + "operationId": "projectUpdateVariable", + "tags": [ + "project" + ], + "description": "Update project variable by its unique ID. This variable will be accessible in all Appwrite Functions at runtime.", + "responses": { + "200": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "updateVariable", + "group": null, + "weight": 206, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "project\/update-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/project\/update-variable.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<VARIABLE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "x-example": "<KEY>" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "x-example": "<VALUE>" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only projects can read them during build and runtime.", + "x-example": false + } + }, + "required": [ + "key" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete variable", + "operationId": "projectDeleteVariable", + "tags": [ + "project" + ], + "description": "Delete a project variable by its unique ID. ", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteVariable", + "group": null, + "weight": 207, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "project\/delete-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/project\/delete-variable.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<VARIABLE_ID>" + }, + "in": "path" + } + ] + } + }, + "\/projects": { + "get": { + "summary": "List projects", + "operationId": "projectsList", + "tags": [ + "projects" + ], + "description": "Get a list of all projects. You can use the query params to filter your results. ", + "responses": { + "200": { + "description": "Projects List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/projectList" + } + } + } + } + }, + "x-appwrite": { + "method": "list", + "group": "projects", + "weight": 157, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/list.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, teamId", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create project", + "operationId": "projectsCreate", + "tags": [ + "projects" + ], + "description": "Create a new project. You can create a maximum of 100 projects per account. ", + "responses": { + "201": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "create", + "group": "projects", + "weight": 156, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "projectId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, and hyphen. Can't start with a special char. Max length is 36 chars.", + "x-example": null + }, + "name": { + "type": "string", + "description": "Project name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "teamId": { + "type": "string", + "description": "Team unique ID.", + "x-example": "<TEAM_ID>" + }, + "region": { + "type": "string", + "description": "Project Region.", + "x-example": "default", + "enum": [ + "default" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "description": { + "type": "string", + "description": "Project description. Max length: 256 chars.", + "x-example": "<DESCRIPTION>" + }, + "logo": { + "type": "string", + "description": "Project logo.", + "x-example": "<LOGO>" + }, + "url": { + "type": "string", + "description": "Project URL.", + "x-example": "https:\/\/example.com" + }, + "legalName": { + "type": "string", + "description": "Project legal Name. Max length: 256 chars.", + "x-example": "<LEGAL_NAME>" + }, + "legalCountry": { + "type": "string", + "description": "Project legal Country. Max length: 256 chars.", + "x-example": "<LEGAL_COUNTRY>" + }, + "legalState": { + "type": "string", + "description": "Project legal State. Max length: 256 chars.", + "x-example": "<LEGAL_STATE>" + }, + "legalCity": { + "type": "string", + "description": "Project legal City. Max length: 256 chars.", + "x-example": "<LEGAL_CITY>" + }, + "legalAddress": { + "type": "string", + "description": "Project legal Address. Max length: 256 chars.", + "x-example": "<LEGAL_ADDRESS>" + }, + "legalTaxId": { + "type": "string", + "description": "Project legal Tax ID. Max length: 256 chars.", + "x-example": "<LEGAL_TAX_ID>" + } + }, + "required": [ + "projectId", + "name", + "teamId" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}": { + "get": { + "summary": "Get project", + "operationId": "projectsGet", + "tags": [ + "projects" + ], + "description": "Get a project by its unique ID. This endpoint allows you to retrieve the project's details, including its name, description, team, region, and other metadata. ", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": "projects", + "weight": 158, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update project", + "operationId": "projectsUpdate", + "tags": [ + "projects" + ], + "description": "Update a project by its unique ID.", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "update", + "group": "projects", + "weight": 159, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Project name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "description": { + "type": "string", + "description": "Project description. Max length: 256 chars.", + "x-example": "<DESCRIPTION>" + }, + "logo": { + "type": "string", + "description": "Project logo.", + "x-example": "<LOGO>" + }, + "url": { + "type": "string", + "description": "Project URL.", + "x-example": "https:\/\/example.com" + }, + "legalName": { + "type": "string", + "description": "Project legal name. Max length: 256 chars.", + "x-example": "<LEGAL_NAME>" + }, + "legalCountry": { + "type": "string", + "description": "Project legal country. Max length: 256 chars.", + "x-example": "<LEGAL_COUNTRY>" + }, + "legalState": { + "type": "string", + "description": "Project legal state. Max length: 256 chars.", + "x-example": "<LEGAL_STATE>" + }, + "legalCity": { + "type": "string", + "description": "Project legal city. Max length: 256 chars.", + "x-example": "<LEGAL_CITY>" + }, + "legalAddress": { + "type": "string", + "description": "Project legal address. Max length: 256 chars.", + "x-example": "<LEGAL_ADDRESS>" + }, + "legalTaxId": { + "type": "string", + "description": "Project legal tax ID. Max length: 256 chars.", + "x-example": "<LEGAL_TAX_ID>" + } + }, + "required": [ + "name" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete project", + "operationId": "projectsDelete", + "tags": [ + "projects" + ], + "description": "Delete a project by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "projects", + "weight": 176, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ] + } + }, + "\/projects\/{projectId}\/api": { + "patch": { + "summary": "Update API status", + "operationId": "projectsUpdateApiStatus", + "tags": [ + "projects" + ], + "description": "Update the status of a specific API type. Use this endpoint to enable or disable API types such as REST, GraphQL and Realtime.", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "updateApiStatus", + "group": "projects", + "weight": 163, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-api-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-api-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "api": { + "type": "string", + "description": "API name.", + "x-example": "rest", + "enum": [ + "rest", + "graphql", + "realtime" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "status": { + "type": "boolean", + "description": "API status.", + "x-example": false + } + }, + "required": [ + "api", + "status" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/api\/all": { + "patch": { + "summary": "Update all API status", + "operationId": "projectsUpdateApiStatusAll", + "tags": [ + "projects" + ], + "description": "Update the status of all API types. Use this endpoint to enable or disable API types such as REST, GraphQL and Realtime all at once.", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "updateApiStatusAll", + "group": "projects", + "weight": 164, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-api-status-all.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-api-status-all.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "boolean", + "description": "API status.", + "x-example": false + } + }, + "required": [ + "status" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/auth\/duration": { + "patch": { + "summary": "Update project authentication duration", + "operationId": "projectsUpdateAuthDuration", + "tags": [ + "projects" + ], + "description": "Update how long sessions created within a project should stay active for.", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "updateAuthDuration", + "group": "auth", + "weight": 169, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-auth-duration.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-duration.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "duration": { + "type": "integer", + "description": "Project session length in seconds. Max length: 31536000 seconds.", + "x-example": 0 + } + }, + "required": [ + "duration" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/auth\/limit": { + "patch": { + "summary": "Update project users limit", + "operationId": "projectsUpdateAuthLimit", + "tags": [ + "projects" + ], + "description": "Update the maximum number of users allowed in this project. Set to 0 for unlimited users. ", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "updateAuthLimit", + "group": "auth", + "weight": 168, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-auth-limit.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-limit.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "limit": { + "type": "integer", + "description": "Set the max number of users allowed in this project. Use 0 for unlimited.", + "x-example": 0 + } + }, + "required": [ + "limit" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/auth\/max-sessions": { + "patch": { + "summary": "Update project user sessions limit", + "operationId": "projectsUpdateAuthSessionsLimit", + "tags": [ + "projects" + ], + "description": "Update the maximum number of sessions allowed per user within the project, if the limit is hit the oldest session will be deleted to make room for new sessions.", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "updateAuthSessionsLimit", + "group": "auth", + "weight": 174, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-auth-sessions-limit.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-sessions-limit.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "limit": { + "type": "integer", + "description": "Set the max number of users allowed in this project. Value allowed is between 1-100. Default is 10", + "x-example": 1 + } + }, + "required": [ + "limit" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/auth\/memberships-privacy": { + "patch": { + "summary": "Update project memberships privacy attributes", + "operationId": "projectsUpdateMembershipsPrivacy", + "tags": [ + "projects" + ], + "description": "Update project membership privacy settings. Use this endpoint to control what user information is visible to other team members, such as user name, email, and MFA status. ", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMembershipsPrivacy", + "group": "auth", + "weight": 167, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-memberships-privacy.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-memberships-privacy.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userName": { + "type": "boolean", + "description": "Set to true to show userName to members of a team.", + "x-example": false + }, + "userEmail": { + "type": "boolean", + "description": "Set to true to show email to members of a team.", + "x-example": false + }, + "mfa": { + "type": "boolean", + "description": "Set to true to show mfa to members of a team.", + "x-example": false + } + }, + "required": [ + "userName", + "userEmail", + "mfa" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/auth\/mock-numbers": { + "patch": { + "summary": "Update the mock numbers for the project", + "operationId": "projectsUpdateMockNumbers", + "tags": [ + "projects" + ], + "description": "Update the list of mock phone numbers for testing. Use these numbers to bypass SMS verification in development. ", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMockNumbers", + "group": "auth", + "weight": 175, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-mock-numbers.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-mock-numbers.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "numbers": { + "type": "array", + "description": "An array of mock numbers and their corresponding verification codes (OTPs). Each number should be a valid E.164 formatted phone number. Maximum of 10 numbers are allowed.", + "x-example": null, + "items": { + "type": "object" + } + } + }, + "required": [ + "numbers" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/auth\/password-dictionary": { + "patch": { + "summary": "Update authentication password dictionary status. Use this endpoint to enable or disable the dicitonary check for user password", + "operationId": "projectsUpdateAuthPasswordDictionary", + "tags": [ + "projects" + ], + "description": "Enable or disable checking user passwords against common passwords dictionary. This helps ensure users don't use common and insecure passwords. ", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "updateAuthPasswordDictionary", + "group": "auth", + "weight": 172, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-auth-password-dictionary.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-password-dictionary.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Set whether or not to enable checking user's password against most commonly used passwords. Default is false.", + "x-example": false + } + }, + "required": [ + "enabled" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/auth\/password-history": { + "patch": { + "summary": "Update authentication password history. Use this endpoint to set the number of password history to save and 0 to disable password history.", + "operationId": "projectsUpdateAuthPasswordHistory", + "tags": [ + "projects" + ], + "description": "Update the authentication password history requirement. Use this endpoint to require new passwords to be different than the last X amount of previously used ones.", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "updateAuthPasswordHistory", + "group": "auth", + "weight": 171, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-auth-password-history.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-password-history.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "limit": { + "type": "integer", + "description": "Set the max number of passwords to store in user history. User can't choose a new password that is already stored in the password history list. Max number of passwords allowed in history is20. Default value is 0", + "x-example": 0 + } + }, + "required": [ + "limit" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/auth\/personal-data": { + "patch": { + "summary": "Update personal data check", + "operationId": "projectsUpdatePersonalDataCheck", + "tags": [ + "projects" + ], + "description": "Enable or disable checking user passwords against their personal data. This helps prevent users from using personal information in their passwords. ", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePersonalDataCheck", + "group": "auth", + "weight": 173, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-personal-data-check.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-personal-data-check.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Set whether or not to check a password for similarity with personal data. Default is false.", + "x-example": false + } + }, + "required": [ + "enabled" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/auth\/session-alerts": { + "patch": { + "summary": "Update project sessions emails", + "operationId": "projectsUpdateSessionAlerts", + "tags": [ + "projects" + ], + "description": "Enable or disable session email alerts. When enabled, users will receive email notifications when new sessions are created.", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "updateSessionAlerts", + "group": "auth", + "weight": 166, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-session-alerts.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-session-alerts.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "alerts": { + "type": "boolean", + "description": "Set to true to enable session emails.", + "x-example": false + } + }, + "required": [ + "alerts" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/auth\/{method}": { + "patch": { + "summary": "Update project auth method status. Use this endpoint to enable or disable a given auth method for this project.", + "operationId": "projectsUpdateAuthStatus", + "tags": [ + "projects" + ], + "description": "Update the status of a specific authentication method. Use this endpoint to enable or disable different authentication methods such as email, magic urls or sms in your project. ", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "updateAuthStatus", + "group": "auth", + "weight": 170, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-auth-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "method", + "description": "Auth Method. Possible values: email-password,magic-url,email-otp,anonymous,invites,jwt,phone", + "required": true, + "schema": { + "type": "string", + "x-example": "email-password", + "enum": [ + "email-password", + "magic-url", + "email-otp", + "anonymous", + "invites", + "jwt", + "phone" + ], + "x-enum-name": "AuthMethod", + "x-enum-keys": [] + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "boolean", + "description": "Set the status of this auth method.", + "x-example": false + } + }, + "required": [ + "status" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/dev-keys": { + "get": { + "summary": "List dev keys", + "operationId": "projectsListDevKeys", + "tags": [ + "projects" + ], + "description": "List all the project\\'s dev keys. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development.'", + "responses": { + "200": { + "description": "Dev Keys List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/devKeyList" + } + } + } + } + }, + "x-appwrite": { + "method": "listDevKeys", + "group": "devKeys", + "weight": 373, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/list-dev-keys.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList all the project\\'s dev keys. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development.'", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: accessedAt, expire", + "required": false, + "schema": { + "type": "string", + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create dev key", + "operationId": "projectsCreateDevKey", + "tags": [ + "projects" + ], + "description": "Create a new project dev key. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development. Strictly meant for development purposes only.", + "responses": { + "201": { + "description": "DevKey", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/devKey" + } + } + } + } + }, + "x-appwrite": { + "method": "createDevKey", + "group": "devKeys", + "weight": 370, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/create-dev-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new project dev key. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development. Strictly meant for development purposes only.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Key name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "expire": { + "type": "string", + "description": "Expiration time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format.", + "x-example": null + } + }, + "required": [ + "name", + "expire" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/dev-keys\/{keyId}": { + "get": { + "summary": "Get dev key", + "operationId": "projectsGetDevKey", + "tags": [ + "projects" + ], + "description": "Get a project\\'s dev key by its unique ID. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development.", + "responses": { + "200": { + "description": "DevKey", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/devKey" + } + } + } + } + }, + "x-appwrite": { + "method": "getDevKey", + "group": "devKeys", + "weight": 372, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/get-dev-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a project\\'s dev key by its unique ID. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "keyId", + "description": "Key unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<KEY_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update dev key", + "operationId": "projectsUpdateDevKey", + "tags": [ + "projects" + ], + "description": "Update a project\\'s dev key by its unique ID. Use this endpoint to update a project\\'s dev key name or expiration time.'", + "responses": { + "200": { + "description": "DevKey", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/devKey" + } + } + } + } + }, + "x-appwrite": { + "method": "updateDevKey", + "group": "devKeys", + "weight": 371, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-dev-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate a project\\'s dev key by its unique ID. Use this endpoint to update a project\\'s dev key name or expiration time.'", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "keyId", + "description": "Key unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<KEY_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Key name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "expire": { + "type": "string", + "description": "Expiration time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format.", + "x-example": null + } + }, + "required": [ + "name", + "expire" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete dev key", + "operationId": "projectsDeleteDevKey", + "tags": [ + "projects" + ], + "description": "Delete a project\\'s dev key by its unique ID. Once deleted, the key will no longer allow bypassing of rate limits and better logging of errors.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDevKey", + "group": "devKeys", + "weight": 374, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/delete-dev-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a project\\'s dev key by its unique ID. Once deleted, the key will no longer allow bypassing of rate limits and better logging of errors.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "keyId", + "description": "Key unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<KEY_ID>" + }, + "in": "path" + } + ] + } + }, + "\/projects\/{projectId}\/jwts": { + "post": { + "summary": "Create JWT", + "operationId": "projectsCreateJWT", + "tags": [ + "projects" + ], + "description": "Create a new JWT token. This token can be used to authenticate users with custom scopes and expiration time. ", + "responses": { + "201": { + "description": "JWT", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/jwt" + } + } + } + } + }, + "x-appwrite": { + "method": "createJWT", + "group": "auth", + "weight": 188, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/create-j-w-t.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-jwt.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "scopes": { + "type": "array", + "description": "List of scopes allowed for JWT key. Maximum of 100 scopes are allowed.", + "x-example": null, + "items": { + "type": "string" + } + }, + "duration": { + "type": "integer", + "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", + "x-example": 0 + } + }, + "required": [ + "scopes" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/keys": { + "get": { + "summary": "List keys", + "operationId": "projectsListKeys", + "tags": [ + "projects" + ], + "description": "Get a list of all API keys from the current project. ", + "responses": { + "200": { + "description": "API Keys List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/keyList" + } + } + } + } + }, + "x-appwrite": { + "method": "listKeys", + "group": "keys", + "weight": 184, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/list-keys.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/list-keys.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "keys.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ] + }, + "post": { + "summary": "Create key", + "operationId": "projectsCreateKey", + "tags": [ + "projects" + ], + "description": "Create a new API key. It's recommended to have multiple API keys with strict scopes for separate functions within your project.", + "responses": { + "201": { + "description": "Key", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/key" + } + } + } + } + }, + "x-appwrite": { + "method": "createKey", + "group": "keys", + "weight": 183, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/create-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-key.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "keys.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Key name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "scopes": { + "type": "array", + "description": "Key scopes list. Maximum of 100 scopes are allowed.", + "x-example": null, + "items": { + "type": "string" + } + }, + "expire": { + "type": "string", + "description": "Expiration time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Use null for unlimited expiration.", + "x-example": null + } + }, + "required": [ + "name", + "scopes" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/keys\/{keyId}": { + "get": { + "summary": "Get key", + "operationId": "projectsGetKey", + "tags": [ + "projects" + ], + "description": "Get a key by its unique ID. This endpoint returns details about a specific API key in your project including it's scopes.", + "responses": { + "200": { + "description": "Key", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/key" + } + } + } + } + }, + "x-appwrite": { + "method": "getKey", + "group": "keys", + "weight": 185, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/get-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-key.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "keys.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "keyId", + "description": "Key unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<KEY_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update key", + "operationId": "projectsUpdateKey", + "tags": [ + "projects" + ], + "description": "Update a key by its unique ID. Use this endpoint to update the name, scopes, or expiration time of an API key. ", + "responses": { + "200": { + "description": "Key", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/key" + } + } + } + } + }, + "x-appwrite": { + "method": "updateKey", + "group": "keys", + "weight": 186, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-key.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "keys.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "keyId", + "description": "Key unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<KEY_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Key name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "scopes": { + "type": "array", + "description": "Key scopes list. Maximum of 100 events are allowed.", + "x-example": null, + "items": { + "type": "string" + } + }, + "expire": { + "type": "string", + "description": "Expiration time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Use null for unlimited expiration.", + "x-example": null + } + }, + "required": [ + "name", + "scopes" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete key", + "operationId": "projectsDeleteKey", + "tags": [ + "projects" + ], + "description": "Delete a key by its unique ID. Once deleted, the key can no longer be used to authenticate API calls. ", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteKey", + "group": "keys", + "weight": 187, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/delete-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-key.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "keys.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "keyId", + "description": "Key unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<KEY_ID>" + }, + "in": "path" + } + ] + } + }, + "\/projects\/{projectId}\/oauth2": { + "patch": { + "summary": "Update project OAuth2", + "operationId": "projectsUpdateOAuth2", + "tags": [ + "projects" + ], + "description": "Update the OAuth2 provider configurations. Use this endpoint to set up or update the OAuth2 provider credentials or enable\/disable providers. ", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "updateOAuth2", + "group": "auth", + "weight": 165, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-o-auth2.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-oauth2.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "description": "Provider Name", + "x-example": "amazon", + "enum": [ + "amazon", + "apple", + "auth0", + "authentik", + "autodesk", + "bitbucket", + "bitly", + "box", + "dailymotion", + "discord", + "disqus", + "dropbox", + "etsy", + "facebook", + "figma", + "github", + "gitlab", + "google", + "linkedin", + "microsoft", + "notion", + "oidc", + "okta", + "paypal", + "paypalSandbox", + "podio", + "salesforce", + "slack", + "spotify", + "stripe", + "tradeshift", + "tradeshiftBox", + "twitch", + "wordpress", + "yahoo", + "yammer", + "yandex", + "zoho", + "zoom", + "mock" + ], + "x-enum-name": "OAuthProvider", + "x-enum-keys": [] + }, + "appId": { + "type": "string", + "description": "Provider app ID. Max length: 256 chars.", + "x-example": "<APP_ID>" + }, + "secret": { + "type": "string", + "description": "Provider secret key. Max length: 512 chars.", + "x-example": "<SECRET>" + }, + "enabled": { + "type": "boolean", + "description": "Provider status. Set to 'false' to disable new session creation.", + "x-example": false + } + }, + "required": [ + "provider" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/platforms": { + "get": { + "summary": "List platforms", + "operationId": "projectsListPlatforms", + "tags": [ + "projects" + ], + "description": "Get a list of all platforms in the project. This endpoint returns an array of all platforms and their configurations. ", + "responses": { + "200": { + "description": "Platforms List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/platformList" + } + } + } + } + }, + "x-appwrite": { + "method": "listPlatforms", + "group": "platforms", + "weight": 190, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/list-platforms.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/list-platforms.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "platforms.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ] + }, + "post": { + "summary": "Create platform", + "operationId": "projectsCreatePlatform", + "tags": [ + "projects" + ], + "description": "Create a new platform for your project. Use this endpoint to register a new platform where your users will run your application which will interact with the Appwrite API.", + "responses": { + "201": { + "description": "Platform", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/platform" + } + } + } + } + }, + "x-appwrite": { + "method": "createPlatform", + "group": "platforms", + "weight": 189, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/create-platform.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-platform.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "platforms.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Platform type.", + "x-example": "web", + "enum": [ + "web", + "flutter-web", + "flutter-ios", + "flutter-android", + "flutter-linux", + "flutter-macos", + "flutter-windows", + "apple-ios", + "apple-macos", + "apple-watchos", + "apple-tvos", + "android", + "unity", + "react-native-ios", + "react-native-android" + ], + "x-enum-name": "PlatformType", + "x-enum-keys": [] + }, + "name": { + "type": "string", + "description": "Platform name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "key": { + "type": "string", + "description": "Package name for Android or bundle ID for iOS or macOS. Max length: 256 chars.", + "x-example": "<KEY>" + }, + "store": { + "type": "string", + "description": "App store or Google Play store ID. Max length: 256 chars.", + "x-example": "<STORE>" + }, + "hostname": { + "type": "string", + "description": "Platform client hostname. Max length: 256 chars.", + "x-example": null + } + }, + "required": [ + "type", + "name" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/platforms\/{platformId}": { + "get": { + "summary": "Get platform", + "operationId": "projectsGetPlatform", + "tags": [ + "projects" + ], + "description": "Get a platform by its unique ID. This endpoint returns the platform's details, including its name, type, and key configurations. ", + "responses": { + "200": { + "description": "Platform", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/platform" + } + } + } + } + }, + "x-appwrite": { + "method": "getPlatform", + "group": "platforms", + "weight": 191, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/get-platform.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-platform.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "platforms.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "platformId", + "description": "Platform unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PLATFORM_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update platform", + "operationId": "projectsUpdatePlatform", + "tags": [ + "projects" + ], + "description": "Update a platform by its unique ID. Use this endpoint to update the platform's name, key, platform store ID, or hostname. ", + "responses": { + "200": { + "description": "Platform", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/platform" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePlatform", + "group": "platforms", + "weight": 192, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-platform.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-platform.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "platforms.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "platformId", + "description": "Platform unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PLATFORM_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Platform name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "key": { + "type": "string", + "description": "Package name for android or bundle ID for iOS. Max length: 256 chars.", + "x-example": "<KEY>" + }, + "store": { + "type": "string", + "description": "App store or Google Play store ID. Max length: 256 chars.", + "x-example": "<STORE>" + }, + "hostname": { + "type": "string", + "description": "Platform client URL. Max length: 256 chars.", + "x-example": null + } + }, + "required": [ + "name" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete platform", + "operationId": "projectsDeletePlatform", + "tags": [ + "projects" + ], + "description": "Delete a platform by its unique ID. This endpoint removes the platform and all its configurations from the project. ", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deletePlatform", + "group": "platforms", + "weight": 193, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/delete-platform.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-platform.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "platforms.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "platformId", + "description": "Platform unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PLATFORM_ID>" + }, + "in": "path" + } + ] + } + }, + "\/projects\/{projectId}\/service": { + "patch": { + "summary": "Update service status", + "operationId": "projectsUpdateServiceStatus", + "tags": [ + "projects" + ], + "description": "Update the status of a specific service. Use this endpoint to enable or disable a service in your project. ", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "updateServiceStatus", + "group": "projects", + "weight": 161, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-service-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-service-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "service": { + "type": "string", + "description": "Service name.", + "x-example": "account", + "enum": [ + "account", + "avatars", + "databases", + "locale", + "health", + "storage", + "teams", + "users", + "sites", + "functions", + "graphql", + "messaging" + ], + "x-enum-name": "ApiService", + "x-enum-keys": [] + }, + "status": { + "type": "boolean", + "description": "Service status.", + "x-example": false + } + }, + "required": [ + "service", + "status" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/service\/all": { + "patch": { + "summary": "Update all service status", + "operationId": "projectsUpdateServiceStatusAll", + "tags": [ + "projects" + ], + "description": "Update the status of all services. Use this endpoint to enable or disable all optional services at once. ", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "updateServiceStatusAll", + "group": "projects", + "weight": 162, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-service-status-all.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-service-status-all.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "boolean", + "description": "Service status.", + "x-example": false + } + }, + "required": [ + "status" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/smtp": { + "patch": { + "summary": "Update SMTP", + "operationId": "projectsUpdateSmtp", + "tags": [ + "projects" + ], + "description": "Update the SMTP configuration for your project. Use this endpoint to configure your project's SMTP provider with your custom settings for sending transactional emails. ", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "updateSmtp", + "group": "templates", + "weight": 194, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-smtp.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-smtp.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable custom SMTP service", + "x-example": false + }, + "senderName": { + "type": "string", + "description": "Name of the email sender", + "x-example": "<SENDER_NAME>" + }, + "senderEmail": { + "type": "string", + "description": "Email of the sender", + "x-example": "email@example.com" + }, + "replyTo": { + "type": "string", + "description": "Reply to email", + "x-example": "email@example.com" + }, + "host": { + "type": "string", + "description": "SMTP server host name", + "x-example": null + }, + "port": { + "type": "integer", + "description": "SMTP server port", + "x-example": null + }, + "username": { + "type": "string", + "description": "SMTP server username", + "x-example": "<USERNAME>" + }, + "password": { + "type": "string", + "description": "SMTP server password", + "x-example": "<PASSWORD>" + }, + "secure": { + "type": "string", + "description": "Does SMTP server use secure connection", + "x-example": "tls", + "enum": [ + "tls", + "ssl" + ], + "x-enum-name": "SMTPSecure", + "x-enum-keys": [] + } + }, + "required": [ + "enabled" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/smtp\/tests": { + "post": { + "summary": "Create SMTP test", + "operationId": "projectsCreateSmtpTest", + "tags": [ + "projects" + ], + "description": "Send a test email to verify SMTP configuration. ", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "createSmtpTest", + "group": "templates", + "weight": 195, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/create-smtp-test.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-smtp-test.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "emails": { + "type": "array", + "description": "Array of emails to send test email to. Maximum of 10 emails are allowed.", + "x-example": null, + "items": { + "type": "string" + } + }, + "senderName": { + "type": "string", + "description": "Name of the email sender", + "x-example": "<SENDER_NAME>" + }, + "senderEmail": { + "type": "string", + "description": "Email of the sender", + "x-example": "email@example.com" + }, + "replyTo": { + "type": "string", + "description": "Reply to email", + "x-example": "email@example.com" + }, + "host": { + "type": "string", + "description": "SMTP server host name", + "x-example": null + }, + "port": { + "type": "integer", + "description": "SMTP server port", + "x-example": null + }, + "username": { + "type": "string", + "description": "SMTP server username", + "x-example": "<USERNAME>" + }, + "password": { + "type": "string", + "description": "SMTP server password", + "x-example": "<PASSWORD>" + }, + "secure": { + "type": "string", + "description": "Does SMTP server use secure connection", + "x-example": "tls", + "enum": [ + "tls", + "ssl" + ], + "x-enum-name": "SMTPSecure", + "x-enum-keys": [] + } + }, + "required": [ + "emails", + "senderName", + "senderEmail", + "host" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/team": { + "patch": { + "summary": "Update project team", + "operationId": "projectsUpdateTeam", + "tags": [ + "projects" + ], + "description": "Update the team ID of a project allowing for it to be transferred to another team.", + "responses": { + "200": { + "description": "Project", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/project" + } + } + } + } + }, + "x-appwrite": { + "method": "updateTeam", + "group": "projects", + "weight": 160, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-team.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "teamId": { + "type": "string", + "description": "Team ID of the team to transfer project to.", + "x-example": "<TEAM_ID>" + } + }, + "required": [ + "teamId" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/templates\/email\/{type}\/{locale}": { + "get": { + "summary": "Get custom email template", + "operationId": "projectsGetEmailTemplate", + "tags": [ + "projects" + ], + "description": "Get a custom email template for the specified locale and type. This endpoint returns the template content, subject, and other configuration details. ", + "responses": { + "200": { + "description": "EmailTemplate", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/emailTemplate" + } + } + } + } + }, + "x-appwrite": { + "method": "getEmailTemplate", + "group": "templates", + "weight": 197, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/get-email-template.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-email-template.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "type", + "description": "Template type", + "required": true, + "schema": { + "type": "string", + "x-example": "verification", + "enum": [ + "verification", + "magicsession", + "recovery", + "invitation", + "mfachallenge", + "sessionalert", + "otpsession" + ], + "x-enum-name": "EmailTemplateType", + "x-enum-keys": [] + }, + "in": "path" + }, + { + "name": "locale", + "description": "Template locale", + "required": true, + "schema": { + "type": "string", + "x-example": "af", + "enum": [ + "af", + "ar-ae", + "ar-bh", + "ar-dz", + "ar-eg", + "ar-iq", + "ar-jo", + "ar-kw", + "ar-lb", + "ar-ly", + "ar-ma", + "ar-om", + "ar-qa", + "ar-sa", + "ar-sy", + "ar-tn", + "ar-ye", + "as", + "az", + "be", + "bg", + "bh", + "bn", + "bs", + "ca", + "cs", + "cy", + "da", + "de", + "de-at", + "de-ch", + "de-li", + "de-lu", + "el", + "en", + "en-au", + "en-bz", + "en-ca", + "en-gb", + "en-ie", + "en-jm", + "en-nz", + "en-tt", + "en-us", + "en-za", + "eo", + "es", + "es-ar", + "es-bo", + "es-cl", + "es-co", + "es-cr", + "es-do", + "es-ec", + "es-gt", + "es-hn", + "es-mx", + "es-ni", + "es-pa", + "es-pe", + "es-pr", + "es-py", + "es-sv", + "es-uy", + "es-ve", + "et", + "eu", + "fa", + "fi", + "fo", + "fr", + "fr-be", + "fr-ca", + "fr-ch", + "fr-lu", + "ga", + "gd", + "he", + "hi", + "hr", + "hu", + "id", + "is", + "it", + "it-ch", + "ja", + "ji", + "ko", + "ku", + "lt", + "lv", + "mk", + "ml", + "ms", + "mt", + "nb", + "ne", + "nl", + "nl-be", + "nn", + "no", + "pa", + "pl", + "pt", + "pt-br", + "rm", + "ro", + "ro-md", + "ru", + "ru-md", + "sb", + "sk", + "sl", + "sq", + "sr", + "sv", + "sv-fi", + "th", + "tn", + "tr", + "ts", + "ua", + "ur", + "ve", + "vi", + "xh", + "zh-cn", + "zh-hk", + "zh-sg", + "zh-tw", + "zu" + ], + "x-enum-name": "EmailTemplateLocale", + "x-enum-keys": [] + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update custom email templates", + "operationId": "projectsUpdateEmailTemplate", + "tags": [ + "projects" + ], + "description": "Update a custom email template for the specified locale and type. Use this endpoint to modify the content of your email templates.", + "responses": { + "200": { + "description": "EmailTemplate", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/emailTemplate" + } + } + } + } + }, + "x-appwrite": { + "method": "updateEmailTemplate", + "group": "templates", + "weight": 199, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-email-template.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-email-template.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "type", + "description": "Template type", + "required": true, + "schema": { + "type": "string", + "x-example": "verification", + "enum": [ + "verification", + "magicsession", + "recovery", + "invitation", + "mfachallenge", + "sessionalert", + "otpsession" + ], + "x-enum-name": "EmailTemplateType", + "x-enum-keys": [] + }, + "in": "path" + }, + { + "name": "locale", + "description": "Template locale", + "required": true, + "schema": { + "type": "string", + "x-example": "af", + "enum": [ + "af", + "ar-ae", + "ar-bh", + "ar-dz", + "ar-eg", + "ar-iq", + "ar-jo", + "ar-kw", + "ar-lb", + "ar-ly", + "ar-ma", + "ar-om", + "ar-qa", + "ar-sa", + "ar-sy", + "ar-tn", + "ar-ye", + "as", + "az", + "be", + "bg", + "bh", + "bn", + "bs", + "ca", + "cs", + "cy", + "da", + "de", + "de-at", + "de-ch", + "de-li", + "de-lu", + "el", + "en", + "en-au", + "en-bz", + "en-ca", + "en-gb", + "en-ie", + "en-jm", + "en-nz", + "en-tt", + "en-us", + "en-za", + "eo", + "es", + "es-ar", + "es-bo", + "es-cl", + "es-co", + "es-cr", + "es-do", + "es-ec", + "es-gt", + "es-hn", + "es-mx", + "es-ni", + "es-pa", + "es-pe", + "es-pr", + "es-py", + "es-sv", + "es-uy", + "es-ve", + "et", + "eu", + "fa", + "fi", + "fo", + "fr", + "fr-be", + "fr-ca", + "fr-ch", + "fr-lu", + "ga", + "gd", + "he", + "hi", + "hr", + "hu", + "id", + "is", + "it", + "it-ch", + "ja", + "ji", + "ko", + "ku", + "lt", + "lv", + "mk", + "ml", + "ms", + "mt", + "nb", + "ne", + "nl", + "nl-be", + "nn", + "no", + "pa", + "pl", + "pt", + "pt-br", + "rm", + "ro", + "ro-md", + "ru", + "ru-md", + "sb", + "sk", + "sl", + "sq", + "sr", + "sv", + "sv-fi", + "th", + "tn", + "tr", + "ts", + "ua", + "ur", + "ve", + "vi", + "xh", + "zh-cn", + "zh-hk", + "zh-sg", + "zh-tw", + "zu" + ], + "x-enum-name": "EmailTemplateLocale", + "x-enum-keys": [] + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "subject": { + "type": "string", + "description": "Email Subject", + "x-example": "<SUBJECT>" + }, + "message": { + "type": "string", + "description": "Template message", + "x-example": "<MESSAGE>" + }, + "senderName": { + "type": "string", + "description": "Name of the email sender", + "x-example": "<SENDER_NAME>" + }, + "senderEmail": { + "type": "string", + "description": "Email of the sender", + "x-example": "email@example.com" + }, + "replyTo": { + "type": "string", + "description": "Reply to email", + "x-example": "email@example.com" + } + }, + "required": [ + "subject", + "message" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete custom email template", + "operationId": "projectsDeleteEmailTemplate", + "tags": [ + "projects" + ], + "description": "Reset a custom email template to its default value. This endpoint removes any custom content and restores the template to its original state. ", + "responses": { + "200": { + "description": "EmailTemplate", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/emailTemplate" + } + } + } + } + }, + "x-appwrite": { + "method": "deleteEmailTemplate", + "group": "templates", + "weight": 201, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/delete-email-template.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-email-template.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "type", + "description": "Template type", + "required": true, + "schema": { + "type": "string", + "x-example": "verification", + "enum": [ + "verification", + "magicsession", + "recovery", + "invitation", + "mfachallenge", + "sessionalert", + "otpsession" + ], + "x-enum-name": "EmailTemplateType", + "x-enum-keys": [] + }, + "in": "path" + }, + { + "name": "locale", + "description": "Template locale", + "required": true, + "schema": { + "type": "string", + "x-example": "af", + "enum": [ + "af", + "ar-ae", + "ar-bh", + "ar-dz", + "ar-eg", + "ar-iq", + "ar-jo", + "ar-kw", + "ar-lb", + "ar-ly", + "ar-ma", + "ar-om", + "ar-qa", + "ar-sa", + "ar-sy", + "ar-tn", + "ar-ye", + "as", + "az", + "be", + "bg", + "bh", + "bn", + "bs", + "ca", + "cs", + "cy", + "da", + "de", + "de-at", + "de-ch", + "de-li", + "de-lu", + "el", + "en", + "en-au", + "en-bz", + "en-ca", + "en-gb", + "en-ie", + "en-jm", + "en-nz", + "en-tt", + "en-us", + "en-za", + "eo", + "es", + "es-ar", + "es-bo", + "es-cl", + "es-co", + "es-cr", + "es-do", + "es-ec", + "es-gt", + "es-hn", + "es-mx", + "es-ni", + "es-pa", + "es-pe", + "es-pr", + "es-py", + "es-sv", + "es-uy", + "es-ve", + "et", + "eu", + "fa", + "fi", + "fo", + "fr", + "fr-be", + "fr-ca", + "fr-ch", + "fr-lu", + "ga", + "gd", + "he", + "hi", + "hr", + "hu", + "id", + "is", + "it", + "it-ch", + "ja", + "ji", + "ko", + "ku", + "lt", + "lv", + "mk", + "ml", + "ms", + "mt", + "nb", + "ne", + "nl", + "nl-be", + "nn", + "no", + "pa", + "pl", + "pt", + "pt-br", + "rm", + "ro", + "ro-md", + "ru", + "ru-md", + "sb", + "sk", + "sl", + "sq", + "sr", + "sv", + "sv-fi", + "th", + "tn", + "tr", + "ts", + "ua", + "ur", + "ve", + "vi", + "xh", + "zh-cn", + "zh-hk", + "zh-sg", + "zh-tw", + "zu" + ], + "x-enum-name": "EmailTemplateLocale", + "x-enum-keys": [] + }, + "in": "path" + } + ] + } + }, + "\/projects\/{projectId}\/templates\/sms\/{type}\/{locale}": { + "get": { + "summary": "Get custom SMS template", + "operationId": "projectsGetSmsTemplate", + "tags": [ + "projects" + ], + "description": "Get a custom SMS template for the specified locale and type returning it's contents.", + "responses": { + "200": { + "description": "SmsTemplate", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/smsTemplate" + } + } + } + } + }, + "x-appwrite": { + "method": "getSmsTemplate", + "group": "templates", + "weight": 196, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/get-sms-template.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-sms-template.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "type", + "description": "Template type", + "required": true, + "schema": { + "type": "string", + "x-example": "verification", + "enum": [ + "verification", + "login", + "invitation", + "mfachallenge" + ], + "x-enum-name": "SmsTemplateType", + "x-enum-keys": [] + }, + "in": "path" + }, + { + "name": "locale", + "description": "Template locale", + "required": true, + "schema": { + "type": "string", + "x-example": "af", + "enum": [ + "af", + "ar-ae", + "ar-bh", + "ar-dz", + "ar-eg", + "ar-iq", + "ar-jo", + "ar-kw", + "ar-lb", + "ar-ly", + "ar-ma", + "ar-om", + "ar-qa", + "ar-sa", + "ar-sy", + "ar-tn", + "ar-ye", + "as", + "az", + "be", + "bg", + "bh", + "bn", + "bs", + "ca", + "cs", + "cy", + "da", + "de", + "de-at", + "de-ch", + "de-li", + "de-lu", + "el", + "en", + "en-au", + "en-bz", + "en-ca", + "en-gb", + "en-ie", + "en-jm", + "en-nz", + "en-tt", + "en-us", + "en-za", + "eo", + "es", + "es-ar", + "es-bo", + "es-cl", + "es-co", + "es-cr", + "es-do", + "es-ec", + "es-gt", + "es-hn", + "es-mx", + "es-ni", + "es-pa", + "es-pe", + "es-pr", + "es-py", + "es-sv", + "es-uy", + "es-ve", + "et", + "eu", + "fa", + "fi", + "fo", + "fr", + "fr-be", + "fr-ca", + "fr-ch", + "fr-lu", + "ga", + "gd", + "he", + "hi", + "hr", + "hu", + "id", + "is", + "it", + "it-ch", + "ja", + "ji", + "ko", + "ku", + "lt", + "lv", + "mk", + "ml", + "ms", + "mt", + "nb", + "ne", + "nl", + "nl-be", + "nn", + "no", + "pa", + "pl", + "pt", + "pt-br", + "rm", + "ro", + "ro-md", + "ru", + "ru-md", + "sb", + "sk", + "sl", + "sq", + "sr", + "sv", + "sv-fi", + "th", + "tn", + "tr", + "ts", + "ua", + "ur", + "ve", + "vi", + "xh", + "zh-cn", + "zh-hk", + "zh-sg", + "zh-tw", + "zu" + ], + "x-enum-name": "SmsTemplateLocale", + "x-enum-keys": [] + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update custom SMS template", + "operationId": "projectsUpdateSmsTemplate", + "tags": [ + "projects" + ], + "description": "Update a custom SMS template for the specified locale and type. Use this endpoint to modify the content of your SMS templates. ", + "responses": { + "200": { + "description": "SmsTemplate", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/smsTemplate" + } + } + } + } + }, + "x-appwrite": { + "method": "updateSmsTemplate", + "group": "templates", + "weight": 198, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-sms-template.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-sms-template.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "type", + "description": "Template type", + "required": true, + "schema": { + "type": "string", + "x-example": "verification", + "enum": [ + "verification", + "login", + "invitation", + "mfachallenge" + ], + "x-enum-name": "SmsTemplateType", + "x-enum-keys": [] + }, + "in": "path" + }, + { + "name": "locale", + "description": "Template locale", + "required": true, + "schema": { + "type": "string", + "x-example": "af", + "enum": [ + "af", + "ar-ae", + "ar-bh", + "ar-dz", + "ar-eg", + "ar-iq", + "ar-jo", + "ar-kw", + "ar-lb", + "ar-ly", + "ar-ma", + "ar-om", + "ar-qa", + "ar-sa", + "ar-sy", + "ar-tn", + "ar-ye", + "as", + "az", + "be", + "bg", + "bh", + "bn", + "bs", + "ca", + "cs", + "cy", + "da", + "de", + "de-at", + "de-ch", + "de-li", + "de-lu", + "el", + "en", + "en-au", + "en-bz", + "en-ca", + "en-gb", + "en-ie", + "en-jm", + "en-nz", + "en-tt", + "en-us", + "en-za", + "eo", + "es", + "es-ar", + "es-bo", + "es-cl", + "es-co", + "es-cr", + "es-do", + "es-ec", + "es-gt", + "es-hn", + "es-mx", + "es-ni", + "es-pa", + "es-pe", + "es-pr", + "es-py", + "es-sv", + "es-uy", + "es-ve", + "et", + "eu", + "fa", + "fi", + "fo", + "fr", + "fr-be", + "fr-ca", + "fr-ch", + "fr-lu", + "ga", + "gd", + "he", + "hi", + "hr", + "hu", + "id", + "is", + "it", + "it-ch", + "ja", + "ji", + "ko", + "ku", + "lt", + "lv", + "mk", + "ml", + "ms", + "mt", + "nb", + "ne", + "nl", + "nl-be", + "nn", + "no", + "pa", + "pl", + "pt", + "pt-br", + "rm", + "ro", + "ro-md", + "ru", + "ru-md", + "sb", + "sk", + "sl", + "sq", + "sr", + "sv", + "sv-fi", + "th", + "tn", + "tr", + "ts", + "ua", + "ur", + "ve", + "vi", + "xh", + "zh-cn", + "zh-hk", + "zh-sg", + "zh-tw", + "zu" + ], + "x-enum-name": "SmsTemplateLocale", + "x-enum-keys": [] + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Template message", + "x-example": "<MESSAGE>" + } + }, + "required": [ + "message" + ] + } + } + } + } + }, + "delete": { + "summary": "Reset custom SMS template", + "operationId": "projectsDeleteSmsTemplate", + "tags": [ + "projects" + ], + "description": "Reset a custom SMS template to its default value. This endpoint removes any custom message and restores the template to its original state. ", + "responses": { + "200": { + "description": "SmsTemplate", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/smsTemplate" + } + } + } + } + }, + "x-appwrite": { + "method": "deleteSmsTemplate", + "group": "templates", + "weight": 200, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/delete-sms-template.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-sms-template.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "type", + "description": "Template type", + "required": true, + "schema": { + "type": "string", + "x-example": "verification", + "enum": [ + "verification", + "login", + "invitation", + "mfachallenge" + ], + "x-enum-name": "SmsTemplateType", + "x-enum-keys": [] + }, + "in": "path" + }, + { + "name": "locale", + "description": "Template locale", + "required": true, + "schema": { + "type": "string", + "x-example": "af", + "enum": [ + "af", + "ar-ae", + "ar-bh", + "ar-dz", + "ar-eg", + "ar-iq", + "ar-jo", + "ar-kw", + "ar-lb", + "ar-ly", + "ar-ma", + "ar-om", + "ar-qa", + "ar-sa", + "ar-sy", + "ar-tn", + "ar-ye", + "as", + "az", + "be", + "bg", + "bh", + "bn", + "bs", + "ca", + "cs", + "cy", + "da", + "de", + "de-at", + "de-ch", + "de-li", + "de-lu", + "el", + "en", + "en-au", + "en-bz", + "en-ca", + "en-gb", + "en-ie", + "en-jm", + "en-nz", + "en-tt", + "en-us", + "en-za", + "eo", + "es", + "es-ar", + "es-bo", + "es-cl", + "es-co", + "es-cr", + "es-do", + "es-ec", + "es-gt", + "es-hn", + "es-mx", + "es-ni", + "es-pa", + "es-pe", + "es-pr", + "es-py", + "es-sv", + "es-uy", + "es-ve", + "et", + "eu", + "fa", + "fi", + "fo", + "fr", + "fr-be", + "fr-ca", + "fr-ch", + "fr-lu", + "ga", + "gd", + "he", + "hi", + "hr", + "hu", + "id", + "is", + "it", + "it-ch", + "ja", + "ji", + "ko", + "ku", + "lt", + "lv", + "mk", + "ml", + "ms", + "mt", + "nb", + "ne", + "nl", + "nl-be", + "nn", + "no", + "pa", + "pl", + "pt", + "pt-br", + "rm", + "ro", + "ro-md", + "ru", + "ru-md", + "sb", + "sk", + "sl", + "sq", + "sr", + "sv", + "sv-fi", + "th", + "tn", + "tr", + "ts", + "ua", + "ur", + "ve", + "vi", + "xh", + "zh-cn", + "zh-hk", + "zh-sg", + "zh-tw", + "zu" + ], + "x-enum-name": "SmsTemplateLocale", + "x-enum-keys": [] + }, + "in": "path" + } + ] + } + }, + "\/projects\/{projectId}\/webhooks": { + "get": { + "summary": "List webhooks", + "operationId": "projectsListWebhooks", + "tags": [ + "projects" + ], + "description": "Get a list of all webhooks belonging to the project. You can use the query params to filter your results. ", + "responses": { + "200": { + "description": "Webhooks List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/webhookList" + } + } + } + } + }, + "x-appwrite": { + "method": "listWebhooks", + "group": "webhooks", + "weight": 178, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/list-webhooks.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/list-webhooks.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ] + }, + "post": { + "summary": "Create webhook", + "operationId": "projectsCreateWebhook", + "tags": [ + "projects" + ], + "description": "Create a new webhook. Use this endpoint to configure a URL that will receive events from Appwrite when specific events occur. ", + "responses": { + "201": { + "description": "Webhook", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/webhook" + } + } + } + } + }, + "x-appwrite": { + "method": "createWebhook", + "group": "webhooks", + "weight": 177, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/create-webhook.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-webhook.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Webhook name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Enable or disable a webhook.", + "x-example": false + }, + "events": { + "type": "array", + "description": "Events list. Maximum of 100 events are allowed.", + "x-example": null, + "items": { + "type": "string" + } + }, + "url": { + "type": "string", + "description": "Webhook URL.", + "x-example": null + }, + "security": { + "type": "boolean", + "description": "Certificate verification, false for disabled or true for enabled.", + "x-example": false + }, + "httpUser": { + "type": "string", + "description": "Webhook HTTP user. Max length: 256 chars.", + "x-example": "<HTTP_USER>" + }, + "httpPass": { + "type": "string", + "description": "Webhook HTTP password. Max length: 256 chars.", + "x-example": "<HTTP_PASS>" + } + }, + "required": [ + "name", + "events", + "url", + "security" + ] + } + } + } + } + } + }, + "\/projects\/{projectId}\/webhooks\/{webhookId}": { + "get": { + "summary": "Get webhook", + "operationId": "projectsGetWebhook", + "tags": [ + "projects" + ], + "description": "Get a webhook by its unique ID. This endpoint returns details about a specific webhook configured for a project. ", + "responses": { + "200": { + "description": "Webhook", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/webhook" + } + } + } + } + }, + "x-appwrite": { + "method": "getWebhook", + "group": "webhooks", + "weight": 179, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/get-webhook.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-webhook.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "webhookId", + "description": "Webhook unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<WEBHOOK_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update webhook", + "operationId": "projectsUpdateWebhook", + "tags": [ + "projects" + ], + "description": "Update a webhook by its unique ID. Use this endpoint to update the URL, events, or status of an existing webhook. ", + "responses": { + "200": { + "description": "Webhook", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/webhook" + } + } + } + } + }, + "x-appwrite": { + "method": "updateWebhook", + "group": "webhooks", + "weight": 180, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-webhook.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-webhook.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "webhookId", + "description": "Webhook unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<WEBHOOK_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Webhook name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Enable or disable a webhook.", + "x-example": false + }, + "events": { + "type": "array", + "description": "Events list. Maximum of 100 events are allowed.", + "x-example": null, + "items": { + "type": "string" + } + }, + "url": { + "type": "string", + "description": "Webhook URL.", + "x-example": null + }, + "security": { + "type": "boolean", + "description": "Certificate verification, false for disabled or true for enabled.", + "x-example": false + }, + "httpUser": { + "type": "string", + "description": "Webhook HTTP user. Max length: 256 chars.", + "x-example": "<HTTP_USER>" + }, + "httpPass": { + "type": "string", + "description": "Webhook HTTP password. Max length: 256 chars.", + "x-example": "<HTTP_PASS>" + } + }, + "required": [ + "name", + "events", + "url", + "security" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete webhook", + "operationId": "projectsDeleteWebhook", + "tags": [ + "projects" + ], + "description": "Delete a webhook by its unique ID. Once deleted, the webhook will no longer receive project events. ", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteWebhook", + "group": "webhooks", + "weight": 182, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/delete-webhook.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-webhook.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "webhookId", + "description": "Webhook unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<WEBHOOK_ID>" + }, + "in": "path" + } + ] + } + }, + "\/projects\/{projectId}\/webhooks\/{webhookId}\/signature": { + "patch": { + "summary": "Update webhook signature key", + "operationId": "projectsUpdateWebhookSignature", + "tags": [ + "projects" + ], + "description": "Update the webhook signature key. This endpoint can be used to regenerate the signature key used to sign and validate payload deliveries for a specific webhook. ", + "responses": { + "200": { + "description": "Webhook", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/webhook" + } + } + } + } + }, + "x-appwrite": { + "method": "updateWebhookSignature", + "group": "webhooks", + "weight": 181, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-webhook-signature.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-webhook-signature.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROJECT_ID>" + }, + "in": "path" + }, + { + "name": "webhookId", + "description": "Webhook unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<WEBHOOK_ID>" + }, + "in": "path" + } + ] + } + }, + "\/proxy\/rules": { + "get": { + "summary": "List rules", + "operationId": "proxyListRules", + "tags": [ + "proxy" + ], + "description": "Get a list of all the proxy rules. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Rule List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/proxyRuleList" + } + } + } + } + }, + "x-appwrite": { + "method": "listRules", + "group": null, + "weight": 294, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "proxy\/list-rules.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/proxy\/list-rules.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rules.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/databases#querying-documents). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: domain, type, trigger, deploymentResourceType, deploymentResourceId, deploymentId, deploymentVcsProviderBranch", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/proxy\/rules\/api": { + "post": { + "summary": "Create API rule", + "operationId": "proxyCreateAPIRule", + "tags": [ + "proxy" + ], + "description": "Create a new proxy rule for serving Appwrite's API on custom domain.", + "responses": { + "201": { + "description": "Rule", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/proxyRule" + } + } + } + } + }, + "x-appwrite": { + "method": "createAPIRule", + "group": null, + "weight": 435, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "proxy\/create-a-p-i-rule.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new proxy rule for serving Appwrite's API on custom domain.", + "rate-limit": 10, + "rate-time": 60, + "rate-key": "userId:{userId}, url:{url}", + "scope": "rules.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "domain": { + "type": "string", + "description": "Domain name.", + "x-example": null + } + }, + "required": [ + "domain" + ] + } + } + } + } + } + }, + "\/proxy\/rules\/function": { + "post": { + "summary": "Create function rule", + "operationId": "proxyCreateFunctionRule", + "tags": [ + "proxy" + ], + "description": "Create a new proxy rule for executing Appwrite Function on custom domain.", + "responses": { + "201": { + "description": "Rule", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/proxyRule" + } + } + } + } + }, + "x-appwrite": { + "method": "createFunctionRule", + "group": null, + "weight": 437, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "proxy\/create-function-rule.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new proxy rule for executing Appwrite Function on custom domain.", + "rate-limit": 10, + "rate-time": 60, + "rate-key": "userId:{userId}, url:{url}", + "scope": "rules.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "domain": { + "type": "string", + "description": "Domain name.", + "x-example": null + }, + "functionId": { + "type": "string", + "description": "ID of function to be executed.", + "x-example": "<FUNCTION_ID>" + }, + "branch": { + "type": "string", + "description": "Name of VCS branch to deploy changes automatically", + "x-example": "<BRANCH>" + } + }, + "required": [ + "domain", + "functionId" + ] + } + } + } + } + } + }, + "\/proxy\/rules\/redirect": { + "post": { + "summary": "Create Redirect rule", + "operationId": "proxyCreateRedirectRule", + "tags": [ + "proxy" + ], + "description": "Create a new proxy rule for to redirect from custom domain to another domain.", + "responses": { + "201": { + "description": "Rule", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/proxyRule" + } + } + } + } + }, + "x-appwrite": { + "method": "createRedirectRule", + "group": null, + "weight": 438, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "proxy\/create-redirect-rule.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new proxy rule for to redirect from custom domain to another domain.", + "rate-limit": 10, + "rate-time": 60, + "rate-key": "userId:{userId}, url:{url}", + "scope": "rules.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "domain": { + "type": "string", + "description": "Domain name.", + "x-example": null + }, + "url": { + "type": "string", + "description": "Target URL of redirection", + "x-example": "https:\/\/example.com" + }, + "statusCode": { + "type": "string", + "description": "Status code of redirection", + "x-example": "301", + "enum": [ + "301", + "302", + "307", + "308" + ], + "x-enum-name": null, + "x-enum-keys": [ + "Moved Permanently 301", + "Found 302", + "Temporary Redirect 307", + "Permanent Redirect 308" + ] + }, + "resourceId": { + "type": "string", + "description": "ID of parent resource.", + "x-example": "<RESOURCE_ID>" + }, + "resourceType": { + "type": "string", + "description": "Type of parent resource.", + "x-example": "site", + "enum": [ + "site", + "function" + ], + "x-enum-name": "ProxyResourceType", + "x-enum-keys": [ + "Site", + "Function" + ] + } + }, + "required": [ + "domain", + "url", + "statusCode", + "resourceId", + "resourceType" + ] + } + } + } + } + } + }, + "\/proxy\/rules\/site": { + "post": { + "summary": "Create site rule", + "operationId": "proxyCreateSiteRule", + "tags": [ + "proxy" + ], + "description": "Create a new proxy rule for serving Appwrite Site on custom domain.", + "responses": { + "201": { + "description": "Rule", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/proxyRule" + } + } + } + } + }, + "x-appwrite": { + "method": "createSiteRule", + "group": null, + "weight": 436, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "proxy\/create-site-rule.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new proxy rule for serving Appwrite Site on custom domain.", + "rate-limit": 10, + "rate-time": 60, + "rate-key": "userId:{userId}, url:{url}", + "scope": "rules.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "domain": { + "type": "string", + "description": "Domain name.", + "x-example": null + }, + "siteId": { + "type": "string", + "description": "ID of site to be executed.", + "x-example": "<SITE_ID>" + }, + "branch": { + "type": "string", + "description": "Name of VCS branch to deploy changes automatically", + "x-example": "<BRANCH>" + } + }, + "required": [ + "domain", + "siteId" + ] + } + } + } + } + } + }, + "\/proxy\/rules\/{ruleId}": { + "get": { + "summary": "Get rule", + "operationId": "proxyGetRule", + "tags": [ + "proxy" + ], + "description": "Get a proxy rule by its unique ID.", + "responses": { + "200": { + "description": "Rule", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/proxyRule" + } + } + } + } + }, + "x-appwrite": { + "method": "getRule", + "group": null, + "weight": 295, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "proxy\/get-rule.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/proxy\/get-rule.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rules.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "ruleId", + "description": "Rule ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<RULE_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete rule", + "operationId": "proxyDeleteRule", + "tags": [ + "proxy" + ], + "description": "Delete a proxy rule by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteRule", + "group": null, + "weight": 296, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "proxy\/delete-rule.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/proxy\/delete-rule.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rules.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "ruleId", + "description": "Rule ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<RULE_ID>" + }, + "in": "path" + } + ] + } + }, + "\/proxy\/rules\/{ruleId}\/verification": { + "patch": { + "summary": "Update rule verification status", + "operationId": "proxyUpdateRuleVerification", + "tags": [ + "proxy" + ], + "description": "Retry getting verification process of a proxy rule. This endpoint triggers domain verification by checking DNS records (CNAME) against the configured target domain. If verification is successful, a TLS certificate will be automatically provisioned for the domain.", + "responses": { + "200": { + "description": "Rule", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/proxyRule" + } + } + } + } + }, + "x-appwrite": { + "method": "updateRuleVerification", + "group": null, + "weight": 297, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "proxy\/update-rule-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/proxy\/update-rule-verification.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rules.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "ruleId", + "description": "Rule ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<RULE_ID>" + }, + "in": "path" + } + ] + } + }, + "\/sites": { + "get": { + "summary": "List sites", + "operationId": "sitesList", + "tags": [ + "sites" + ], + "description": "Get a list of all the project's sites. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Sites List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/siteList" + } + } + } + } + }, + "x-appwrite": { + "method": "list", + "group": "sites", + "weight": 407, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the project's sites. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, enabled, framework, deploymentId, buildCommand, installCommand, outputDirectory, installationId", + "required": false, + "schema": { + "type": "string", + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create site", + "operationId": "sitesCreate", + "tags": [ + "sites" + ], + "description": "Create a new site.", + "responses": { + "201": { + "description": "Site", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/site" + } + } + } + } + }, + "x-appwrite": { + "method": "create", + "group": "sites", + "weight": 405, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new site.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "siteId": { + "type": "string", + "description": "Site ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<SITE_ID>" + }, + "name": { + "type": "string", + "description": "Site name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "framework": { + "type": "string", + "description": "Sites framework.", + "x-example": "analog", + "enum": [ + "analog", + "angular", + "nextjs", + "react", + "nuxt", + "vue", + "sveltekit", + "astro", + "remix", + "lynx", + "flutter", + "react-native", + "vite", + "other" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "enabled": { + "type": "boolean", + "description": "Is site enabled? When set to 'disabled', users cannot access the site but Server SDKs with and API key can still access the site. No data is lost when this is toggled.", + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.", + "x-example": false + }, + "timeout": { + "type": "integer", + "description": "Maximum request time in seconds.", + "x-example": 1 + }, + "installCommand": { + "type": "string", + "description": "Install Command.", + "x-example": "<INSTALL_COMMAND>" + }, + "buildCommand": { + "type": "string", + "description": "Build Command.", + "x-example": "<BUILD_COMMAND>" + }, + "outputDirectory": { + "type": "string", + "description": "Output Directory for site.", + "x-example": "<OUTPUT_DIRECTORY>" + }, + "buildRuntime": { + "type": "string", + "description": "Runtime to use during build step.", + "x-example": "node-14.5", + "enum": [ + "node-14.5", + "node-16.0", + "node-18.0", + "node-19.0", + "node-20.0", + "node-21.0", + "node-22", + "php-8.0", + "php-8.1", + "php-8.2", + "php-8.3", + "ruby-3.0", + "ruby-3.1", + "ruby-3.2", + "ruby-3.3", + "python-3.8", + "python-3.9", + "python-3.10", + "python-3.11", + "python-3.12", + "python-ml-3.11", + "python-ml-3.12", + "deno-1.21", + "deno-1.24", + "deno-1.35", + "deno-1.40", + "deno-1.46", + "deno-2.0", + "dart-2.15", + "dart-2.16", + "dart-2.17", + "dart-2.18", + "dart-2.19", + "dart-3.0", + "dart-3.1", + "dart-3.3", + "dart-3.5", + "dart-3.8", + "dotnet-6.0", + "dotnet-7.0", + "dotnet-8.0", + "java-8.0", + "java-11.0", + "java-17.0", + "java-18.0", + "java-21.0", + "java-22", + "swift-5.5", + "swift-5.8", + "swift-5.9", + "swift-5.10", + "kotlin-1.6", + "kotlin-1.8", + "kotlin-1.9", + "kotlin-2.0", + "cpp-17", + "cpp-20", + "bun-1.0", + "bun-1.1", + "go-1.23", + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29", + "flutter-3.32" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "adapter": { + "type": "string", + "description": "Framework adapter defining rendering strategy. Allowed values are: static, ssr", + "x-example": "static", + "enum": [ + "static", + "ssr" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "installationId": { + "type": "string", + "description": "Appwrite Installation ID for VCS (Version Control System) deployment.", + "x-example": "<INSTALLATION_ID>" + }, + "fallbackFile": { + "type": "string", + "description": "Fallback file for single page application sites.", + "x-example": "<FALLBACK_FILE>" + }, + "providerRepositoryId": { + "type": "string", + "description": "Repository ID of the repo linked to the site.", + "x-example": "<PROVIDER_REPOSITORY_ID>" + }, + "providerBranch": { + "type": "string", + "description": "Production branch for the repo linked to the site.", + "x-example": "<PROVIDER_BRANCH>" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is the VCS (Version Control System) connection in silent mode for the repo linked to the site? In silent mode, comments will not be made on commits and pull requests.", + "x-example": false + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to site code in the linked repo.", + "x-example": "<PROVIDER_ROOT_DIRECTORY>" + }, + "specification": { + "type": "string", + "description": "Framework specification for the site and builds.", + "x-example": null + } + }, + "required": [ + "siteId", + "name", + "framework", + "buildRuntime" + ] + } + } + } + } + } + }, + "\/sites\/frameworks": { + "get": { + "summary": "List frameworks", + "operationId": "sitesListFrameworks", + "tags": [ + "sites" + ], + "description": "Get a list of all frameworks that are currently available on the server instance.", + "responses": { + "200": { + "description": "Frameworks List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/frameworkList" + } + } + } + } + }, + "x-appwrite": { + "method": "listFrameworks", + "group": "frameworks", + "weight": 410, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-frameworks.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all frameworks that are currently available on the server instance.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/sites\/specifications": { + "get": { + "summary": "List specifications", + "operationId": "sitesListSpecifications", + "tags": [ + "sites" + ], + "description": "List allowed site specifications for this instance.", + "responses": { + "200": { + "description": "Specifications List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/specificationList" + } + } + } + } + }, + "x-appwrite": { + "method": "listSpecifications", + "group": "frameworks", + "weight": 433, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-specifications.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList allowed site specifications for this instance.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/sites\/templates": { + "get": { + "summary": "List templates", + "operationId": "sitesListTemplates", + "tags": [ + "sites" + ], + "description": "List available site templates. You can use template details in [createSite](\/docs\/references\/cloud\/server-nodejs\/sites#create) method.", + "responses": { + "200": { + "description": "Site Templates List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/templateSiteList" + } + } + } + } + }, + "x-appwrite": { + "method": "listTemplates", + "group": "templates", + "weight": 429, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-templates.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList available site templates. You can use template details in [createSite](\/docs\/references\/cloud\/server-nodejs\/sites#create) method.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "frameworks", + "description": "List of frameworks allowed for filtering site templates. Maximum of 100 frameworks are allowed.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "useCases", + "description": "List of use cases allowed for filtering site templates. Maximum of 100 use cases are allowed.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "limit", + "description": "Limit the number of templates returned in the response. Default limit is 25, and maximum limit is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 1, + "default": 25 + }, + "in": "query" + }, + { + "name": "offset", + "description": "Offset the list of returned templates. Maximum offset is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0 + }, + "in": "query" + } + ] + } + }, + "\/sites\/templates\/{templateId}": { + "get": { + "summary": "Get site template", + "operationId": "sitesGetTemplate", + "tags": [ + "sites" + ], + "description": "Get a site template using ID. You can use template details in [createSite](\/docs\/references\/cloud\/server-nodejs\/sites#create) method.", + "responses": { + "200": { + "description": "Template Site", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/templateSite" + } + } + } + } + }, + "x-appwrite": { + "method": "getTemplate", + "group": "templates", + "weight": 430, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get-template.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a site template using ID. You can use template details in [createSite](\/docs\/references\/cloud\/server-nodejs\/sites#create) method.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "templateId", + "description": "Template ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEMPLATE_ID>" + }, + "in": "path" + } + ] + } + }, + "\/sites\/usage": { + "get": { + "summary": "Get sites usage", + "operationId": "sitesListUsage", + "tags": [ + "sites" + ], + "description": "Get usage metrics and statistics for all sites in the project. View statistics including total deployments, builds, logs, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", + "responses": { + "200": { + "description": "UsageSites", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/usageSites" + } + } + } + } + }, + "x-appwrite": { + "method": "listUsage", + "group": null, + "weight": 431, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet usage metrics and statistics for all sites in the project. View statistics including total deployments, builds, logs, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "range", + "description": "Date range.", + "required": false, + "schema": { + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "SiteUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d" + }, + "in": "query" + } + ] + } + }, + "\/sites\/{siteId}": { + "get": { + "summary": "Get site", + "operationId": "sitesGet", + "tags": [ + "sites" + ], + "description": "Get a site by its unique ID.", + "responses": { + "200": { + "description": "Site", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/site" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": "sites", + "weight": 406, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a site by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update site", + "operationId": "sitesUpdate", + "tags": [ + "sites" + ], + "description": "Update site by its unique ID.", + "responses": { + "200": { + "description": "Site", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/site" + } + } + } + } + }, + "x-appwrite": { + "method": "update", + "group": "sites", + "weight": 408, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/update.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate site by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Site name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "framework": { + "type": "string", + "description": "Sites framework.", + "x-example": "analog", + "enum": [ + "analog", + "angular", + "nextjs", + "react", + "nuxt", + "vue", + "sveltekit", + "astro", + "remix", + "lynx", + "flutter", + "react-native", + "vite", + "other" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "enabled": { + "type": "boolean", + "description": "Is site enabled? When set to 'disabled', users cannot access the site but Server SDKs with and API key can still access the site. No data is lost when this is toggled.", + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.", + "x-example": false + }, + "timeout": { + "type": "integer", + "description": "Maximum request time in seconds.", + "x-example": 1 + }, + "installCommand": { + "type": "string", + "description": "Install Command.", + "x-example": "<INSTALL_COMMAND>" + }, + "buildCommand": { + "type": "string", + "description": "Build Command.", + "x-example": "<BUILD_COMMAND>" + }, + "outputDirectory": { + "type": "string", + "description": "Output Directory for site.", + "x-example": "<OUTPUT_DIRECTORY>" + }, + "buildRuntime": { + "type": "string", + "description": "Runtime to use during build step.", + "x-example": "node-14.5", + "enum": [ + "node-14.5", + "node-16.0", + "node-18.0", + "node-19.0", + "node-20.0", + "node-21.0", + "node-22", + "php-8.0", + "php-8.1", + "php-8.2", + "php-8.3", + "ruby-3.0", + "ruby-3.1", + "ruby-3.2", + "ruby-3.3", + "python-3.8", + "python-3.9", + "python-3.10", + "python-3.11", + "python-3.12", + "python-ml-3.11", + "python-ml-3.12", + "deno-1.21", + "deno-1.24", + "deno-1.35", + "deno-1.40", + "deno-1.46", + "deno-2.0", + "dart-2.15", + "dart-2.16", + "dart-2.17", + "dart-2.18", + "dart-2.19", + "dart-3.0", + "dart-3.1", + "dart-3.3", + "dart-3.5", + "dart-3.8", + "dotnet-6.0", + "dotnet-7.0", + "dotnet-8.0", + "java-8.0", + "java-11.0", + "java-17.0", + "java-18.0", + "java-21.0", + "java-22", + "swift-5.5", + "swift-5.8", + "swift-5.9", + "swift-5.10", + "kotlin-1.6", + "kotlin-1.8", + "kotlin-1.9", + "kotlin-2.0", + "cpp-17", + "cpp-20", + "bun-1.0", + "bun-1.1", + "go-1.23", + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29", + "flutter-3.32" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "adapter": { + "type": "string", + "description": "Framework adapter defining rendering strategy. Allowed values are: static, ssr", + "x-example": "static", + "enum": [ + "static", + "ssr" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "fallbackFile": { + "type": "string", + "description": "Fallback file for single page application sites.", + "x-example": "<FALLBACK_FILE>" + }, + "installationId": { + "type": "string", + "description": "Appwrite Installation ID for VCS (Version Control System) deployment.", + "x-example": "<INSTALLATION_ID>" + }, + "providerRepositoryId": { + "type": "string", + "description": "Repository ID of the repo linked to the site.", + "x-example": "<PROVIDER_REPOSITORY_ID>" + }, + "providerBranch": { + "type": "string", + "description": "Production branch for the repo linked to the site.", + "x-example": "<PROVIDER_BRANCH>" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is the VCS (Version Control System) connection in silent mode for the repo linked to the site? In silent mode, comments will not be made on commits and pull requests.", + "x-example": false + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to site code in the linked repo.", + "x-example": "<PROVIDER_ROOT_DIRECTORY>" + }, + "specification": { + "type": "string", + "description": "Framework specification for the site and builds.", + "x-example": null + } + }, + "required": [ + "name", + "framework" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete site", + "operationId": "sitesDelete", + "tags": [ + "sites" + ], + "description": "Delete a site by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "sites", + "weight": 409, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a site by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ] + } + }, + "\/sites\/{siteId}\/deployment": { + "patch": { + "summary": "Update site's deployment", + "operationId": "sitesUpdateSiteDeployment", + "tags": [ + "sites" + ], + "description": "Update the site active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your site.", + "responses": { + "200": { + "description": "Site", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/site" + } + } + } + } + }, + "x-appwrite": { + "method": "updateSiteDeployment", + "group": "sites", + "weight": 416, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/update-site-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate the site active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your site.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "deploymentId": { + "type": "string", + "description": "Deployment ID.", + "x-example": "<DEPLOYMENT_ID>" + } + }, + "required": [ + "deploymentId" + ] + } + } + } + } + } + }, + "\/sites\/{siteId}\/deployments": { + "get": { + "summary": "List deployments", + "operationId": "sitesListDeployments", + "tags": [ + "sites" + ], + "description": "Get a list of all the site's code deployments. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Deployments List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deploymentList" + } + } + } + } + }, + "x-appwrite": { + "method": "listDeployments", + "group": "deployments", + "weight": 415, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-deployments.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the site's code deployments. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create deployment", + "operationId": "sitesCreateDeployment", + "tags": [ + "sites" + ], + "description": "Create a new site code deployment. Use this endpoint to upload a new version of your site code. To activate your newly uploaded code, you'll need to update the function's deployment to use your new deployment ID.", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createDeployment", + "group": "deployments", + "weight": 411, + "cookies": false, + "type": "upload", + "deprecated": false, + "demo": "sites\/create-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new site code deployment. Use this endpoint to upload a new version of your site code. To activate your newly uploaded code, you'll need to update the function's deployment to use your new deployment ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": true, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "multipart\/form-data": { + "schema": { + "type": "object", + "properties": { + "installCommand": { + "type": "string", + "description": "Install Commands.", + "x-example": "<INSTALL_COMMAND>" + }, + "buildCommand": { + "type": "string", + "description": "Build Commands.", + "x-example": "<BUILD_COMMAND>" + }, + "outputDirectory": { + "type": "string", + "description": "Output Directory.", + "x-example": "<OUTPUT_DIRECTORY>" + }, + "code": { + "type": "string", + "description": "Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.", + "x-example": null + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "x-example": false + } + }, + "required": [ + "code", + "activate" + ] + } + } + } + } + } + }, + "\/sites\/{siteId}\/deployments\/duplicate": { + "post": { + "summary": "Create duplicate deployment", + "operationId": "sitesCreateDuplicateDeployment", + "tags": [ + "sites" + ], + "description": "Create a new build for an existing site deployment. This endpoint allows you to rebuild a deployment with the updated site configuration, including its commands and output directory if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createDuplicateDeployment", + "group": "deployments", + "weight": 419, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create-duplicate-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new build for an existing site deployment. This endpoint allows you to rebuild a deployment with the updated site configuration, including its commands and output directory if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "deploymentId": { + "type": "string", + "description": "Deployment ID.", + "x-example": "<DEPLOYMENT_ID>" + } + }, + "required": [ + "deploymentId" + ] + } + } + } + } + } + }, + "\/sites\/{siteId}\/deployments\/template": { + "post": { + "summary": "Create template deployment", + "operationId": "sitesCreateTemplateDeployment", + "tags": [ + "sites" + ], + "description": "Create a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/sites#listTemplates) to find the template details.", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createTemplateDeployment", + "group": "deployments", + "weight": 412, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create-template-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/sites#listTemplates) to find the template details.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "repository": { + "type": "string", + "description": "Repository name of the template.", + "x-example": "<REPOSITORY>" + }, + "owner": { + "type": "string", + "description": "The name of the owner of the template.", + "x-example": "<OWNER>" + }, + "rootDirectory": { + "type": "string", + "description": "Path to site code in the template repo.", + "x-example": "<ROOT_DIRECTORY>" + }, + "version": { + "type": "string", + "description": "Version (tag) for the repo linked to the site template.", + "x-example": "<VERSION>" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "x-example": false + } + }, + "required": [ + "repository", + "owner", + "rootDirectory", + "version" + ] + } + } + } + } + } + }, + "\/sites\/{siteId}\/deployments\/vcs": { + "post": { + "summary": "Create VCS deployment", + "operationId": "sitesCreateVcsDeployment", + "tags": [ + "sites" + ], + "description": "Create a deployment when a site is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createVcsDeployment", + "group": "deployments", + "weight": 413, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create-vcs-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment when a site is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Type of reference passed. Allowed values are: branch, commit", + "x-example": "branch", + "enum": [ + "branch", + "commit", + "tag" + ], + "x-enum-name": "VCSDeploymentType", + "x-enum-keys": [] + }, + "reference": { + "type": "string", + "description": "VCS reference to create deployment from. Depending on type this can be: branch name, commit hash", + "x-example": "<REFERENCE>" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "x-example": false + } + }, + "required": [ + "type", + "reference" + ] + } + } + } + } + } + }, + "\/sites\/{siteId}\/deployments\/{deploymentId}": { + "get": { + "summary": "Get deployment", + "operationId": "sitesGetDeployment", + "tags": [ + "sites" + ], + "description": "Get a site deployment by its unique ID.", + "responses": { + "200": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "getDeployment", + "group": "deployments", + "weight": 414, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a site deployment by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DEPLOYMENT_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete deployment", + "operationId": "sitesDeleteDeployment", + "tags": [ + "sites" + ], + "description": "Delete a site deployment by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDeployment", + "group": "deployments", + "weight": 417, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/delete-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a site deployment by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DEPLOYMENT_ID>" + }, + "in": "path" + } + ] + } + }, + "\/sites\/{siteId}\/deployments\/{deploymentId}\/download": { + "get": { + "summary": "Get deployment download", + "operationId": "sitesGetDeploymentDownload", + "tags": [ + "sites" + ], + "description": "Get a site deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "responses": { + "200": { + "description": "File" + } + }, + "x-appwrite": { + "method": "getDeploymentDownload", + "group": "deployments", + "weight": 418, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "sites\/get-deployment-download.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a site deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DEPLOYMENT_ID>" + }, + "in": "path" + }, + { + "name": "type", + "description": "Deployment file to download. Can be: \"source\", \"output\".", + "required": false, + "schema": { + "type": "string", + "x-example": "source", + "enum": [ + "source", + "output" + ], + "x-enum-name": "DeploymentDownloadType", + "x-enum-keys": [], + "default": "source" + }, + "in": "query" + } + ] + } + }, + "\/sites\/{siteId}\/deployments\/{deploymentId}\/status": { + "patch": { + "summary": "Update deployment status", + "operationId": "sitesUpdateDeploymentStatus", + "tags": [ + "sites" + ], + "description": "Cancel an ongoing site deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", + "responses": { + "200": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "updateDeploymentStatus", + "group": "deployments", + "weight": 420, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/update-deployment-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCancel an ongoing site deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DEPLOYMENT_ID>" + }, + "in": "path" + } + ] + } + }, + "\/sites\/{siteId}\/logs": { + "get": { + "summary": "List logs", + "operationId": "sitesListLogs", + "tags": [ + "sites" + ], + "description": "Get a list of all site logs. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Executions List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/executionList" + } + } + } + } + }, + "x-appwrite": { + "method": "listLogs", + "group": "logs", + "weight": 422, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all site logs. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "log.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: trigger, status, responseStatusCode, duration, requestMethod, requestPath, deploymentId", + "required": false, + "schema": { + "type": "string", + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/sites\/{siteId}\/logs\/{logId}": { + "get": { + "summary": "Get log", + "operationId": "sitesGetLog", + "tags": [ + "sites" + ], + "description": "Get a site request log by its unique ID.", + "responses": { + "200": { + "description": "Execution", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/execution" + } + } + } + } + }, + "x-appwrite": { + "method": "getLog", + "group": "logs", + "weight": 421, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get-log.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a site request log by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "log.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "logId", + "description": "Log ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<LOG_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete log", + "operationId": "sitesDeleteLog", + "tags": [ + "sites" + ], + "description": "Delete a site log by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteLog", + "group": "logs", + "weight": 423, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/delete-log.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a site log by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "log.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "logId", + "description": "Log ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<LOG_ID>" + }, + "in": "path" + } + ] + } + }, + "\/sites\/{siteId}\/usage": { + "get": { + "summary": "Get site usage", + "operationId": "sitesGetUsage", + "tags": [ + "sites" + ], + "description": "Get usage metrics and statistics for a for a specific site. View statistics including total deployments, builds, executions, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", + "responses": { + "200": { + "description": "UsageSite", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/usageSite" + } + } + } + } + }, + "x-appwrite": { + "method": "getUsage", + "group": null, + "weight": 432, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet usage metrics and statistics for a for a specific site. View statistics including total deployments, builds, executions, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "range", + "description": "Date range.", + "required": false, + "schema": { + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "SiteUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d" + }, + "in": "query" + } + ] + } + }, + "\/sites\/{siteId}\/variables": { + "get": { + "summary": "List variables", + "operationId": "sitesListVariables", + "tags": [ + "sites" + ], + "description": "Get a list of all variables of a specific site.", + "responses": { + "200": { + "description": "Variables List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variableList" + } + } + } + } + }, + "x-appwrite": { + "method": "listVariables", + "group": "variables", + "weight": 426, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-variables.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all variables of a specific site.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ] + }, + "post": { + "summary": "Create variable", + "operationId": "sitesCreateVariable", + "tags": [ + "sites" + ], + "description": "Create a new site variable. These variables can be accessed during build and runtime (server-side rendering) as environment variables.", + "responses": { + "201": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "createVariable", + "group": "variables", + "weight": 424, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new site variable. These variables can be accessed during build and runtime (server-side rendering) as environment variables.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "x-example": "<KEY>" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "x-example": "<VALUE>" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only sites can read them during build and runtime.", + "x-example": false + } + }, + "required": [ + "key", + "value" + ] + } + } + } + } + } + }, + "\/sites\/{siteId}\/variables\/{variableId}": { + "get": { + "summary": "Get variable", + "operationId": "sitesGetVariable", + "tags": [ + "sites" + ], + "description": "Get a variable by its unique ID.", + "responses": { + "200": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "getVariable", + "group": "variables", + "weight": 425, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<VARIABLE_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update variable", + "operationId": "sitesUpdateVariable", + "tags": [ + "sites" + ], + "description": "Update variable by its unique ID.", + "responses": { + "200": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "updateVariable", + "group": "variables", + "weight": 427, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/update-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<VARIABLE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "x-example": "<KEY>" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "x-example": "<VALUE>" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only sites can read them during build and runtime.", + "x-example": false + } + }, + "required": [ + "key" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete variable", + "operationId": "sitesDeleteVariable", + "tags": [ + "sites" + ], + "description": "Delete a variable by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteVariable", + "group": "variables", + "weight": 428, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/delete-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<VARIABLE_ID>" + }, + "in": "path" + } + ] + } + }, + "\/storage\/buckets": { + "get": { + "summary": "List buckets", + "operationId": "storageListBuckets", + "tags": [ + "storage" + ], + "description": "Get a list of all the storage buckets. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Buckets List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/bucketList" + } + } + } + } + }, + "x-appwrite": { + "method": "listBuckets", + "group": "buckets", + "weight": 209, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/list-buckets.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/list-buckets.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create bucket", + "operationId": "storageCreateBucket", + "tags": [ + "storage" + ], + "description": "Create a new storage bucket.", + "responses": { + "201": { + "description": "Bucket", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/bucket" + } + } + } + } + }, + "x-appwrite": { + "method": "createBucket", + "group": "buckets", + "weight": 208, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/create-bucket.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/create-bucket.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "bucketId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<BUCKET_ID>" + }, + "name": { + "type": "string", + "description": "Bucket name", + "x-example": "<NAME>" + }, + "permissions": { + "type": "array", + "description": "An array of permission strings. By default, no user is granted with any permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "fileSecurity": { + "type": "boolean", + "description": "Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Is bucket enabled? When set to 'disabled', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.", + "x-example": false + }, + "maximumFileSize": { + "type": "integer", + "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", + "x-example": 1 + }, + "allowedFileExtensions": { + "type": "array", + "description": "Allowed file extensions. Maximum of 100 extensions are allowed, each 64 characters long.", + "x-example": null, + "items": { + "type": "string" + } + }, + "compression": { + "type": "string", + "description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", + "x-example": "none", + "enum": [ + "none", + "gzip", + "zstd" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "encryption": { + "type": "boolean", + "description": "Is encryption enabled? For file size above 20MB encryption is skipped even if it's enabled", + "x-example": false + }, + "antivirus": { + "type": "boolean", + "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", + "x-example": false + } + }, + "required": [ + "bucketId", + "name" + ] + } + } + } + } + } + }, + "\/storage\/buckets\/{bucketId}": { + "get": { + "summary": "Get bucket", + "operationId": "storageGetBucket", + "tags": [ + "storage" + ], + "description": "Get a storage bucket by its unique ID. This endpoint response returns a JSON object with the storage bucket metadata.", + "responses": { + "200": { + "description": "Bucket", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/bucket" + } + } + } + } + }, + "x-appwrite": { + "method": "getBucket", + "group": "buckets", + "weight": 210, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/get-bucket.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-bucket.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Bucket unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update bucket", + "operationId": "storageUpdateBucket", + "tags": [ + "storage" + ], + "description": "Update a storage bucket by its unique ID.", + "responses": { + "200": { + "description": "Bucket", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/bucket" + } + } + } + } + }, + "x-appwrite": { + "method": "updateBucket", + "group": "buckets", + "weight": 211, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/update-bucket.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/update-bucket.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Bucket unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Bucket name", + "x-example": "<NAME>" + }, + "permissions": { + "type": "array", + "description": "An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "fileSecurity": { + "type": "boolean", + "description": "Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Is bucket enabled? When set to 'disabled', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.", + "x-example": false + }, + "maximumFileSize": { + "type": "integer", + "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", + "x-example": 1 + }, + "allowedFileExtensions": { + "type": "array", + "description": "Allowed file extensions. Maximum of 100 extensions are allowed, each 64 characters long.", + "x-example": null, + "items": { + "type": "string" + } + }, + "compression": { + "type": "string", + "description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", + "x-example": "none", + "enum": [ + "none", + "gzip", + "zstd" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "encryption": { + "type": "boolean", + "description": "Is encryption enabled? For file size above 20MB encryption is skipped even if it's enabled", + "x-example": false + }, + "antivirus": { + "type": "boolean", + "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", + "x-example": false + } + }, + "required": [ + "name" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete bucket", + "operationId": "storageDeleteBucket", + "tags": [ + "storage" + ], + "description": "Delete a storage bucket by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteBucket", + "group": "buckets", + "weight": 212, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/delete-bucket.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/delete-bucket.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Bucket unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files": { + "get": { + "summary": "List files", + "operationId": "storageListFiles", + "tags": [ + "storage" + ], + "description": "Get a list of all the user files. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Files List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/fileList" + } + } + } + } + }, + "x-appwrite": { + "method": "listFiles", + "group": "files", + "weight": 214, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/list-files.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/list-files.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, signature, mimeType, sizeOriginal, chunksTotal, chunksUploaded", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create file", + "operationId": "storageCreateFile", + "tags": [ + "storage" + ], + "description": "Create a new file. Before using this route, you should create a new bucket resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/storage#storageCreateBucket) API or directly from your Appwrite console.\n\nLarger files should be uploaded using multiple requests with the [content-range](https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Headers\/Content-Range) header to send a partial request with a maximum supported chunk of `5MB`. The `content-range` header values should always be in bytes.\n\nWhen the first request is sent, the server will return the **File** object, and the subsequent part request must include the file's **id** in `x-appwrite-id` header to allow the server to know that the partial upload is for the existing file and not for a new one.\n\nIf you're creating a new file using one of the Appwrite SDKs, all the chunking logic will be managed by the SDK internally.\n", + "responses": { + "201": { + "description": "File", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/file" + } + } + } + } + }, + "x-appwrite": { + "method": "createFile", + "group": "files", + "weight": 213, + "cookies": false, + "type": "upload", + "deprecated": false, + "demo": "storage\/create-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/create-file.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId},chunkId:{chunkId}", + "scope": "files.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "multipart\/form-data": { + "schema": { + "type": "object", + "properties": { + "fileId": { + "type": "string", + "description": "File ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<FILE_ID>", + "x-upload-id": true + }, + "file": { + "type": "string", + "description": "Binary file. Appwrite SDKs provide helpers to handle file input. [Learn about file input](https:\/\/appwrite.io\/docs\/products\/storage\/upload-download#input-file).", + "x-example": null + }, + "permissions": { + "type": "array", + "description": "An array of permission strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "fileId", + "file" + ] + } + } + } + } + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}": { + "get": { + "summary": "Get file", + "operationId": "storageGetFile", + "tags": [ + "storage" + ], + "description": "Get a file by its unique ID. This endpoint response returns a JSON object with the file metadata.", + "responses": { + "200": { + "description": "File", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/file" + } + } + } + } + }, + "x-appwrite": { + "method": "getFile", + "group": "files", + "weight": 215, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/get-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FILE_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update file", + "operationId": "storageUpdateFile", + "tags": [ + "storage" + ], + "description": "Update a file by its unique ID. Only users with write permissions have access to update this resource.", + "responses": { + "200": { + "description": "File", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/file" + } + } + } + } + }, + "x-appwrite": { + "method": "updateFile", + "group": "files", + "weight": 220, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/update-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/update-file.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "files.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FILE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the file", + "x-example": "<NAME>" + }, + "permissions": { + "type": "array", + "description": "An array of permission string. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete file", + "operationId": "storageDeleteFile", + "tags": [ + "storage" + ], + "description": "Delete a file by its unique ID. Only users with write permissions have access to delete this resource.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteFile", + "group": "files", + "weight": 221, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/delete-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/delete-file.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "files.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FILE_ID>" + }, + "in": "path" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/download": { + "get": { + "summary": "Get file for download", + "operationId": "storageGetFileDownload", + "tags": [ + "storage" + ], + "description": "Get a file content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "responses": { + "200": { + "description": "File" + } + }, + "x-appwrite": { + "method": "getFileDownload", + "group": "files", + "weight": 217, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "storage\/get-file-download.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file-download.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FILE_ID>" + }, + "in": "path" + }, + { + "name": "token", + "description": "File token for accessing this file.", + "required": false, + "schema": { + "type": "string", + "x-example": "<TOKEN>", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/preview": { + "get": { + "summary": "Get file preview", + "operationId": "storageGetFilePreview", + "tags": [ + "storage" + ], + "description": "Get a file preview image. Currently, this method supports preview for image files (jpg, png, and gif), other supported formats, like pdf, docs, slides, and spreadsheets, will return the file icon image. You can also pass query string arguments for cutting and resizing your preview image. Preview is supported only for image files smaller than 10MB.", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getFilePreview", + "group": "files", + "weight": 216, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "storage\/get-file-preview.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file-preview.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File ID", + "required": true, + "schema": { + "type": "string", + "x-example": "<FILE_ID>" + }, + "in": "path" + }, + { + "name": "width", + "description": "Resize preview image width, Pass an integer between 0 to 4000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0 + }, + "in": "query" + }, + { + "name": "height", + "description": "Resize preview image height, Pass an integer between 0 to 4000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0 + }, + "in": "query" + }, + { + "name": "gravity", + "description": "Image crop gravity. Can be one of center,top-left,top,top-right,left,right,bottom-left,bottom,bottom-right", + "required": false, + "schema": { + "type": "string", + "x-example": "center", + "enum": [ + "center", + "top-left", + "top", + "top-right", + "left", + "right", + "bottom-left", + "bottom", + "bottom-right" + ], + "x-enum-name": "ImageGravity", + "x-enum-keys": [], + "default": "center" + }, + "in": "query" + }, + { + "name": "quality", + "description": "Preview image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1 + }, + "in": "query" + }, + { + "name": "borderWidth", + "description": "Preview image border in pixels. Pass an integer between 0 to 100. Defaults to 0.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0 + }, + "in": "query" + }, + { + "name": "borderColor", + "description": "Preview image border color. Use a valid HEX color, no # is needed for prefix.", + "required": false, + "schema": { + "type": "string", + "default": "" + }, + "in": "query" + }, + { + "name": "borderRadius", + "description": "Preview image border radius in pixels. Pass an integer between 0 to 4000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0 + }, + "in": "query" + }, + { + "name": "opacity", + "description": "Preview image opacity. Only works with images having an alpha channel (like png). Pass a number between 0 to 1.", + "required": false, + "schema": { + "type": "number", + "format": "float", + "x-example": 0, + "default": 1 + }, + "in": "query" + }, + { + "name": "rotation", + "description": "Preview image rotation in degrees. Pass an integer between -360 and 360.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": -360, + "default": 0 + }, + "in": "query" + }, + { + "name": "background", + "description": "Preview image background color. Only works with transparent images (png). Use a valid HEX color, no # is needed for prefix.", + "required": false, + "schema": { + "type": "string", + "default": "" + }, + "in": "query" + }, + { + "name": "output", + "description": "Output format type (jpeg, jpg, png, gif and webp).", + "required": false, + "schema": { + "type": "string", + "x-example": "jpg", + "enum": [ + "jpg", + "jpeg", + "png", + "webp", + "heic", + "avif", + "gif" + ], + "x-enum-name": "ImageFormat", + "x-enum-keys": [], + "default": "" + }, + "in": "query" + }, + { + "name": "token", + "description": "File token for accessing this file.", + "required": false, + "schema": { + "type": "string", + "x-example": "<TOKEN>", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/view": { + "get": { + "summary": "Get file for view", + "operationId": "storageGetFileView", + "tags": [ + "storage" + ], + "description": "Get a file content by its unique ID. This endpoint is similar to the download method but returns with no 'Content-Disposition: attachment' header.", + "responses": { + "200": { + "description": "File" + } + }, + "x-appwrite": { + "method": "getFileView", + "group": "files", + "weight": 218, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "storage\/get-file-view.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file-view.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FILE_ID>" + }, + "in": "path" + }, + { + "name": "token", + "description": "File token for accessing this file.", + "required": false, + "schema": { + "type": "string", + "x-example": "<TOKEN>", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/storage\/usage": { + "get": { + "summary": "Get storage usage stats", + "operationId": "storageGetUsage", + "tags": [ + "storage" + ], + "description": "Get usage metrics and statistics for all buckets in the project. You can view the total number of buckets, files, storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.\n", + "responses": { + "200": { + "description": "StorageUsage", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/usageStorage" + } + } + } + } + }, + "x-appwrite": { + "method": "getUsage", + "group": null, + "weight": 222, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/get-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-usage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "range", + "description": "Date range.", + "required": false, + "schema": { + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "StorageUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d" + }, + "in": "query" + } + ] + } + }, + "\/storage\/{bucketId}\/usage": { + "get": { + "summary": "Get bucket usage stats", + "operationId": "storageGetBucketUsage", + "tags": [ + "storage" + ], + "description": "Get usage metrics and statistics a specific bucket in the project. You can view the total number of files, storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.\n", + "responses": { + "200": { + "description": "UsageBuckets", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/usageBuckets" + } + } + } + } + }, + "x-appwrite": { + "method": "getBucketUsage", + "group": null, + "weight": 223, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/get-bucket-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-bucket-usage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Bucket ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + }, + { + "name": "range", + "description": "Date range.", + "required": false, + "schema": { + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "StorageUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d" + }, + "in": "query" + } + ] + } + }, + "\/teams": { + "get": { + "summary": "List teams", + "operationId": "teamsList", + "tags": [ + "teams" + ], + "description": "Get a list of all the teams in which the current user is a member. You can use the parameters to filter your results.", + "responses": { + "200": { + "description": "Teams List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/teamList" + } + } + } + } + }, + "x-appwrite": { + "method": "list", + "group": "teams", + "weight": 225, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/list-teams.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, total, billingPlan", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create team", + "operationId": "teamsCreate", + "tags": [ + "teams" + ], + "description": "Create a new team. The user who creates the team will automatically be assigned as the owner of the team. Only the users with the owner role can invite new members, add new owners and delete or update the team.", + "responses": { + "201": { + "description": "Team", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/team" + } + } + } + } + }, + "x-appwrite": { + "method": "create", + "group": "teams", + "weight": 224, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/create-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "teamId": { + "type": "string", + "description": "Team ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<TEAM_ID>" + }, + "name": { + "type": "string", + "description": "Team name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "roles": { + "type": "array", + "description": "Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.", + "x-example": null, + "items": { + "type": "string" + } + } + }, + "required": [ + "teamId", + "name" + ] + } + } + } + } + } + }, + "\/teams\/{teamId}": { + "get": { + "summary": "Get team", + "operationId": "teamsGet", + "tags": [ + "teams" + ], + "description": "Get a team by its ID. All team members have read access for this resource.", + "responses": { + "200": { + "description": "Team", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/team" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": "teams", + "weight": 226, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update name", + "operationId": "teamsUpdateName", + "tags": [ + "teams" + ], + "description": "Update the team's name by its unique ID.", + "responses": { + "200": { + "description": "Team", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/team" + } + } + } + } + }, + "x-appwrite": { + "method": "updateName", + "group": "teams", + "weight": 228, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-name.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-name.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "New team name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "name" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete team", + "operationId": "teamsDelete", + "tags": [ + "teams" + ], + "description": "Delete a team using its ID. Only team members with the owner role can delete the team.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "teams", + "weight": 230, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/delete-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + } + ] + } + }, + "\/teams\/{teamId}\/logs": { + "get": { + "summary": "List team logs", + "operationId": "teamsListLogs", + "tags": [ + "teams" + ], + "description": "Get the team activity logs list by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/logList" + } + } + } + } + }, + "x-appwrite": { + "method": "listLogs", + "group": "logs", + "weight": 237, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/list-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/teams\/{teamId}\/memberships": { + "get": { + "summary": "List team memberships", + "operationId": "teamsListMemberships", + "tags": [ + "teams" + ], + "description": "Use this endpoint to list a team's members using the team's ID. All team members have read access to this endpoint. Hide sensitive attributes from the response by toggling membership privacy in the Console.", + "responses": { + "200": { + "description": "Memberships List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/membershipList" + } + } + } + } + }, + "x-appwrite": { + "method": "listMemberships", + "group": "memberships", + "weight": 232, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/list-memberships.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/list-team-members.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create team membership", + "operationId": "teamsCreateMembership", + "tags": [ + "teams" + ], + "description": "Invite a new member to join your team. Provide an ID for existing users, or invite unregistered users using an email or phone number. If initiated from a Client SDK, Appwrite will send an email or sms with a link to join the team to the invited user, and an account will be created for them if one doesn't exist. If initiated from a Server SDK, the new member will be added automatically to the team.\n\nYou only need to provide one of a user ID, email, or phone number. Appwrite will prioritize accepting the user ID > email > phone number if you provide more than one of these parameters.\n\nUse the `url` parameter to redirect the user from the invitation email to your app. After the user is redirected, use the [Update Team Membership Status](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/teams#updateMembershipStatus) endpoint to allow the user to accept the invitation to the team. \n\nPlease note that to avoid a [Redirect Attack](https:\/\/github.com\/OWASP\/CheatSheetSeries\/blob\/master\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) Appwrite will accept the only redirect URLs under the domains you have added as a platform on the Appwrite Console.\n", + "responses": { + "201": { + "description": "Membership", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/membership" + } + } + } + } + }, + "x-appwrite": { + "method": "createMembership", + "group": "memberships", + "weight": 231, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/create-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/create-team-membership.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "Email of the new team member.", + "x-example": "email@example.com" + }, + "userId": { + "type": "string", + "description": "ID of the user to be added to a team.", + "x-example": "<USER_ID>" + }, + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "x-example": "+12065550100" + }, + "roles": { + "type": "array", + "description": "Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.", + "x-example": null, + "items": { + "type": "string" + } + }, + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "x-example": "https:\/\/example.com" + }, + "name": { + "type": "string", + "description": "Name of the new team member. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "roles" + ] + } + } + } + } + } + }, + "\/teams\/{teamId}\/memberships\/{membershipId}": { + "get": { + "summary": "Get team membership", + "operationId": "teamsGetMembership", + "tags": [ + "teams" + ], + "description": "Get a team member by the membership unique id. All team members have read access for this resource. Hide sensitive attributes from the response by toggling membership privacy in the Console.", + "responses": { + "200": { + "description": "Membership", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/membership" + } + } + } + } + }, + "x-appwrite": { + "method": "getMembership", + "group": "memberships", + "weight": 233, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/get-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team-member.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MEMBERSHIP_ID>" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update membership", + "operationId": "teamsUpdateMembership", + "tags": [ + "teams" + ], + "description": "Modify the roles of a team member. Only team members with the owner role have access to this endpoint. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions).\n", + "responses": { + "200": { + "description": "Membership", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/membership" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMembership", + "group": "memberships", + "weight": 234, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-membership.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MEMBERSHIP_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "roles": { + "type": "array", + "description": "An array of strings. Use this param to set the user's roles in the team. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.", + "x-example": null, + "items": { + "type": "string" + } + } + }, + "required": [ + "roles" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete team membership", + "operationId": "teamsDeleteMembership", + "tags": [ + "teams" + ], + "description": "This endpoint allows a user to leave a team or for a team owner to delete the membership of any other team member. You can also use this endpoint to delete a user membership even if it is not accepted.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteMembership", + "group": "memberships", + "weight": 236, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/delete-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/delete-team-membership.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MEMBERSHIP_ID>" + }, + "in": "path" + } + ] + } + }, + "\/teams\/{teamId}\/memberships\/{membershipId}\/status": { + "patch": { + "summary": "Update team membership status", + "operationId": "teamsUpdateMembershipStatus", + "tags": [ + "teams" + ], + "description": "Use this endpoint to allow a user to accept an invitation to join a team after being redirected back to your app from the invitation email received by the user.\n\nIf the request is successful, a session for the user is automatically created.\n", + "responses": { + "200": { + "description": "Membership", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/membership" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMembershipStatus", + "group": "memberships", + "weight": 235, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-membership-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-membership-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MEMBERSHIP_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Secret key.", + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + } + } + } + }, + "\/teams\/{teamId}\/prefs": { + "get": { + "summary": "Get team preferences", + "operationId": "teamsGetPrefs", + "tags": [ + "teams" + ], + "description": "Get the team's shared preferences by its unique ID. If a preference doesn't need to be shared by all team members, prefer storing them in [user preferences](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#getPrefs).", + "responses": { + "200": { + "description": "Preferences", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/preferences" + } + } + } + } + }, + "x-appwrite": { + "method": "getPrefs", + "group": "teams", + "weight": 227, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/get-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update preferences", + "operationId": "teamsUpdatePrefs", + "tags": [ + "teams" + ], + "description": "Update the team's preferences by its unique ID. The object you pass is stored as is and replaces any previous value. The maximum allowed prefs size is 64kB and throws an error if exceeded.", + "responses": { + "200": { + "description": "Preferences", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/preferences" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePrefs", + "group": "teams", + "weight": 229, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "prefs": { + "type": "object", + "description": "Prefs key-value JSON object.", + "x-example": "{}" + } + }, + "required": [ + "prefs" + ] + } + } + } + } + } + }, + "\/tokens\/buckets\/{bucketId}\/files\/{fileId}": { + "get": { + "summary": "List tokens", + "operationId": "tokensList", + "tags": [ + "tokens" + ], + "description": "List all the tokens created for a specific file or bucket. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Resource Tokens List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/resourceTokenList" + } + } + } + } + }, + "x-appwrite": { + "method": "list", + "group": "files", + "weight": 441, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList all the tokens created for a specific file or bucket. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "tokens.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FILE_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: expire", + "required": false, + "schema": { + "type": "string", + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create file token", + "operationId": "tokensCreateFileToken", + "tags": [ + "tokens" + ], + "description": "Create a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", + "responses": { + "201": { + "description": "ResourceToken", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/resourceToken" + } + } + } + } + }, + "x-appwrite": { + "method": "createFileToken", + "group": "files", + "weight": 439, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/create-file-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "tokens.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FILE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "expire": { + "type": "string", + "description": "Token expiry date", + "x-example": null, + "x-nullable": true + } + } + } + } + } + } + } + }, + "\/tokens\/{tokenId}": { + "get": { + "summary": "Get token", + "operationId": "tokensGet", + "tags": [ + "tokens" + ], + "description": "Get a token by its unique ID.", + "responses": { + "200": { + "description": "ResourceToken", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/resourceToken" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": "tokens", + "weight": 440, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a token by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "tokens.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOKEN_ID>" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update token", + "operationId": "tokensUpdate", + "tags": [ + "tokens" + ], + "description": "Update a token by its unique ID. Use this endpoint to update a token's expiry date.", + "responses": { + "200": { + "description": "ResourceToken", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/resourceToken" + } + } + } + } + }, + "x-appwrite": { + "method": "update", + "group": "tokens", + "weight": 442, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/update.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate a token by its unique ID. Use this endpoint to update a token's expiry date.", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "tokens.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOKEN_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "expire": { + "type": "string", + "description": "File token expiry date", + "x-example": null, + "x-nullable": true + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete token", + "operationId": "tokensDelete", + "tags": [ + "tokens" + ], + "description": "Delete a token by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "tokens", + "weight": 443, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a token by its unique ID.", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "tokens.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOKEN_ID>" + }, + "in": "path" + } + ] + } + }, + "\/users": { + "get": { + "summary": "List users", + "operationId": "usersList", + "tags": [ + "users" + ], + "description": "Get a list of all the project's users. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Users List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/userList" + } + } + } + } + }, + "x-appwrite": { + "method": "list", + "group": "users", + "weight": 247, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-users.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, email, phone, status, passwordUpdate, registration, emailVerification, phoneVerification, labels", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create user", + "operationId": "usersCreate", + "tags": [ + "users" + ], + "description": "Create a new user.", + "responses": { + "201": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "create", + "group": "users", + "weight": 238, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "x-example": "+12065550100" + }, + "password": { + "type": "string", + "description": "Plain text user password. Must be at least 8 chars.", + "x-example": null + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "userId" + ] + } + } + } + } + } + }, + "\/users\/argon2": { + "post": { + "summary": "Create user with Argon2 password", + "operationId": "usersCreateArgon2User", + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [Argon2](https:\/\/en.wikipedia.org\/wiki\/Argon2) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "createArgon2User", + "group": "users", + "weight": 241, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-argon2user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-argon2-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using Argon2.", + "x-example": "password" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + } + } + } + }, + "\/users\/bcrypt": { + "post": { + "summary": "Create user with bcrypt password", + "operationId": "usersCreateBcryptUser", + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [Bcrypt](https:\/\/en.wikipedia.org\/wiki\/Bcrypt) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "createBcryptUser", + "group": "users", + "weight": 239, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-bcrypt-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-bcrypt-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using Bcrypt.", + "x-example": "password" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + } + } + } + }, + "\/users\/identities": { + "get": { + "summary": "List identities", + "operationId": "usersListIdentities", + "tags": [ + "users" + ], + "description": "Get identities for all users.", + "responses": { + "200": { + "description": "Identities List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/identityList" + } + } + } + } + }, + "x-appwrite": { + "method": "listIdentities", + "group": "identities", + "weight": 255, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-identities.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-identities.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, provider, providerUid, providerEmail, providerAccessTokenExpiry", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/users\/identities\/{identityId}": { + "delete": { + "summary": "Delete identity", + "operationId": "usersDeleteIdentity", + "tags": [ + "users" + ], + "description": "Delete an identity by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteIdentity", + "group": "identities", + "weight": 278, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-identity.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-identity.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "identityId", + "description": "Identity ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<IDENTITY_ID>" + }, + "in": "path" + } + ] + } + }, + "\/users\/md5": { + "post": { + "summary": "Create user with MD5 password", + "operationId": "usersCreateMD5User", + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [MD5](https:\/\/en.wikipedia.org\/wiki\/MD5) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "createMD5User", + "group": "users", + "weight": 240, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-m-d5user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-md5-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using MD5.", + "x-example": "password" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + } + } + } + }, + "\/users\/phpass": { + "post": { + "summary": "Create user with PHPass password", + "operationId": "usersCreatePHPassUser", + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [PHPass](https:\/\/www.openwall.com\/phpass\/) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "createPHPassUser", + "group": "users", + "weight": 243, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-p-h-pass-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-phpass-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or pass the string `ID.unique()`to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using PHPass.", + "x-example": "password" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + } + } + } + }, + "\/users\/scrypt": { + "post": { + "summary": "Create user with Scrypt password", + "operationId": "usersCreateScryptUser", + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [Scrypt](https:\/\/github.com\/Tarsnap\/scrypt) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "createScryptUser", + "group": "users", + "weight": 244, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-scrypt-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-scrypt-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using Scrypt.", + "x-example": "password" + }, + "passwordSalt": { + "type": "string", + "description": "Optional salt used to hash password.", + "x-example": "<PASSWORD_SALT>" + }, + "passwordCpu": { + "type": "integer", + "description": "Optional CPU cost used to hash password.", + "x-example": null + }, + "passwordMemory": { + "type": "integer", + "description": "Optional memory cost used to hash password.", + "x-example": null + }, + "passwordParallel": { + "type": "integer", + "description": "Optional parallelization cost used to hash password.", + "x-example": null + }, + "passwordLength": { + "type": "integer", + "description": "Optional hash length used to hash password.", + "x-example": null + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password", + "passwordSalt", + "passwordCpu", + "passwordMemory", + "passwordParallel", + "passwordLength" + ] + } + } + } + } + } + }, + "\/users\/scrypt-modified": { + "post": { + "summary": "Create user with Scrypt modified password", + "operationId": "usersCreateScryptModifiedUser", + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [Scrypt Modified](https:\/\/gist.github.com\/Meldiron\/eecf84a0225eccb5a378d45bb27462cc) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "createScryptModifiedUser", + "group": "users", + "weight": 245, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-scrypt-modified-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-scrypt-modified-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using Scrypt Modified.", + "x-example": "password" + }, + "passwordSalt": { + "type": "string", + "description": "Salt used to hash password.", + "x-example": "<PASSWORD_SALT>" + }, + "passwordSaltSeparator": { + "type": "string", + "description": "Salt separator used to hash password.", + "x-example": "<PASSWORD_SALT_SEPARATOR>" + }, + "passwordSignerKey": { + "type": "string", + "description": "Signer key used to hash password.", + "x-example": "<PASSWORD_SIGNER_KEY>" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password", + "passwordSalt", + "passwordSaltSeparator", + "passwordSignerKey" + ] + } + } + } + } + } + }, + "\/users\/sha": { + "post": { + "summary": "Create user with SHA password", + "operationId": "usersCreateSHAUser", + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [SHA](https:\/\/en.wikipedia.org\/wiki\/Secure_Hash_Algorithm) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "createSHAUser", + "group": "users", + "weight": 242, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-s-h-a-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-sha-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using SHA.", + "x-example": "password" + }, + "passwordVersion": { + "type": "string", + "description": "Optional SHA version used to hash password. Allowed values are: 'sha1', 'sha224', 'sha256', 'sha384', 'sha512\/224', 'sha512\/256', 'sha512', 'sha3-224', 'sha3-256', 'sha3-384', 'sha3-512'", + "x-example": "sha1", + "enum": [ + "sha1", + "sha224", + "sha256", + "sha384", + "sha512\/224", + "sha512\/256", + "sha512", + "sha3-224", + "sha3-256", + "sha3-384", + "sha3-512" + ], + "x-enum-name": "PasswordHash", + "x-enum-keys": [] + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + } + } + } + }, + "\/users\/usage": { + "get": { + "summary": "Get users usage stats", + "operationId": "usersGetUsage", + "tags": [ + "users" + ], + "description": "Get usage metrics and statistics for all users in the project. You can view the total number of users and sessions. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.\n", + "responses": { + "200": { + "description": "UsageUsers", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/usageUsers" + } + } + } + } + }, + "x-appwrite": { + "method": "getUsage", + "group": null, + "weight": 280, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/get-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-usage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "range", + "description": "Date range.", + "required": false, + "schema": { + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "UserUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d" + }, + "in": "query" + } + ] + } + }, + "\/users\/{userId}": { + "get": { + "summary": "Get user", + "operationId": "usersGet", + "tags": [ + "users" + ], + "description": "Get a user by its unique ID.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": "users", + "weight": 248, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete user", + "operationId": "usersDelete", + "tags": [ + "users" + ], + "description": "Delete a user by its unique ID, thereby releasing it's ID. Since ID is released and can be reused, all user-related resources like documents or storage files should be deleted before user deletion. If you want to keep ID reserved, use the [updateStatus](https:\/\/appwrite.io\/docs\/server\/users#usersUpdateStatus) endpoint instead.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "users", + "weight": 276, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/email": { + "patch": { + "summary": "Update email", + "operationId": "usersUpdateEmail", + "tags": [ + "users" + ], + "description": "Update the user email by its unique ID.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateEmail", + "group": "users", + "weight": 261, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-email.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + } + }, + "required": [ + "email" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/jwts": { + "post": { + "summary": "Create user JWT", + "operationId": "usersCreateJWT", + "tags": [ + "users" + ], + "description": "Use this endpoint to create a JSON Web Token for user by its unique ID. You can use the resulting JWT to authenticate on behalf of the user. The JWT secret will become invalid if the session it uses gets deleted.", + "responses": { + "201": { + "description": "JWT", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/jwt" + } + } + } + } + }, + "x-appwrite": { + "method": "createJWT", + "group": "sessions", + "weight": 279, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-j-w-t.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-user-jwt.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "description": "Session ID. Use the string 'recent' to use the most recent session. Defaults to the most recent session.", + "x-example": "<SESSION_ID>" + }, + "duration": { + "type": "integer", + "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", + "x-example": 0 + } + } + } + } + } + } + } + }, + "\/users\/{userId}\/labels": { + "put": { + "summary": "Update user labels", + "operationId": "usersUpdateLabels", + "tags": [ + "users" + ], + "description": "Update the user labels by its unique ID. \n\nLabels can be used to grant access to resources. While teams are a way for user's to share access to a resource, labels can be defined by the developer to grant access without an invitation. See the [Permissions docs](https:\/\/appwrite.io\/docs\/permissions) for more info.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateLabels", + "group": "users", + "weight": 257, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-labels.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-labels.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "labels": { + "type": "array", + "description": "Array of user labels. Replaces the previous labels. Maximum of 1000 labels are allowed, each up to 36 alphanumeric characters long.", + "x-example": null, + "items": { + "type": "string" + } + } + }, + "required": [ + "labels" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/logs": { + "get": { + "summary": "List user logs", + "operationId": "usersListLogs", + "tags": [ + "users" + ], + "description": "Get the user activity logs list by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/logList" + } + } + } + } + }, + "x-appwrite": { + "method": "listLogs", + "group": "logs", + "weight": 253, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-user-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/users\/{userId}\/memberships": { + "get": { + "summary": "List user memberships", + "operationId": "usersListMemberships", + "tags": [ + "users" + ], + "description": "Get the user membership list by its unique ID.", + "responses": { + "200": { + "description": "Memberships List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/membershipList" + } + } + } + } + }, + "x-appwrite": { + "method": "listMemberships", + "group": "memberships", + "weight": 252, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-memberships.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-user-memberships.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/users\/{userId}\/mfa": { + "patch": { + "summary": "Update MFA", + "operationId": "usersUpdateMfa", + "tags": [ + "users" + ], + "description": "Enable or disable MFA on a user account.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMfa", + "group": "users", + "weight": 266, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-mfa.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-mfa.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "mfa": { + "type": "boolean", + "description": "Enable or disable MFA.", + "x-example": false + } + }, + "required": [ + "mfa" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/mfa\/authenticators\/{type}": { + "delete": { + "summary": "Delete authenticator", + "operationId": "usersDeleteMfaAuthenticator", + "tags": [ + "users" + ], + "description": "Delete an authenticator app.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteMfaAuthenticator", + "group": "mfa", + "weight": 271, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + }, + { + "name": "type", + "description": "Type of authenticator.", + "required": true, + "schema": { + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [] + }, + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/mfa\/factors": { + "get": { + "summary": "List factors", + "operationId": "usersListMfaFactors", + "tags": [ + "users" + ], + "description": "List the factors available on the account to be used as a MFA challange.", + "responses": { + "200": { + "description": "MFAFactors", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaFactors" + } + } + } + } + }, + "x-appwrite": { + "method": "listMfaFactors", + "group": "mfa", + "weight": 267, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-mfa-factors.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-mfa-factors.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/mfa\/recovery-codes": { + "get": { + "summary": "Get MFA recovery codes", + "operationId": "usersGetMfaRecoveryCodes", + "tags": [ + "users" + ], + "description": "Get recovery codes that can be used as backup for MFA flow by User ID. Before getting codes, they must be generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaRecoveryCodes" + } + } + } + } + }, + "x-appwrite": { + "method": "getMfaRecoveryCodes", + "group": "mfa", + "weight": 268, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/get-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update MFA recovery codes (regenerate)", + "operationId": "usersUpdateMfaRecoveryCodes", + "tags": [ + "users" + ], + "description": "Regenerate recovery codes that can be used as backup for MFA flow by User ID. Before regenerating codes, they must be first generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaRecoveryCodes" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMfaRecoveryCodes", + "group": "mfa", + "weight": 270, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Create MFA recovery codes", + "operationId": "usersCreateMfaRecoveryCodes", + "tags": [ + "users" + ], + "description": "Generate recovery codes used as backup for MFA flow for User ID. Recovery codes can be used as a MFA verification type in [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method by client SDK.", + "responses": { + "201": { + "description": "MFA Recovery Codes", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaRecoveryCodes" + } + } + } + } + }, + "x-appwrite": { + "method": "createMfaRecoveryCodes", + "group": "mfa", + "weight": 269, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/name": { + "patch": { + "summary": "Update name", + "operationId": "usersUpdateName", + "tags": [ + "users" + ], + "description": "Update the user name by its unique ID.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateName", + "group": "users", + "weight": 259, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-name.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-name.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "name" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/password": { + "patch": { + "summary": "Update password", + "operationId": "usersUpdatePassword", + "tags": [ + "users" + ], + "description": "Update the user password by its unique ID.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePassword", + "group": "users", + "weight": 260, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-password.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-password.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "password": { + "type": "string", + "description": "New user password. Must be at least 8 chars.", + "x-example": null + } + }, + "required": [ + "password" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/phone": { + "patch": { + "summary": "Update phone", + "operationId": "usersUpdatePhone", + "tags": [ + "users" + ], + "description": "Update the user phone by its unique ID.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePhone", + "group": "users", + "weight": 262, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-phone.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-phone.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "number": { + "type": "string", + "description": "User phone number.", + "x-example": "+12065550100" + } + }, + "required": [ + "number" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/prefs": { + "get": { + "summary": "Get user preferences", + "operationId": "usersGetPrefs", + "tags": [ + "users" + ], + "description": "Get the user preferences by its unique ID.", + "responses": { + "200": { + "description": "Preferences", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/preferences" + } + } + } + } + }, + "x-appwrite": { + "method": "getPrefs", + "group": "users", + "weight": 249, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/get-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-user-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update user preferences", + "operationId": "usersUpdatePrefs", + "tags": [ + "users" + ], + "description": "Update the user preferences by its unique ID. The object you pass is stored as is, and replaces any previous value. The maximum allowed prefs size is 64kB and throws error if exceeded.", + "responses": { + "200": { + "description": "Preferences", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/preferences" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePrefs", + "group": "users", + "weight": 264, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "prefs": { + "type": "object", + "description": "Prefs key-value JSON object.", + "x-example": "{}" + } + }, + "required": [ + "prefs" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/sessions": { + "get": { + "summary": "List user sessions", + "operationId": "usersListSessions", + "tags": [ + "users" + ], + "description": "Get the user sessions list by its unique ID.", + "responses": { + "200": { + "description": "Sessions List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/sessionList" + } + } + } + } + }, + "x-appwrite": { + "method": "listSessions", + "group": "sessions", + "weight": 251, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-user-sessions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + }, + "post": { + "summary": "Create session", + "operationId": "usersCreateSession", + "tags": [ + "users" + ], + "description": "Creates a session for a user. Returns an immediately usable session object.\n\nIf you want to generate a token for a custom authentication flow, use the [POST \/users\/{userId}\/tokens](https:\/\/appwrite.io\/docs\/server\/users#createToken) endpoint.", + "responses": { + "201": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "createSession", + "group": "sessions", + "weight": 272, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-session.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete user sessions", + "operationId": "usersDeleteSessions", + "tags": [ + "users" + ], + "description": "Delete all user's sessions by using the user's unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSessions", + "group": "sessions", + "weight": 275, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-user-sessions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/sessions\/{sessionId}": { + "delete": { + "summary": "Delete user session", + "operationId": "usersDeleteSession", + "tags": [ + "users" + ], + "description": "Delete a user sessions by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSession", + "group": "sessions", + "weight": 274, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-user-session.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + }, + { + "name": "sessionId", + "description": "Session ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SESSION_ID>" + }, + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/status": { + "patch": { + "summary": "Update user status", + "operationId": "usersUpdateStatus", + "tags": [ + "users" + ], + "description": "Update the user status by its unique ID. Use this endpoint as an alternative to deleting a user if you want to keep user's ID reserved.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateStatus", + "group": "users", + "weight": 256, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "boolean", + "description": "User Status. To activate the user pass `true` and to block the user pass `false`.", + "x-example": false + } + }, + "required": [ + "status" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/targets": { + "get": { + "summary": "List user targets", + "operationId": "usersListTargets", + "tags": [ + "users" + ], + "description": "List the messaging targets that are associated with a user.", + "responses": { + "200": { + "description": "Target list", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/targetList" + } + } + } + } + }, + "x-appwrite": { + "method": "listTargets", + "group": "targets", + "weight": 254, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-targets.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-user-targets.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.read", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, providerId, identifier, providerType", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create user target", + "operationId": "usersCreateTarget", + "tags": [ + "users" + ], + "description": "Create a messaging target.", + "responses": { + "201": { + "description": "Target", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/target" + } + } + } + } + }, + "x-appwrite": { + "method": "createTarget", + "group": "targets", + "weight": 246, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "targetId": { + "type": "string", + "description": "Target ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<TARGET_ID>" + }, + "providerType": { + "type": "string", + "description": "The target provider type. Can be one of the following: `email`, `sms` or `push`.", + "x-example": "email", + "enum": [ + "email", + "sms", + "push" + ], + "x-enum-name": "MessagingProviderType", + "x-enum-keys": [] + }, + "identifier": { + "type": "string", + "description": "The target identifier (token, email, phone etc.)", + "x-example": "<IDENTIFIER>" + }, + "providerId": { + "type": "string", + "description": "Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Target name. Max length: 128 chars. For example: My Awesome App Galaxy S23.", + "x-example": "<NAME>" + } + }, + "required": [ + "targetId", + "providerType", + "identifier" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/targets\/{targetId}": { + "get": { + "summary": "Get user target", + "operationId": "usersGetTarget", + "tags": [ + "users" + ], + "description": "Get a user's push notification target by ID.", + "responses": { + "200": { + "description": "Target", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/target" + } + } + } + } + }, + "x-appwrite": { + "method": "getTarget", + "group": "targets", + "weight": 250, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/get-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-user-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.read", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + }, + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TARGET_ID>" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update user target", + "operationId": "usersUpdateTarget", + "tags": [ + "users" + ], + "description": "Update a messaging target.", + "responses": { + "200": { + "description": "Target", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/target" + } + } + } + } + }, + "x-appwrite": { + "method": "updateTarget", + "group": "targets", + "weight": 265, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + }, + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TARGET_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "description": "The target identifier (token, email, phone etc.)", + "x-example": "<IDENTIFIER>" + }, + "providerId": { + "type": "string", + "description": "Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Target name. Max length: 128 chars. For example: My Awesome App Galaxy S23.", + "x-example": "<NAME>" + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete user target", + "operationId": "usersDeleteTarget", + "tags": [ + "users" + ], + "description": "Delete a messaging target.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteTarget", + "group": "targets", + "weight": 277, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + }, + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TARGET_ID>" + }, + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/tokens": { + "post": { + "summary": "Create token", + "operationId": "usersCreateToken", + "tags": [ + "users" + ], + "description": "Returns a token with a secret key for creating a session. Use the user ID and secret and submit a request to the [PUT \/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process.\n", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createToken", + "group": "sessions", + "weight": 273, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-token.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "length": { + "type": "integer", + "description": "Token length in characters. The default length is 6 characters", + "x-example": 4 + }, + "expire": { + "type": "integer", + "description": "Token expiration period in seconds. The default expiration is 15 minutes.", + "x-example": 60 + } + } + } + } + } + } + } + }, + "\/users\/{userId}\/verification": { + "patch": { + "summary": "Update email verification", + "operationId": "usersUpdateEmailVerification", + "tags": [ + "users" + ], + "description": "Update the user email verification status by its unique ID.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateEmailVerification", + "group": "users", + "weight": 263, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-email-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-email-verification.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "emailVerification": { + "type": "boolean", + "description": "User email verification status.", + "x-example": false + } + }, + "required": [ + "emailVerification" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/verification\/phone": { + "patch": { + "summary": "Update phone verification", + "operationId": "usersUpdatePhoneVerification", + "tags": [ + "users" + ], + "description": "Update the user phone verification status by its unique ID.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePhoneVerification", + "group": "users", + "weight": 258, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-phone-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-phone-verification.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "phoneVerification": { + "type": "boolean", + "description": "User phone verification status.", + "x-example": false + } + }, + "required": [ + "phoneVerification" + ] + } + } + } + } + } + }, + "\/vcs\/github\/installations\/{installationId}\/detections": { + "post": { + "summary": "Create repository detection", + "operationId": "vcsCreateRepositoryDetection", + "tags": [ + "vcs" + ], + "description": "Analyze a GitHub repository to automatically detect the programming language and runtime environment. This endpoint scans the repository's files and language statistics to determine the appropriate runtime settings for your function. The GitHub installation must be properly configured and the repository must be accessible through your installation for this endpoint to work.", + "responses": { + "200": { + "description": "DetectionFramework", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/detectionFramework" + } + } + } + } + }, + "x-appwrite": { + "method": "createRepositoryDetection", + "group": "repositories", + "weight": 284, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/create-repository-detection.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/create-repository-detection.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "installationId", + "description": "Installation Id", + "required": true, + "schema": { + "type": "string", + "x-example": "<INSTALLATION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerRepositoryId": { + "type": "string", + "description": "Repository Id", + "x-example": "<PROVIDER_REPOSITORY_ID>" + }, + "type": { + "type": "string", + "description": "Detector type. Must be one of the following: runtime, framework", + "x-example": "runtime", + "enum": [ + "runtime", + "framework" + ], + "x-enum-name": "VCSDetectionType", + "x-enum-keys": [] + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to Root Directory", + "x-example": "<PROVIDER_ROOT_DIRECTORY>" + } + }, + "required": [ + "providerRepositoryId", + "type" + ] + } + } + } + } + } + }, + "\/vcs\/github\/installations\/{installationId}\/providerRepositories": { + "get": { + "summary": "List repositories", + "operationId": "vcsListRepositories", + "tags": [ + "vcs" + ], + "description": "Get a list of GitHub repositories available through your installation. This endpoint returns repositories with their basic information, detected runtime environments, and latest push dates. You can optionally filter repositories using a search term. Each repository's runtime is automatically detected based on its contents and language statistics. The GitHub installation must be properly configured for this endpoint to work.", + "responses": { + "200": { + "description": "Framework Provider Repositories List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/providerRepositoryFrameworkList" + } + } + } + } + }, + "x-appwrite": { + "method": "listRepositories", + "group": "repositories", + "weight": 285, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/list-repositories.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/list-repositories.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "installationId", + "description": "Installation Id", + "required": true, + "schema": { + "type": "string", + "x-example": "<INSTALLATION_ID>" + }, + "in": "path" + }, + { + "name": "type", + "description": "Detector type. Must be one of the following: runtime, framework", + "required": true, + "schema": { + "type": "string", + "x-example": "runtime", + "enum": [ + "runtime", + "framework" + ], + "x-enum-name": "VCSDetectionType", + "x-enum-keys": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create repository", + "operationId": "vcsCreateRepository", + "tags": [ + "vcs" + ], + "description": "Create a new GitHub repository through your installation. This endpoint allows you to create either a public or private repository by specifying a name and visibility setting. The repository will be created under your GitHub user account or organization, depending on your installation type. The GitHub installation must be properly configured and have the necessary permissions for repository creation.", + "responses": { + "200": { + "description": "ProviderRepository", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/providerRepository" + } + } + } + } + }, + "x-appwrite": { + "method": "createRepository", + "group": "repositories", + "weight": 286, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/create-repository.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/create-repository.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "installationId", + "description": "Installation Id", + "required": true, + "schema": { + "type": "string", + "x-example": "<INSTALLATION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Repository name (slug)", + "x-example": "<NAME>" + }, + "private": { + "type": "boolean", + "description": "Mark repository public or private", + "x-example": false + } + }, + "required": [ + "name", + "private" + ] + } + } + } + } + } + }, + "\/vcs\/github\/installations\/{installationId}\/providerRepositories\/{providerRepositoryId}": { + "get": { + "summary": "Get repository", + "operationId": "vcsGetRepository", + "tags": [ + "vcs" + ], + "description": "Get detailed information about a specific GitHub repository from your installation. This endpoint returns repository details including its ID, name, visibility status, organization, and latest push date. The GitHub installation must be properly configured and have access to the requested repository for this endpoint to work.", + "responses": { + "200": { + "description": "ProviderRepository", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/providerRepository" + } + } + } + } + }, + "x-appwrite": { + "method": "getRepository", + "group": "repositories", + "weight": 287, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/get-repository.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/get-repository.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "installationId", + "description": "Installation Id", + "required": true, + "schema": { + "type": "string", + "x-example": "<INSTALLATION_ID>" + }, + "in": "path" + }, + { + "name": "providerRepositoryId", + "description": "Repository Id", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_REPOSITORY_ID>" + }, + "in": "path" + } + ] + } + }, + "\/vcs\/github\/installations\/{installationId}\/providerRepositories\/{providerRepositoryId}\/branches": { + "get": { + "summary": "List repository branches", + "operationId": "vcsListRepositoryBranches", + "tags": [ + "vcs" + ], + "description": "Get a list of all branches from a GitHub repository in your installation. This endpoint returns the names of all branches in the repository and their total count. The GitHub installation must be properly configured and have access to the requested repository for this endpoint to work.\n", + "responses": { + "200": { + "description": "Branches List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/branchList" + } + } + } + } + }, + "x-appwrite": { + "method": "listRepositoryBranches", + "group": "repositories", + "weight": 288, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/list-repository-branches.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/list-repository-branches.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "installationId", + "description": "Installation Id", + "required": true, + "schema": { + "type": "string", + "x-example": "<INSTALLATION_ID>" + }, + "in": "path" + }, + { + "name": "providerRepositoryId", + "description": "Repository Id", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_REPOSITORY_ID>" + }, + "in": "path" + } + ] + } + }, + "\/vcs\/github\/installations\/{installationId}\/providerRepositories\/{providerRepositoryId}\/contents": { + "get": { + "summary": "Get files and directories of a VCS repository", + "operationId": "vcsGetRepositoryContents", + "tags": [ + "vcs" + ], + "description": "Get a list of files and directories from a GitHub repository connected to your project. This endpoint returns the contents of a specified repository path, including file names, sizes, and whether each item is a file or directory. The GitHub installation must be properly configured and the repository must be accessible through your installation for this endpoint to work.\n", + "responses": { + "200": { + "description": "VCS Content List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/vcsContentList" + } + } + } + } + }, + "x-appwrite": { + "method": "getRepositoryContents", + "group": "repositories", + "weight": 283, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/get-repository-contents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/get-repository-contents.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "installationId", + "description": "Installation Id", + "required": true, + "schema": { + "type": "string", + "x-example": "<INSTALLATION_ID>" + }, + "in": "path" + }, + { + "name": "providerRepositoryId", + "description": "Repository Id", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_REPOSITORY_ID>" + }, + "in": "path" + }, + { + "name": "providerRootDirectory", + "description": "Path to get contents of nested directory", + "required": false, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ROOT_DIRECTORY>", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/vcs\/github\/installations\/{installationId}\/repositories\/{repositoryId}": { + "patch": { + "summary": "Update external deployment (authorize)", + "operationId": "vcsUpdateExternalDeployments", + "tags": [ + "vcs" + ], + "description": "Authorize and create deployments for a GitHub pull request in your project. This endpoint allows external contributions by creating deployments from pull requests, enabling preview environments for code review. The pull request must be open and not previously authorized. The GitHub installation must be properly configured and have access to both the repository and pull request for this endpoint to work.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "updateExternalDeployments", + "group": "repositories", + "weight": 293, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/update-external-deployments.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/update-external-deployments.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "installationId", + "description": "Installation Id", + "required": true, + "schema": { + "type": "string", + "x-example": "<INSTALLATION_ID>" + }, + "in": "path" + }, + { + "name": "repositoryId", + "description": "VCS Repository Id", + "required": true, + "schema": { + "type": "string", + "x-example": "<REPOSITORY_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerPullRequestId": { + "type": "string", + "description": "GitHub Pull Request Id", + "x-example": "<PROVIDER_PULL_REQUEST_ID>" + } + }, + "required": [ + "providerPullRequestId" + ] + } + } + } + } + } + }, + "\/vcs\/installations": { + "get": { + "summary": "List installations", + "operationId": "vcsListInstallations", + "tags": [ + "vcs" + ], + "description": "List all VCS installations configured for the current project. This endpoint returns a list of installations including their provider, organization, and other configuration details.\n", + "responses": { + "200": { + "description": "Installations List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/installationList" + } + } + } + } + }, + "x-appwrite": { + "method": "listInstallations", + "group": "installations", + "weight": 290, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/list-installations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/list-installations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: provider, organization", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/vcs\/installations\/{installationId}": { + "get": { + "summary": "Get installation", + "operationId": "vcsGetInstallation", + "tags": [ + "vcs" + ], + "description": "Get a VCS installation by its unique ID. This endpoint returns the installation's details including its provider, organization, and configuration. ", + "responses": { + "200": { + "description": "Installation", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/installation" + } + } + } + } + }, + "x-appwrite": { + "method": "getInstallation", + "group": "installations", + "weight": 291, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/get-installation.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/get-installation.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "installationId", + "description": "Installation Id", + "required": true, + "schema": { + "type": "string", + "x-example": "<INSTALLATION_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete installation", + "operationId": "vcsDeleteInstallation", + "tags": [ + "vcs" + ], + "description": "Delete a VCS installation by its unique ID. This endpoint removes the installation and all its associated repositories from the project.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteInstallation", + "group": "installations", + "weight": 292, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/delete-installation.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/delete-installation.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "installationId", + "description": "Installation Id", + "required": true, + "schema": { + "type": "string", + "x-example": "<INSTALLATION_ID>" + }, + "in": "path" + } + ] + } + } + }, + "tags": [ + { + "name": "account", + "description": "The Account service allows you to authenticate and manage a user account." + }, + { + "name": "avatars", + "description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars." + }, + { + "name": "databases", + "description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents" + }, + { + "name": "locale", + "description": "The Locale service allows you to customize your app based on your users' location." + }, + { + "name": "health", + "description": "The Health service allows you to both validate and monitor your Appwrite server's health." + }, + { + "name": "projects", + "description": "The Project service allows you to manage all the projects in your Appwrite server." + }, + { + "name": "project", + "description": "The Project service allows you to manage all the projects in your Appwrite server." + }, + { + "name": "storage", + "description": "The Storage service allows you to manage your project files." + }, + { + "name": "teams", + "description": "The Teams service allows you to group users of your project and to enable them to share read and write access to your project resources" + }, + { + "name": "users", + "description": "The Users service allows you to manage your project users." + }, + { + "name": "sites", + "description": "The Sites Service allows you view, create and manage your web applications." + }, + { + "name": "functions", + "description": "The Functions Service allows you view, create and manage your Cloud Functions." + }, + { + "name": "proxy", + "description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration." + }, + { + "name": "graphql", + "description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL." + }, + { + "name": "console", + "description": "The Console service allows you to interact with console relevant informations." + }, + { + "name": "migrations", + "description": "The Migrations service allows you to migrate third-party data to your Appwrite project." + }, + { + "name": "messaging", + "description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.)." + } + ], + "components": { + "schemas": { + "any": { + "description": "Any", + "type": "object", + "additionalProperties": true + }, + "error": { + "description": "Error", + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Error message.", + "x-example": "Not found" + }, + "code": { + "type": "string", + "description": "Error code.", + "x-example": "404" + }, + "type": { + "type": "string", + "description": "Error type. You can learn more about all the error types at https:\/\/appwrite.io\/docs\/error-codes#errorTypes", + "x-example": "not_found" + }, + "version": { + "type": "string", + "description": "Server version number.", + "x-example": "1.0" + } + }, + "required": [ + "message", + "code", + "type", + "version" + ] + }, + "documentList": { + "description": "Documents List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of documents documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "documents": { + "type": "array", + "description": "List of documents.", + "items": { + "$ref": "#\/components\/schemas\/document" + }, + "x-example": "" + } + }, + "required": [ + "total", + "documents" + ] + }, + "collectionList": { + "description": "Collections List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of collections documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "collections": { + "type": "array", + "description": "List of collections.", + "items": { + "$ref": "#\/components\/schemas\/collection" + }, + "x-example": "" + } + }, + "required": [ + "total", + "collections" + ] + }, + "databaseList": { + "description": "Databases List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of databases documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "databases": { + "type": "array", + "description": "List of databases.", + "items": { + "$ref": "#\/components\/schemas\/database" + }, + "x-example": "" + } + }, + "required": [ + "total", + "databases" + ] + }, + "indexList": { + "description": "Indexes List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of indexes documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "indexes": { + "type": "array", + "description": "List of indexes.", + "items": { + "$ref": "#\/components\/schemas\/index" + }, + "x-example": "" + } + }, + "required": [ + "total", + "indexes" + ] + }, + "userList": { + "description": "Users List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of users documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "users": { + "type": "array", + "description": "List of users.", + "items": { + "$ref": "#\/components\/schemas\/user" + }, + "x-example": "" + } + }, + "required": [ + "total", + "users" + ] + }, + "sessionList": { + "description": "Sessions List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of sessions documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "sessions": { + "type": "array", + "description": "List of sessions.", + "items": { + "$ref": "#\/components\/schemas\/session" + }, + "x-example": "" + } + }, + "required": [ + "total", + "sessions" + ] + }, + "identityList": { + "description": "Identities List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of identities documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "identities": { + "type": "array", + "description": "List of identities.", + "items": { + "$ref": "#\/components\/schemas\/identity" + }, + "x-example": "" + } + }, + "required": [ + "total", + "identities" + ] + }, + "logList": { + "description": "Logs List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of logs documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "logs": { + "type": "array", + "description": "List of logs.", + "items": { + "$ref": "#\/components\/schemas\/log" + }, + "x-example": "" + } + }, + "required": [ + "total", + "logs" + ] + }, + "fileList": { + "description": "Files List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of files documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "files": { + "type": "array", + "description": "List of files.", + "items": { + "$ref": "#\/components\/schemas\/file" + }, + "x-example": "" + } + }, + "required": [ + "total", + "files" + ] + }, + "bucketList": { + "description": "Buckets List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of buckets documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "buckets": { + "type": "array", + "description": "List of buckets.", + "items": { + "$ref": "#\/components\/schemas\/bucket" + }, + "x-example": "" + } + }, + "required": [ + "total", + "buckets" + ] + }, + "resourceTokenList": { + "description": "Resource Tokens List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of tokens documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "tokens": { + "type": "array", + "description": "List of tokens.", + "items": { + "$ref": "#\/components\/schemas\/resourceToken" + }, + "x-example": "" + } + }, + "required": [ + "total", + "tokens" + ] + }, + "teamList": { + "description": "Teams List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of teams documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "teams": { + "type": "array", + "description": "List of teams.", + "items": { + "$ref": "#\/components\/schemas\/team" + }, + "x-example": "" + } + }, + "required": [ + "total", + "teams" + ] + }, + "membershipList": { + "description": "Memberships List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of memberships documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "memberships": { + "type": "array", + "description": "List of memberships.", + "items": { + "$ref": "#\/components\/schemas\/membership" + }, + "x-example": "" + } + }, + "required": [ + "total", + "memberships" + ] + }, + "siteList": { + "description": "Sites List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of sites documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "sites": { + "type": "array", + "description": "List of sites.", + "items": { + "$ref": "#\/components\/schemas\/site" + }, + "x-example": "" + } + }, + "required": [ + "total", + "sites" + ] + }, + "templateSiteList": { + "description": "Site Templates List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of templates documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "templates": { + "type": "array", + "description": "List of templates.", + "items": { + "$ref": "#\/components\/schemas\/templateSite" + }, + "x-example": "" + } + }, + "required": [ + "total", + "templates" + ] + }, + "functionList": { + "description": "Functions List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of functions documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "functions": { + "type": "array", + "description": "List of functions.", + "items": { + "$ref": "#\/components\/schemas\/function" + }, + "x-example": "" + } + }, + "required": [ + "total", + "functions" + ] + }, + "templateFunctionList": { + "description": "Function Templates List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of templates documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "templates": { + "type": "array", + "description": "List of templates.", + "items": { + "$ref": "#\/components\/schemas\/templateFunction" + }, + "x-example": "" + } + }, + "required": [ + "total", + "templates" + ] + }, + "installationList": { + "description": "Installations List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of installations documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "installations": { + "type": "array", + "description": "List of installations.", + "items": { + "$ref": "#\/components\/schemas\/installation" + }, + "x-example": "" + } + }, + "required": [ + "total", + "installations" + ] + }, + "providerRepositoryFrameworkList": { + "description": "Framework Provider Repositories List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of frameworkProviderRepositories documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "frameworkProviderRepositories": { + "type": "array", + "description": "List of frameworkProviderRepositories.", + "items": { + "$ref": "#\/components\/schemas\/providerRepositoryFramework" + }, + "x-example": "" + } + }, + "required": [ + "total", + "frameworkProviderRepositories" + ] + }, + "providerRepositoryRuntimeList": { + "description": "Runtime Provider Repositories List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of runtimeProviderRepositories documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "runtimeProviderRepositories": { + "type": "array", + "description": "List of runtimeProviderRepositories.", + "items": { + "$ref": "#\/components\/schemas\/providerRepositoryRuntime" + }, + "x-example": "" + } + }, + "required": [ + "total", + "runtimeProviderRepositories" + ] + }, + "branchList": { + "description": "Branches List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of branches documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "branches": { + "type": "array", + "description": "List of branches.", + "items": { + "$ref": "#\/components\/schemas\/branch" + }, + "x-example": "" + } + }, + "required": [ + "total", + "branches" + ] + }, + "frameworkList": { + "description": "Frameworks List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of frameworks documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "frameworks": { + "type": "array", + "description": "List of frameworks.", + "items": { + "$ref": "#\/components\/schemas\/framework" + }, + "x-example": "" + } + }, + "required": [ + "total", + "frameworks" + ] + }, + "runtimeList": { + "description": "Runtimes List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of runtimes documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "runtimes": { + "type": "array", + "description": "List of runtimes.", + "items": { + "$ref": "#\/components\/schemas\/runtime" + }, + "x-example": "" + } + }, + "required": [ + "total", + "runtimes" + ] + }, + "deploymentList": { + "description": "Deployments List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of deployments documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "deployments": { + "type": "array", + "description": "List of deployments.", + "items": { + "$ref": "#\/components\/schemas\/deployment" + }, + "x-example": "" + } + }, + "required": [ + "total", + "deployments" + ] + }, + "executionList": { + "description": "Executions List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of executions documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "executions": { + "type": "array", + "description": "List of executions.", + "items": { + "$ref": "#\/components\/schemas\/execution" + }, + "x-example": "" + } + }, + "required": [ + "total", + "executions" + ] + }, + "projectList": { + "description": "Projects List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of projects documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "projects": { + "type": "array", + "description": "List of projects.", + "items": { + "$ref": "#\/components\/schemas\/project" + }, + "x-example": "" + } + }, + "required": [ + "total", + "projects" + ] + }, + "webhookList": { + "description": "Webhooks List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of webhooks documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "webhooks": { + "type": "array", + "description": "List of webhooks.", + "items": { + "$ref": "#\/components\/schemas\/webhook" + }, + "x-example": "" + } + }, + "required": [ + "total", + "webhooks" + ] + }, + "keyList": { + "description": "API Keys List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of keys documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "keys": { + "type": "array", + "description": "List of keys.", + "items": { + "$ref": "#\/components\/schemas\/key" + }, + "x-example": "" + } + }, + "required": [ + "total", + "keys" + ] + }, + "devKeyList": { + "description": "Dev Keys List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of devKeys documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "devKeys": { + "type": "array", + "description": "List of devKeys.", + "items": { + "$ref": "#\/components\/schemas\/devKey" + }, + "x-example": "" + } + }, + "required": [ + "total", + "devKeys" + ] + }, + "platformList": { + "description": "Platforms List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of platforms documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "platforms": { + "type": "array", + "description": "List of platforms.", + "items": { + "$ref": "#\/components\/schemas\/platform" + }, + "x-example": "" + } + }, + "required": [ + "total", + "platforms" + ] + }, + "countryList": { + "description": "Countries List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of countries documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "countries": { + "type": "array", + "description": "List of countries.", + "items": { + "$ref": "#\/components\/schemas\/country" + }, + "x-example": "" + } + }, + "required": [ + "total", + "countries" + ] + }, + "continentList": { + "description": "Continents List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of continents documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "continents": { + "type": "array", + "description": "List of continents.", + "items": { + "$ref": "#\/components\/schemas\/continent" + }, + "x-example": "" + } + }, + "required": [ + "total", + "continents" + ] + }, + "languageList": { + "description": "Languages List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of languages documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "languages": { + "type": "array", + "description": "List of languages.", + "items": { + "$ref": "#\/components\/schemas\/language" + }, + "x-example": "" + } + }, + "required": [ + "total", + "languages" + ] + }, + "currencyList": { + "description": "Currencies List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of currencies documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "currencies": { + "type": "array", + "description": "List of currencies.", + "items": { + "$ref": "#\/components\/schemas\/currency" + }, + "x-example": "" + } + }, + "required": [ + "total", + "currencies" + ] + }, + "phoneList": { + "description": "Phones List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of phones documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "phones": { + "type": "array", + "description": "List of phones.", + "items": { + "$ref": "#\/components\/schemas\/phone" + }, + "x-example": "" + } + }, + "required": [ + "total", + "phones" + ] + }, + "variableList": { + "description": "Variables List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of variables documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "variables": { + "type": "array", + "description": "List of variables.", + "items": { + "$ref": "#\/components\/schemas\/variable" + }, + "x-example": "" + } + }, + "required": [ + "total", + "variables" + ] + }, + "proxyRuleList": { + "description": "Rule List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of rules documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "rules": { + "type": "array", + "description": "List of rules.", + "items": { + "$ref": "#\/components\/schemas\/proxyRule" + }, + "x-example": "" + } + }, + "required": [ + "total", + "rules" + ] + }, + "localeCodeList": { + "description": "Locale codes list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of localeCodes documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "localeCodes": { + "type": "array", + "description": "List of localeCodes.", + "items": { + "$ref": "#\/components\/schemas\/localeCode" + }, + "x-example": "" + } + }, + "required": [ + "total", + "localeCodes" + ] + }, + "providerList": { + "description": "Provider list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of providers documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "providers": { + "type": "array", + "description": "List of providers.", + "items": { + "$ref": "#\/components\/schemas\/provider" + }, + "x-example": "" + } + }, + "required": [ + "total", + "providers" + ] + }, + "messageList": { + "description": "Message list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of messages documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "messages": { + "type": "array", + "description": "List of messages.", + "items": { + "$ref": "#\/components\/schemas\/message" + }, + "x-example": "" + } + }, + "required": [ + "total", + "messages" + ] + }, + "topicList": { + "description": "Topic list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of topics documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "topics": { + "type": "array", + "description": "List of topics.", + "items": { + "$ref": "#\/components\/schemas\/topic" + }, + "x-example": "" + } + }, + "required": [ + "total", + "topics" + ] + }, + "subscriberList": { + "description": "Subscriber list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of subscribers documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "subscribers": { + "type": "array", + "description": "List of subscribers.", + "items": { + "$ref": "#\/components\/schemas\/subscriber" + }, + "x-example": "" + } + }, + "required": [ + "total", + "subscribers" + ] + }, + "targetList": { + "description": "Target list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of targets documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "targets": { + "type": "array", + "description": "List of targets.", + "items": { + "$ref": "#\/components\/schemas\/target" + }, + "x-example": "" + } + }, + "required": [ + "total", + "targets" + ] + }, + "migrationList": { + "description": "Migrations List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of migrations documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "migrations": { + "type": "array", + "description": "List of migrations.", + "items": { + "$ref": "#\/components\/schemas\/migration" + }, + "x-example": "" + } + }, + "required": [ + "total", + "migrations" + ] + }, + "specificationList": { + "description": "Specifications List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of specifications documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "specifications": { + "type": "array", + "description": "List of specifications.", + "items": { + "$ref": "#\/components\/schemas\/specification" + }, + "x-example": "" + } + }, + "required": [ + "total", + "specifications" + ] + }, + "vcsContentList": { + "description": "VCS Content List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of contents documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "contents": { + "type": "array", + "description": "List of contents.", + "items": { + "$ref": "#\/components\/schemas\/vcsContent" + }, + "x-example": "" + } + }, + "required": [ + "total", + "contents" + ] + }, + "database": { + "description": "Database", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Database ID.", + "x-example": "5e5ea5c16897e" + }, + "name": { + "type": "string", + "description": "Database name.", + "x-example": "My Database" + }, + "$createdAt": { + "type": "string", + "description": "Database creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Database update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "enabled": { + "type": "boolean", + "description": "If database is enabled. Can be 'enabled' or 'disabled'. When disabled, the database is inaccessible to users, but remains accessible to Server SDKs using API keys.", + "x-example": false + } + }, + "required": [ + "$id", + "name", + "$createdAt", + "$updatedAt", + "enabled" + ] + }, + "collection": { + "description": "Collection", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Collection ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Collection creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Collection update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Collection permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + }, + "databaseId": { + "type": "string", + "description": "Database ID.", + "x-example": "5e5ea5c16897e" + }, + "name": { + "type": "string", + "description": "Collection name.", + "x-example": "My Collection" + }, + "enabled": { + "type": "boolean", + "description": "Collection enabled. Can be 'enabled' or 'disabled'. When disabled, the collection is inaccessible to users, but remains accessible to Server SDKs using API keys.", + "x-example": false + }, + "documentSecurity": { + "type": "boolean", + "description": "Whether document-level permissions are enabled. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": true + }, + "attributes": { + "type": "array", + "description": "Collection attributes.", + "items": { + "anyOf": [ + { + "$ref": "#\/components\/schemas\/attributeBoolean" + }, + { + "$ref": "#\/components\/schemas\/attributeInteger" + }, + { + "$ref": "#\/components\/schemas\/attributeFloat" + }, + { + "$ref": "#\/components\/schemas\/attributeEmail" + }, + { + "$ref": "#\/components\/schemas\/attributeEnum" + }, + { + "$ref": "#\/components\/schemas\/attributeUrl" + }, + { + "$ref": "#\/components\/schemas\/attributeIp" + }, + { + "$ref": "#\/components\/schemas\/attributeDatetime" + }, + { + "$ref": "#\/components\/schemas\/attributeRelationship" + }, + { + "$ref": "#\/components\/schemas\/attributeString" + } + ] + }, + "x-example": {} + }, + "indexes": { + "type": "array", + "description": "Collection indexes.", + "items": { + "$ref": "#\/components\/schemas\/index" + }, + "x-example": {} + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "$permissions", + "databaseId", + "name", + "enabled", + "documentSecurity", + "attributes", + "indexes" + ] + }, + "attributeList": { + "description": "Attributes List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of attributes in the given collection.", + "x-example": 5, + "format": "int32" + }, + "attributes": { + "type": "array", + "description": "List of attributes.", + "items": { + "anyOf": [ + { + "$ref": "#\/components\/schemas\/attributeBoolean" + }, + { + "$ref": "#\/components\/schemas\/attributeInteger" + }, + { + "$ref": "#\/components\/schemas\/attributeFloat" + }, + { + "$ref": "#\/components\/schemas\/attributeEmail" + }, + { + "$ref": "#\/components\/schemas\/attributeEnum" + }, + { + "$ref": "#\/components\/schemas\/attributeUrl" + }, + { + "$ref": "#\/components\/schemas\/attributeIp" + }, + { + "$ref": "#\/components\/schemas\/attributeDatetime" + }, + { + "$ref": "#\/components\/schemas\/attributeRelationship" + }, + { + "$ref": "#\/components\/schemas\/attributeString" + } + ] + }, + "x-example": "" + } + }, + "required": [ + "total", + "attributes" + ] + }, + "attributeString": { + "description": "AttributeString", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "fullName" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "size": { + "type": "integer", + "description": "Attribute size.", + "x-example": 128, + "format": "int32" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "default", + "nullable": true + }, + "encrypt": { + "type": "boolean", + "description": "Defines whether this attribute is encrypted or not.", + "x-example": false, + "nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "size" + ] + }, + "attributeInteger": { + "description": "AttributeInteger", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "count" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "integer" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "min": { + "type": "integer", + "description": "Minimum value to enforce for new documents.", + "x-example": 1, + "format": "int32", + "nullable": true + }, + "max": { + "type": "integer", + "description": "Maximum value to enforce for new documents.", + "x-example": 10, + "format": "int32", + "nullable": true + }, + "default": { + "type": "integer", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": 10, + "format": "int32", + "nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt" + ] + }, + "attributeFloat": { + "description": "AttributeFloat", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "percentageCompleted" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "double" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "min": { + "type": "number", + "description": "Minimum value to enforce for new documents.", + "x-example": 1.5, + "format": "double", + "nullable": true + }, + "max": { + "type": "number", + "description": "Maximum value to enforce for new documents.", + "x-example": 10.5, + "format": "double", + "nullable": true + }, + "default": { + "type": "number", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": 2.5, + "format": "double", + "nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt" + ] + }, + "attributeBoolean": { + "description": "AttributeBoolean", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "isEnabled" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "boolean" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "default": { + "type": "boolean", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": false, + "nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt" + ] + }, + "attributeEmail": { + "description": "AttributeEmail", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "userEmail" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "format": { + "type": "string", + "description": "String format.", + "x-example": "email" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "default@example.com", + "nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "format" + ] + }, + "attributeEnum": { + "description": "AttributeEnum", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "status" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "elements": { + "type": "array", + "description": "Array of elements in enumerated type.", + "items": { + "type": "string" + }, + "x-example": "element" + }, + "format": { + "type": "string", + "description": "String format.", + "x-example": "enum" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "element", + "nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "elements", + "format" + ] + }, + "attributeIp": { + "description": "AttributeIP", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "ipAddress" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "format": { + "type": "string", + "description": "String format.", + "x-example": "ip" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "192.0.2.0", + "nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "format" + ] + }, + "attributeUrl": { + "description": "AttributeURL", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "githubUrl" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "format": { + "type": "string", + "description": "String format.", + "x-example": "url" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "http:\/\/example.com", + "nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "format" + ] + }, + "attributeDatetime": { + "description": "AttributeDatetime", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "birthDay" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "datetime" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "format": { + "type": "string", + "description": "ISO 8601 format.", + "x-example": "datetime" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Only null is optional", + "x-example": "2020-10-15T06:38:00.000+00:00", + "nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "format" + ] + }, + "attributeRelationship": { + "description": "AttributeRelationship", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "fullName" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "relatedCollection": { + "type": "string", + "description": "The ID of the related collection.", + "x-example": "collection" + }, + "relationType": { + "type": "string", + "description": "The type of the relationship.", + "x-example": "oneToOne|oneToMany|manyToOne|manyToMany" + }, + "twoWay": { + "type": "boolean", + "description": "Is the relationship two-way?", + "x-example": false + }, + "twoWayKey": { + "type": "string", + "description": "The key of the two-way relationship.", + "x-example": "string" + }, + "onDelete": { + "type": "string", + "description": "How deleting the parent document will propagate to child documents.", + "x-example": "restrict|cascade|setNull" + }, + "side": { + "type": "string", + "description": "Whether this is the parent or child side of the relationship", + "x-example": "parent|child" + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "relatedCollection", + "relationType", + "twoWay", + "twoWayKey", + "onDelete", + "side" + ] + }, + "index": { + "description": "Index", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Index Key.", + "x-example": "index1" + }, + "type": { + "type": "string", + "description": "Index type.", + "x-example": "primary" + }, + "status": { + "type": "string", + "description": "Index status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an index.", + "x-example": "string" + }, + "attributes": { + "type": "array", + "description": "Index attributes.", + "items": { + "type": "string" + }, + "x-example": [] + }, + "lengths": { + "type": "array", + "description": "Index attributes length.", + "items": { + "type": "integer", + "format": "int32" + }, + "x-example": [] + }, + "orders": { + "type": "array", + "description": "Index orders.", + "items": { + "type": "string" + }, + "x-example": [], + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Index creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Index update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "key", + "type", + "status", + "error", + "attributes", + "lengths", + "$createdAt", + "$updatedAt" + ] + }, + "document": { + "description": "Document", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Document ID.", + "x-example": "5e5ea5c16897e" + }, + "$sequence": { + "type": "integer", + "description": "Document automatically incrementing ID.", + "x-example": 1, + "format": "int32" + }, + "$collectionId": { + "type": "string", + "description": "Collection ID.", + "x-example": "5e5ea5c15117e" + }, + "$databaseId": { + "type": "string", + "description": "Database ID.", + "x-example": "5e5ea5c15117e" + }, + "$createdAt": { + "type": "string", + "description": "Document creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Document update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Document permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + } + }, + "additionalProperties": true, + "required": [ + "$id", + "$sequence", + "$collectionId", + "$databaseId", + "$createdAt", + "$updatedAt", + "$permissions" + ] + }, + "log": { + "description": "Log", + "type": "object", + "properties": { + "event": { + "type": "string", + "description": "Event name.", + "x-example": "account.sessions.create" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "610fc2f985ee0" + }, + "userEmail": { + "type": "string", + "description": "User Email.", + "x-example": "john@appwrite.io" + }, + "userName": { + "type": "string", + "description": "User Name.", + "x-example": "John Doe" + }, + "mode": { + "type": "string", + "description": "API mode when event triggered.", + "x-example": "admin" + }, + "ip": { + "type": "string", + "description": "IP session in use when the session was created.", + "x-example": "127.0.0.1" + }, + "time": { + "type": "string", + "description": "Log creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "osCode": { + "type": "string", + "description": "Operating system code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/os.json).", + "x-example": "Mac" + }, + "osName": { + "type": "string", + "description": "Operating system name.", + "x-example": "Mac" + }, + "osVersion": { + "type": "string", + "description": "Operating system version.", + "x-example": "Mac" + }, + "clientType": { + "type": "string", + "description": "Client type.", + "x-example": "browser" + }, + "clientCode": { + "type": "string", + "description": "Client code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/clients.json).", + "x-example": "CM" + }, + "clientName": { + "type": "string", + "description": "Client name.", + "x-example": "Chrome Mobile iOS" + }, + "clientVersion": { + "type": "string", + "description": "Client version.", + "x-example": "84.0" + }, + "clientEngine": { + "type": "string", + "description": "Client engine name.", + "x-example": "WebKit" + }, + "clientEngineVersion": { + "type": "string", + "description": "Client engine name.", + "x-example": "605.1.15" + }, + "deviceName": { + "type": "string", + "description": "Device name.", + "x-example": "smartphone" + }, + "deviceBrand": { + "type": "string", + "description": "Device brand name.", + "x-example": "Google" + }, + "deviceModel": { + "type": "string", + "description": "Device model name.", + "x-example": "Nexus 5" + }, + "countryCode": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + }, + "countryName": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + } + }, + "required": [ + "event", + "userId", + "userEmail", + "userName", + "mode", + "ip", + "time", + "osCode", + "osName", + "osVersion", + "clientType", + "clientCode", + "clientName", + "clientVersion", + "clientEngine", + "clientEngineVersion", + "deviceName", + "deviceBrand", + "deviceModel", + "countryCode", + "countryName" + ] + }, + "user": { + "description": "User", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "User creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "User update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "User name.", + "x-example": "John Doe" + }, + "password": { + "type": "string", + "description": "Hashed user password.", + "x-example": "$argon2id$v=19$m=2048,t=4,p=3$aUZjLnliVWRINmFNTWMudg$5S+x+7uA31xFnrHFT47yFwcJeaP0w92L\/4LdgrVRXxE", + "nullable": true + }, + "hash": { + "type": "string", + "description": "Password hashing algorithm.", + "x-example": "argon2", + "nullable": true + }, + "hashOptions": { + "type": "object", + "description": "Password hashing algorithm configuration.", + "x-example": {}, + "items": { + "oneOf": [ + { + "$ref": "#\/components\/schemas\/algoArgon2" + }, + { + "$ref": "#\/components\/schemas\/algoScrypt" + }, + { + "$ref": "#\/components\/schemas\/algoScryptModified" + }, + { + "$ref": "#\/components\/schemas\/algoBcrypt" + }, + { + "$ref": "#\/components\/schemas\/algoPhpass" + }, + { + "$ref": "#\/components\/schemas\/algoSha" + }, + { + "$ref": "#\/components\/schemas\/algoMd5" + } + ] + }, + "nullable": true + }, + "registration": { + "type": "string", + "description": "User registration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "boolean", + "description": "User status. Pass `true` for enabled and `false` for disabled.", + "x-example": true + }, + "labels": { + "type": "array", + "description": "Labels for the user.", + "items": { + "type": "string" + }, + "x-example": [ + "vip" + ] + }, + "passwordUpdate": { + "type": "string", + "description": "Password update time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "email": { + "type": "string", + "description": "User email address.", + "x-example": "john@appwrite.io" + }, + "phone": { + "type": "string", + "description": "User phone number in E.164 format.", + "x-example": "+4930901820" + }, + "emailVerification": { + "type": "boolean", + "description": "Email verification status.", + "x-example": true + }, + "phoneVerification": { + "type": "boolean", + "description": "Phone verification status.", + "x-example": true + }, + "mfa": { + "type": "boolean", + "description": "Multi factor authentication status.", + "x-example": true + }, + "prefs": { + "type": "object", + "description": "User preferences as a key-value object", + "x-example": { + "theme": "pink", + "timezone": "UTC" + }, + "items": { + "$ref": "#\/components\/schemas\/preferences" + } + }, + "targets": { + "type": "array", + "description": "A user-owned message receiver. A single user may have multiple e.g. emails, phones, and a browser. Each target is registered with a single provider.", + "items": { + "$ref": "#\/components\/schemas\/target" + }, + "x-example": [] + }, + "accessedAt": { + "type": "string", + "description": "Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "registration", + "status", + "labels", + "passwordUpdate", + "email", + "phone", + "emailVerification", + "phoneVerification", + "mfa", + "prefs", + "targets", + "accessedAt" + ] + }, + "algoMd5": { + "description": "AlgoMD5", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "md5" + } + }, + "required": [ + "type" + ] + }, + "algoSha": { + "description": "AlgoSHA", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "sha" + } + }, + "required": [ + "type" + ] + }, + "algoPhpass": { + "description": "AlgoPHPass", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "phpass" + } + }, + "required": [ + "type" + ] + }, + "algoBcrypt": { + "description": "AlgoBcrypt", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "bcrypt" + } + }, + "required": [ + "type" + ] + }, + "algoScrypt": { + "description": "AlgoScrypt", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "scrypt" + }, + "costCpu": { + "type": "integer", + "description": "CPU complexity of computed hash.", + "x-example": 8, + "format": "int32" + }, + "costMemory": { + "type": "integer", + "description": "Memory complexity of computed hash.", + "x-example": 14, + "format": "int32" + }, + "costParallel": { + "type": "integer", + "description": "Parallelization of computed hash.", + "x-example": 1, + "format": "int32" + }, + "length": { + "type": "integer", + "description": "Length used to compute hash.", + "x-example": 64, + "format": "int32" + } + }, + "required": [ + "type", + "costCpu", + "costMemory", + "costParallel", + "length" + ] + }, + "algoScryptModified": { + "description": "AlgoScryptModified", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "scryptMod" + }, + "salt": { + "type": "string", + "description": "Salt used to compute hash.", + "x-example": "UxLMreBr6tYyjQ==" + }, + "saltSeparator": { + "type": "string", + "description": "Separator used to compute hash.", + "x-example": "Bw==" + }, + "signerKey": { + "type": "string", + "description": "Key used to compute hash.", + "x-example": "XyEKE9RcTDeLEsL\/RjwPDBv\/RqDl8fb3gpYEOQaPihbxf1ZAtSOHCjuAAa7Q3oHpCYhXSN9tizHgVOwn6krflQ==" + } + }, + "required": [ + "type", + "salt", + "saltSeparator", + "signerKey" + ] + }, + "algoArgon2": { + "description": "AlgoArgon2", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "argon2" + }, + "memoryCost": { + "type": "integer", + "description": "Memory used to compute hash.", + "x-example": 65536, + "format": "int32" + }, + "timeCost": { + "type": "integer", + "description": "Amount of time consumed to compute hash", + "x-example": 4, + "format": "int32" + }, + "threads": { + "type": "integer", + "description": "Number of threads used to compute hash.", + "x-example": 3, + "format": "int32" + } + }, + "required": [ + "type", + "memoryCost", + "timeCost", + "threads" + ] + }, + "preferences": { + "description": "Preferences", + "type": "object", + "additionalProperties": true + }, + "session": { + "description": "Session", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Session ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Session creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Session update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5bb8c16897e" + }, + "expire": { + "type": "string", + "description": "Session expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "provider": { + "type": "string", + "description": "Session Provider.", + "x-example": "email" + }, + "providerUid": { + "type": "string", + "description": "Session Provider User ID.", + "x-example": "user@example.com" + }, + "providerAccessToken": { + "type": "string", + "description": "Session Provider Access Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + }, + "providerAccessTokenExpiry": { + "type": "string", + "description": "The date of when the access token expires in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "providerRefreshToken": { + "type": "string", + "description": "Session Provider Refresh Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + }, + "ip": { + "type": "string", + "description": "IP in use when the session was created.", + "x-example": "127.0.0.1" + }, + "osCode": { + "type": "string", + "description": "Operating system code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/os.json).", + "x-example": "Mac" + }, + "osName": { + "type": "string", + "description": "Operating system name.", + "x-example": "Mac" + }, + "osVersion": { + "type": "string", + "description": "Operating system version.", + "x-example": "Mac" + }, + "clientType": { + "type": "string", + "description": "Client type.", + "x-example": "browser" + }, + "clientCode": { + "type": "string", + "description": "Client code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/clients.json).", + "x-example": "CM" + }, + "clientName": { + "type": "string", + "description": "Client name.", + "x-example": "Chrome Mobile iOS" + }, + "clientVersion": { + "type": "string", + "description": "Client version.", + "x-example": "84.0" + }, + "clientEngine": { + "type": "string", + "description": "Client engine name.", + "x-example": "WebKit" + }, + "clientEngineVersion": { + "type": "string", + "description": "Client engine name.", + "x-example": "605.1.15" + }, + "deviceName": { + "type": "string", + "description": "Device name.", + "x-example": "smartphone" + }, + "deviceBrand": { + "type": "string", + "description": "Device brand name.", + "x-example": "Google" + }, + "deviceModel": { + "type": "string", + "description": "Device model name.", + "x-example": "Nexus 5" + }, + "countryCode": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + }, + "countryName": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + }, + "current": { + "type": "boolean", + "description": "Returns true if this the current user session.", + "x-example": true + }, + "factors": { + "type": "array", + "description": "Returns a list of active session factors.", + "items": { + "type": "string" + }, + "x-example": [ + "email" + ] + }, + "secret": { + "type": "string", + "description": "Secret used to authenticate the user. Only included if the request was made with an API key", + "x-example": "5e5bb8c16897e" + }, + "mfaUpdatedAt": { + "type": "string", + "description": "Most recent date in ISO 8601 format when the session successfully passed MFA challenge.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "userId", + "expire", + "provider", + "providerUid", + "providerAccessToken", + "providerAccessTokenExpiry", + "providerRefreshToken", + "ip", + "osCode", + "osName", + "osVersion", + "clientType", + "clientCode", + "clientName", + "clientVersion", + "clientEngine", + "clientEngineVersion", + "deviceName", + "deviceBrand", + "deviceModel", + "countryCode", + "countryName", + "current", + "factors", + "secret", + "mfaUpdatedAt" + ] + }, + "identity": { + "description": "Identity", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Identity ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Identity creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Identity update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5bb8c16897e" + }, + "provider": { + "type": "string", + "description": "Identity Provider.", + "x-example": "email" + }, + "providerUid": { + "type": "string", + "description": "ID of the User in the Identity Provider.", + "x-example": "5e5bb8c16897e" + }, + "providerEmail": { + "type": "string", + "description": "Email of the User in the Identity Provider.", + "x-example": "user@example.com" + }, + "providerAccessToken": { + "type": "string", + "description": "Identity Provider Access Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + }, + "providerAccessTokenExpiry": { + "type": "string", + "description": "The date of when the access token expires in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "providerRefreshToken": { + "type": "string", + "description": "Identity Provider Refresh Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "userId", + "provider", + "providerUid", + "providerEmail", + "providerAccessToken", + "providerAccessTokenExpiry", + "providerRefreshToken" + ] + }, + "token": { + "description": "Token", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Token ID.", + "x-example": "bb8ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Token creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c168bb8" + }, + "secret": { + "type": "string", + "description": "Token secret key. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.", + "x-example": "" + }, + "expire": { + "type": "string", + "description": "Token expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "phrase": { + "type": "string", + "description": "Security phrase of a token. Empty if security phrase was not requested when creating a token. It includes randomly generated phrase which is also sent in the external resource such as email.", + "x-example": "Golden Fox" + } + }, + "required": [ + "$id", + "$createdAt", + "userId", + "secret", + "expire", + "phrase" + ] + }, + "jwt": { + "description": "JWT", + "type": "object", + "properties": { + "jwt": { + "type": "string", + "description": "JWT encoded string.", + "x-example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + } + }, + "required": [ + "jwt" + ] + }, + "locale": { + "description": "Locale", + "type": "object", + "properties": { + "ip": { + "type": "string", + "description": "User IP address.", + "x-example": "127.0.0.1" + }, + "countryCode": { + "type": "string", + "description": "Country code in [ISO 3166-1](http:\/\/en.wikipedia.org\/wiki\/ISO_3166-1) two-character format", + "x-example": "US" + }, + "country": { + "type": "string", + "description": "Country name. This field support localization.", + "x-example": "United States" + }, + "continentCode": { + "type": "string", + "description": "Continent code. A two character continent code \"AF\" for Africa, \"AN\" for Antarctica, \"AS\" for Asia, \"EU\" for Europe, \"NA\" for North America, \"OC\" for Oceania, and \"SA\" for South America.", + "x-example": "NA" + }, + "continent": { + "type": "string", + "description": "Continent name. This field support localization.", + "x-example": "North America" + }, + "eu": { + "type": "boolean", + "description": "True if country is part of the European Union.", + "x-example": false + }, + "currency": { + "type": "string", + "description": "Currency code in [ISO 4217-1](http:\/\/en.wikipedia.org\/wiki\/ISO_4217) three-character format", + "x-example": "USD" + } + }, + "required": [ + "ip", + "countryCode", + "country", + "continentCode", + "continent", + "eu", + "currency" + ] + }, + "localeCode": { + "description": "LocaleCode", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Locale codes in [ISO 639-1](https:\/\/en.wikipedia.org\/wiki\/List_of_ISO_639-1_codes)", + "x-example": "en-us" + }, + "name": { + "type": "string", + "description": "Locale name", + "x-example": "US" + } + }, + "required": [ + "code", + "name" + ] + }, + "file": { + "description": "File", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "File ID.", + "x-example": "5e5ea5c16897e" + }, + "bucketId": { + "type": "string", + "description": "Bucket ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "File creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "File update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "File permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + }, + "name": { + "type": "string", + "description": "File name.", + "x-example": "Pink.png" + }, + "signature": { + "type": "string", + "description": "File MD5 signature.", + "x-example": "5d529fd02b544198ae075bd57c1762bb" + }, + "mimeType": { + "type": "string", + "description": "File mime type.", + "x-example": "image\/png" + }, + "sizeOriginal": { + "type": "integer", + "description": "File original size in bytes.", + "x-example": 17890, + "format": "int32" + }, + "chunksTotal": { + "type": "integer", + "description": "Total number of chunks available", + "x-example": 17890, + "format": "int32" + }, + "chunksUploaded": { + "type": "integer", + "description": "Total number of chunks uploaded", + "x-example": 17890, + "format": "int32" + } + }, + "required": [ + "$id", + "bucketId", + "$createdAt", + "$updatedAt", + "$permissions", + "name", + "signature", + "mimeType", + "sizeOriginal", + "chunksTotal", + "chunksUploaded" + ] + }, + "bucket": { + "description": "Bucket", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Bucket ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Bucket creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Bucket update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Bucket permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + }, + "fileSecurity": { + "type": "boolean", + "description": "Whether file-level security is enabled. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": true + }, + "name": { + "type": "string", + "description": "Bucket name.", + "x-example": "Documents" + }, + "enabled": { + "type": "boolean", + "description": "Bucket enabled.", + "x-example": false + }, + "maximumFileSize": { + "type": "integer", + "description": "Maximum file size supported.", + "x-example": 100, + "format": "int32" + }, + "allowedFileExtensions": { + "type": "array", + "description": "Allowed file extensions.", + "items": { + "type": "string" + }, + "x-example": [ + "jpg", + "png" + ] + }, + "compression": { + "type": "string", + "description": "Compression algorithm choosen for compression. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).", + "x-example": "gzip" + }, + "encryption": { + "type": "boolean", + "description": "Bucket is encrypted.", + "x-example": false + }, + "antivirus": { + "type": "boolean", + "description": "Virus scanning is enabled.", + "x-example": false + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "$permissions", + "fileSecurity", + "name", + "enabled", + "maximumFileSize", + "allowedFileExtensions", + "compression", + "encryption", + "antivirus" + ] + }, + "resourceToken": { + "description": "ResourceToken", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Token ID.", + "x-example": "bb8ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Token creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "resourceId": { + "type": "string", + "description": "Resource ID.", + "x-example": "5e5ea5c168bb8:5e5ea5c168bb8" + }, + "resourceType": { + "type": "string", + "description": "Resource type.", + "x-example": "files" + }, + "expire": { + "type": "string", + "description": "Token expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "secret": { + "type": "string", + "description": "JWT encoded string.", + "x-example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + }, + "accessedAt": { + "type": "string", + "description": "Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "resourceId", + "resourceType", + "expire", + "secret", + "accessedAt" + ] + }, + "team": { + "description": "Team", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Team ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Team creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Team update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Team name.", + "x-example": "VIP" + }, + "total": { + "type": "integer", + "description": "Total number of team members.", + "x-example": 7, + "format": "int32" + }, + "prefs": { + "type": "object", + "description": "Team preferences as a key-value object", + "x-example": { + "theme": "pink", + "timezone": "UTC" + }, + "items": { + "$ref": "#\/components\/schemas\/preferences" + } + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "total", + "prefs" + ] + }, + "membership": { + "description": "Membership", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Membership ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Membership creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Membership update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c16897e" + }, + "userName": { + "type": "string", + "description": "User name. Hide this attribute by toggling membership privacy in the Console.", + "x-example": "John Doe" + }, + "userEmail": { + "type": "string", + "description": "User email address. Hide this attribute by toggling membership privacy in the Console.", + "x-example": "john@appwrite.io" + }, + "teamId": { + "type": "string", + "description": "Team ID.", + "x-example": "5e5ea5c16897e" + }, + "teamName": { + "type": "string", + "description": "Team name.", + "x-example": "VIP" + }, + "invited": { + "type": "string", + "description": "Date, the user has been invited to join the team in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "joined": { + "type": "string", + "description": "Date, the user has accepted the invitation to join the team in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "confirm": { + "type": "boolean", + "description": "User confirmation status, true if the user has joined the team or false otherwise.", + "x-example": false + }, + "mfa": { + "type": "boolean", + "description": "Multi factor authentication status, true if the user has MFA enabled or false otherwise. Hide this attribute by toggling membership privacy in the Console.", + "x-example": false + }, + "roles": { + "type": "array", + "description": "User list of roles", + "items": { + "type": "string" + }, + "x-example": [ + "owner" + ] + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "userId", + "userName", + "userEmail", + "teamId", + "teamName", + "invited", + "joined", + "confirm", + "mfa", + "roles" + ] + }, + "site": { + "description": "Site", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Site ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Site creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Site update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Site name.", + "x-example": "My Site" + }, + "enabled": { + "type": "boolean", + "description": "Site enabled.", + "x-example": false + }, + "live": { + "type": "boolean", + "description": "Is the site deployed with the latest configuration? This is set to false if you've changed an environment variables, entrypoint, commands, or other settings that needs redeploy to be applied. When the value is false, redeploy the site to update it with the latest configuration.", + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.", + "x-example": false + }, + "framework": { + "type": "string", + "description": "Site framework.", + "x-example": "react" + }, + "deploymentId": { + "type": "string", + "description": "Site's active deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "deploymentCreatedAt": { + "type": "string", + "description": "Active deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "deploymentScreenshotLight": { + "type": "string", + "description": "Screenshot of active deployment with light theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "deploymentScreenshotDark": { + "type": "string", + "description": "Screenshot of active deployment with dark theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentId": { + "type": "string", + "description": "Site's latest deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentCreatedAt": { + "type": "string", + "description": "Latest deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentStatus": { + "type": "string", + "description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, + "vars": { + "type": "array", + "description": "Site variables.", + "items": { + "$ref": "#\/components\/schemas\/variable" + }, + "x-example": [] + }, + "timeout": { + "type": "integer", + "description": "Site request timeout in seconds.", + "x-example": 300, + "format": "int32" + }, + "installCommand": { + "type": "string", + "description": "The install command used to install the site dependencies.", + "x-example": "npm install" + }, + "buildCommand": { + "type": "string", + "description": "The build command used to build the site.", + "x-example": "npm run build" + }, + "outputDirectory": { + "type": "string", + "description": "The directory where the site build output is located.", + "x-example": "build" + }, + "installationId": { + "type": "string", + "description": "Site VCS (Version Control System) installation id.", + "x-example": "6m40at4ejk5h2u9s1hboo" + }, + "providerRepositoryId": { + "type": "string", + "description": "VCS (Version Control System) Repository ID", + "x-example": "appwrite" + }, + "providerBranch": { + "type": "string", + "description": "VCS (Version Control System) branch name", + "x-example": "main" + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to site in VCS (Version Control System) repository", + "x-example": "sites\/helloWorld" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is VCS (Version Control System) connection is in silent mode? When in silence mode, no comments will be posted on the repository pull or merge requests", + "x-example": false + }, + "specification": { + "type": "string", + "description": "Machine specification for builds and executions.", + "x-example": "s-1vcpu-512mb" + }, + "buildRuntime": { + "type": "string", + "description": "Site build runtime.", + "x-example": "node-22" + }, + "adapter": { + "type": "string", + "description": "Site framework adapter.", + "x-example": "static" + }, + "fallbackFile": { + "type": "string", + "description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.", + "x-example": "index.html" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "enabled", + "live", + "logging", + "framework", + "deploymentId", + "deploymentCreatedAt", + "deploymentScreenshotLight", + "deploymentScreenshotDark", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", + "vars", + "timeout", + "installCommand", + "buildCommand", + "outputDirectory", + "installationId", + "providerRepositoryId", + "providerBranch", + "providerRootDirectory", + "providerSilentMode", + "specification", + "buildRuntime", + "adapter", + "fallbackFile" + ] + }, + "templateSite": { + "description": "Template Site", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Site Template ID.", + "x-example": "starter" + }, + "name": { + "type": "string", + "description": "Site Template Name.", + "x-example": "Starter site" + }, + "tagline": { + "type": "string", + "description": "Short description of template", + "x-example": "Minimal web app integrating with Appwrite." + }, + "demoUrl": { + "type": "string", + "description": "URL hosting a template demo.", + "x-example": "https:\/\/nextjs-starter.appwrite.network\/" + }, + "screenshotDark": { + "type": "string", + "description": "File URL with preview screenshot in dark theme preference.", + "x-example": "https:\/\/cloud.appwrite.io\/images\/sites\/templates\/template-for-blog-dark.png" + }, + "screenshotLight": { + "type": "string", + "description": "File URL with preview screenshot in light theme preference.", + "x-example": "https:\/\/cloud.appwrite.io\/images\/sites\/templates\/template-for-blog-light.png" + }, + "useCases": { + "type": "array", + "description": "Site use cases.", + "items": { + "type": "string" + }, + "x-example": "Starter" + }, + "frameworks": { + "type": "array", + "description": "List of frameworks that can be used with this template.", + "items": { + "$ref": "#\/components\/schemas\/templateFramework" + }, + "x-example": [] + }, + "vcsProvider": { + "type": "string", + "description": "VCS (Version Control System) Provider.", + "x-example": "github" + }, + "providerRepositoryId": { + "type": "string", + "description": "VCS (Version Control System) Repository ID", + "x-example": "templates" + }, + "providerOwner": { + "type": "string", + "description": "VCS (Version Control System) Owner.", + "x-example": "appwrite" + }, + "providerVersion": { + "type": "string", + "description": "VCS (Version Control System) branch version (tag).", + "x-example": "main" + }, + "variables": { + "type": "array", + "description": "Site variables.", + "items": { + "$ref": "#\/components\/schemas\/templateVariable" + }, + "x-example": [] + } + }, + "required": [ + "key", + "name", + "tagline", + "demoUrl", + "screenshotDark", + "screenshotLight", + "useCases", + "frameworks", + "vcsProvider", + "providerRepositoryId", + "providerOwner", + "providerVersion", + "variables" + ] + }, + "templateFramework": { + "description": "Template Framework", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Parent framework key.", + "x-example": "sveltekit" + }, + "name": { + "type": "string", + "description": "Framework Name.", + "x-example": "SvelteKit" + }, + "installCommand": { + "type": "string", + "description": "The install command used to install the dependencies.", + "x-example": "npm install" + }, + "buildCommand": { + "type": "string", + "description": "The build command used to build the deployment.", + "x-example": "npm run build" + }, + "outputDirectory": { + "type": "string", + "description": "The output directory to store the build output.", + "x-example": ".\/build" + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to site in VCS (Version Control System) repository", + "x-example": ".\/svelte-kit\/starter" + }, + "buildRuntime": { + "type": "string", + "description": "Runtime used during build step of template.", + "x-example": "node-22" + }, + "adapter": { + "type": "string", + "description": "Site framework runtime", + "x-example": "ssr" + }, + "fallbackFile": { + "type": "string", + "description": "Fallback file for SPA. Only relevant for static serve runtime.", + "x-example": "index.html" + } + }, + "required": [ + "key", + "name", + "installCommand", + "buildCommand", + "outputDirectory", + "providerRootDirectory", + "buildRuntime", + "adapter", + "fallbackFile" + ] + }, + "function": { + "description": "Function", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Function ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Function creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Function update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "execute": { + "type": "array", + "description": "Execution permissions.", + "items": { + "type": "string" + }, + "x-example": "users" + }, + "name": { + "type": "string", + "description": "Function name.", + "x-example": "My Function" + }, + "enabled": { + "type": "boolean", + "description": "Function enabled.", + "x-example": false + }, + "live": { + "type": "boolean", + "description": "Is the function deployed with the latest configuration? This is set to false if you've changed an environment variables, entrypoint, commands, or other settings that needs redeploy to be applied. When the value is false, redeploy the function to update it with the latest configuration.", + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", + "x-example": false + }, + "runtime": { + "type": "string", + "description": "Function execution and build runtime.", + "x-example": "python-3.8" + }, + "deploymentId": { + "type": "string", + "description": "Function's active deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "deploymentCreatedAt": { + "type": "string", + "description": "Active deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentId": { + "type": "string", + "description": "Function's latest deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentCreatedAt": { + "type": "string", + "description": "Latest deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentStatus": { + "type": "string", + "description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, + "scopes": { + "type": "array", + "description": "Allowed permission scopes.", + "items": { + "type": "string" + }, + "x-example": "users.read" + }, + "vars": { + "type": "array", + "description": "Function variables.", + "items": { + "$ref": "#\/components\/schemas\/variable" + }, + "x-example": [] + }, + "events": { + "type": "array", + "description": "Function trigger events.", + "items": { + "type": "string" + }, + "x-example": "account.create" + }, + "schedule": { + "type": "string", + "description": "Function execution schedule in CRON format.", + "x-example": "5 4 * * *" + }, + "timeout": { + "type": "integer", + "description": "Function execution timeout in seconds.", + "x-example": 300, + "format": "int32" + }, + "entrypoint": { + "type": "string", + "description": "The entrypoint file used to execute the deployment.", + "x-example": "index.js" + }, + "commands": { + "type": "string", + "description": "The build command used to build the deployment.", + "x-example": "npm install" + }, + "version": { + "type": "string", + "description": "Version of Open Runtimes used for the function.", + "x-example": "v2" + }, + "installationId": { + "type": "string", + "description": "Function VCS (Version Control System) installation id.", + "x-example": "6m40at4ejk5h2u9s1hboo" + }, + "providerRepositoryId": { + "type": "string", + "description": "VCS (Version Control System) Repository ID", + "x-example": "appwrite" + }, + "providerBranch": { + "type": "string", + "description": "VCS (Version Control System) branch name", + "x-example": "main" + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to function in VCS (Version Control System) repository", + "x-example": "functions\/helloWorld" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is VCS (Version Control System) connection is in silent mode? When in silence mode, no comments will be posted on the repository pull or merge requests", + "x-example": false + }, + "specification": { + "type": "string", + "description": "Machine specification for builds and executions.", + "x-example": "s-1vcpu-512mb" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "execute", + "name", + "enabled", + "live", + "logging", + "runtime", + "deploymentId", + "deploymentCreatedAt", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", + "scopes", + "vars", + "events", + "schedule", + "timeout", + "entrypoint", + "commands", + "version", + "installationId", + "providerRepositoryId", + "providerBranch", + "providerRootDirectory", + "providerSilentMode", + "specification" + ] + }, + "templateFunction": { + "description": "Template Function", + "type": "object", + "properties": { + "icon": { + "type": "string", + "description": "Function Template Icon.", + "x-example": "icon-lightning-bolt" + }, + "id": { + "type": "string", + "description": "Function Template ID.", + "x-example": "starter" + }, + "name": { + "type": "string", + "description": "Function Template Name.", + "x-example": "Starter function" + }, + "tagline": { + "type": "string", + "description": "Function Template Tagline.", + "x-example": "A simple function to get started." + }, + "permissions": { + "type": "array", + "description": "Execution permissions.", + "items": { + "type": "string" + }, + "x-example": "any" + }, + "events": { + "type": "array", + "description": "Function trigger events.", + "items": { + "type": "string" + }, + "x-example": "account.create" + }, + "cron": { + "type": "string", + "description": "Function execution schedult in CRON format.", + "x-example": "0 0 * * *" + }, + "timeout": { + "type": "integer", + "description": "Function execution timeout in seconds.", + "x-example": 300, + "format": "int32" + }, + "useCases": { + "type": "array", + "description": "Function use cases.", + "items": { + "type": "string" + }, + "x-example": "Starter" + }, + "runtimes": { + "type": "array", + "description": "List of runtimes that can be used with this template.", + "items": { + "$ref": "#\/components\/schemas\/templateRuntime" + }, + "x-example": [] + }, + "instructions": { + "type": "string", + "description": "Function Template Instructions.", + "x-example": "For documentation and instructions check out <link>." + }, + "vcsProvider": { + "type": "string", + "description": "VCS (Version Control System) Provider.", + "x-example": "github" + }, + "providerRepositoryId": { + "type": "string", + "description": "VCS (Version Control System) Repository ID", + "x-example": "templates" + }, + "providerOwner": { + "type": "string", + "description": "VCS (Version Control System) Owner.", + "x-example": "appwrite" + }, + "providerVersion": { + "type": "string", + "description": "VCS (Version Control System) branch version (tag).", + "x-example": "main" + }, + "variables": { + "type": "array", + "description": "Function variables.", + "items": { + "$ref": "#\/components\/schemas\/templateVariable" + }, + "x-example": [] + }, + "scopes": { + "type": "array", + "description": "Function scopes.", + "items": { + "type": "string" + }, + "x-example": "users.read" + } + }, + "required": [ + "icon", + "id", + "name", + "tagline", + "permissions", + "events", + "cron", + "timeout", + "useCases", + "runtimes", + "instructions", + "vcsProvider", + "providerRepositoryId", + "providerOwner", + "providerVersion", + "variables", + "scopes" + ] + }, + "templateRuntime": { + "description": "Template Runtime", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Runtime Name.", + "x-example": "node-19.0" + }, + "commands": { + "type": "string", + "description": "The build command used to build the deployment.", + "x-example": "npm install" + }, + "entrypoint": { + "type": "string", + "description": "The entrypoint file used to execute the deployment.", + "x-example": "index.js" + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to function in VCS (Version Control System) repository", + "x-example": "node\/starter" + } + }, + "required": [ + "name", + "commands", + "entrypoint", + "providerRootDirectory" + ] + }, + "templateVariable": { + "description": "Template Variable", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Variable Name.", + "x-example": "APPWRITE_DATABASE_ID" + }, + "description": { + "type": "string", + "description": "Variable Description.", + "x-example": "The ID of the Appwrite database that contains the collection to sync." + }, + "value": { + "type": "string", + "description": "Variable Value.", + "x-example": "512" + }, + "secret": { + "type": "boolean", + "description": "Variable secret flag. Secret variables can only be updated or deleted, but never read.", + "x-example": false + }, + "placeholder": { + "type": "string", + "description": "Variable Placeholder.", + "x-example": "64a55...7b912" + }, + "required": { + "type": "boolean", + "description": "Is the variable required?", + "x-example": false + }, + "type": { + "type": "string", + "description": "Variable Type.", + "x-example": "password" + } + }, + "required": [ + "name", + "description", + "value", + "secret", + "placeholder", + "required", + "type" + ] + }, + "installation": { + "description": "Installation", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Function ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Function creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Function update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "provider": { + "type": "string", + "description": "VCS (Version Control System) provider name.", + "x-example": "github" + }, + "organization": { + "type": "string", + "description": "VCS (Version Control System) organization name.", + "x-example": "appwrite" + }, + "providerInstallationId": { + "type": "string", + "description": "VCS (Version Control System) installation ID.", + "x-example": "5322" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "provider", + "organization", + "providerInstallationId" + ] + }, + "providerRepository": { + "description": "ProviderRepository", + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "VCS (Version Control System) repository ID.", + "x-example": "5e5ea5c16897e" + }, + "name": { + "type": "string", + "description": "VCS (Version Control System) repository name.", + "x-example": "appwrite" + }, + "organization": { + "type": "string", + "description": "VCS (Version Control System) organization name", + "x-example": "appwrite" + }, + "provider": { + "type": "string", + "description": "VCS (Version Control System) provider name.", + "x-example": "github" + }, + "private": { + "type": "boolean", + "description": "Is VCS (Version Control System) repository private?", + "x-example": true + }, + "pushedAt": { + "type": "string", + "description": "Last commit date in ISO 8601 format.", + "x-example": "datetime" + } + }, + "required": [ + "id", + "name", + "organization", + "provider", + "private", + "pushedAt" + ] + }, + "providerRepositoryFramework": { + "description": "ProviderRepositoryFramework", + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "VCS (Version Control System) repository ID.", + "x-example": "5e5ea5c16897e" + }, + "name": { + "type": "string", + "description": "VCS (Version Control System) repository name.", + "x-example": "appwrite" + }, + "organization": { + "type": "string", + "description": "VCS (Version Control System) organization name", + "x-example": "appwrite" + }, + "provider": { + "type": "string", + "description": "VCS (Version Control System) provider name.", + "x-example": "github" + }, + "private": { + "type": "boolean", + "description": "Is VCS (Version Control System) repository private?", + "x-example": true + }, + "pushedAt": { + "type": "string", + "description": "Last commit date in ISO 8601 format.", + "x-example": "datetime" + }, + "framework": { + "type": "string", + "description": "Auto-detected framework. Empty if type is not \"framework\".", + "x-example": "nextjs" + } + }, + "required": [ + "id", + "name", + "organization", + "provider", + "private", + "pushedAt", + "framework" + ] + }, + "providerRepositoryRuntime": { + "description": "ProviderRepositoryRuntime", + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "VCS (Version Control System) repository ID.", + "x-example": "5e5ea5c16897e" + }, + "name": { + "type": "string", + "description": "VCS (Version Control System) repository name.", + "x-example": "appwrite" + }, + "organization": { + "type": "string", + "description": "VCS (Version Control System) organization name", + "x-example": "appwrite" + }, + "provider": { + "type": "string", + "description": "VCS (Version Control System) provider name.", + "x-example": "github" + }, + "private": { + "type": "boolean", + "description": "Is VCS (Version Control System) repository private?", + "x-example": true + }, + "pushedAt": { + "type": "string", + "description": "Last commit date in ISO 8601 format.", + "x-example": "datetime" + }, + "runtime": { + "type": "string", + "description": "Auto-detected runtime. Empty if type is not \"runtime\".", + "x-example": "node-22" + } + }, + "required": [ + "id", + "name", + "organization", + "provider", + "private", + "pushedAt", + "runtime" + ] + }, + "detectionFramework": { + "description": "DetectionFramework", + "type": "object", + "properties": { + "framework": { + "type": "string", + "description": "Framework", + "x-example": "nuxt" + }, + "installCommand": { + "type": "string", + "description": "Site Install Command", + "x-example": "npm install" + }, + "buildCommand": { + "type": "string", + "description": "Site Build Command", + "x-example": "npm run build" + }, + "outputDirectory": { + "type": "string", + "description": "Site Output Directory", + "x-example": "dist" + } + }, + "required": [ + "framework", + "installCommand", + "buildCommand", + "outputDirectory" + ] + }, + "detectionRuntime": { + "description": "DetectionRuntime", + "type": "object", + "properties": { + "runtime": { + "type": "string", + "description": "Runtime", + "x-example": "node" + }, + "entrypoint": { + "type": "string", + "description": "Function Entrypoint", + "x-example": "index.js" + }, + "commands": { + "type": "string", + "description": "Function install and build commands", + "x-example": "npm install && npm run build" + } + }, + "required": [ + "runtime", + "entrypoint", + "commands" + ] + }, + "vcsContent": { + "description": "VcsContents", + "type": "object", + "properties": { + "size": { + "type": "integer", + "description": "Content size in bytes. Only files have size, and for directories, 0 is returned.", + "x-example": 1523, + "format": "int32", + "nullable": true + }, + "isDirectory": { + "type": "boolean", + "description": "If a content is a directory. Directories can be used to check nested contents.", + "x-example": true, + "nullable": true + }, + "name": { + "type": "string", + "description": "Name of directory or file.", + "x-example": "Main.java" + } + }, + "required": [ + "name" + ] + }, + "branch": { + "description": "Branch", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Branch Name.", + "x-example": "main" + } + }, + "required": [ + "name" + ] + }, + "runtime": { + "description": "Runtime", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Runtime ID.", + "x-example": "python-3.8" + }, + "key": { + "type": "string", + "description": "Parent runtime key.", + "x-example": "python" + }, + "name": { + "type": "string", + "description": "Runtime Name.", + "x-example": "Python" + }, + "version": { + "type": "string", + "description": "Runtime version.", + "x-example": "3.8" + }, + "base": { + "type": "string", + "description": "Base Docker image used to build the runtime.", + "x-example": "python:3.8-alpine" + }, + "image": { + "type": "string", + "description": "Image name of Docker Hub.", + "x-example": "appwrite\\\/runtime-for-python:3.8" + }, + "logo": { + "type": "string", + "description": "Name of the logo image.", + "x-example": "python.png" + }, + "supports": { + "type": "array", + "description": "List of supported architectures.", + "items": { + "type": "string" + }, + "x-example": "amd64" + } + }, + "required": [ + "$id", + "key", + "name", + "version", + "base", + "image", + "logo", + "supports" + ] + }, + "framework": { + "description": "Framework", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Framework key.", + "x-example": "sveltekit" + }, + "name": { + "type": "string", + "description": "Framework Name.", + "x-example": "SvelteKit" + }, + "buildRuntime": { + "type": "string", + "description": "Default runtime version.", + "x-example": "node-22" + }, + "runtimes": { + "type": "array", + "description": "List of supported runtime versions.", + "items": { + "type": "string" + }, + "x-example": [ + "static-1", + "node-22" + ] + }, + "adapters": { + "type": "array", + "description": "List of supported adapters.", + "items": { + "$ref": "#\/components\/schemas\/frameworkAdapter" + }, + "x-example": [ + { + "key": "static", + "buildRuntime": "node-22", + "buildCommand": "npm run build", + "installCommand": "npm install", + "outputDirectory": ".\/dist" + } + ] + } + }, + "required": [ + "key", + "name", + "buildRuntime", + "runtimes", + "adapters" + ] + }, + "frameworkAdapter": { + "description": "Framework Adapter", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Adapter key.", + "x-example": "static" + }, + "installCommand": { + "type": "string", + "description": "Default command to download dependencies.", + "x-example": "npm install" + }, + "buildCommand": { + "type": "string", + "description": "Default command to build site into output directory.", + "x-example": "npm run build" + }, + "outputDirectory": { + "type": "string", + "description": "Default output directory of build.", + "x-example": ".\/dist" + }, + "fallbackFile": { + "type": "string", + "description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.", + "x-example": "index.html" + } + }, + "required": [ + "key", + "installCommand", + "buildCommand", + "outputDirectory", + "fallbackFile" + ] + }, + "deployment": { + "description": "Deployment", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Deployment update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "type": { + "type": "string", + "description": "Type of deployment.", + "x-example": "vcs" + }, + "resourceId": { + "type": "string", + "description": "Resource ID.", + "x-example": "5e5ea6g16897e" + }, + "resourceType": { + "type": "string", + "description": "Resource type.", + "x-example": "functions" + }, + "entrypoint": { + "type": "string", + "description": "The entrypoint file to use to execute the deployment code.", + "x-example": "index.js" + }, + "sourceSize": { + "type": "integer", + "description": "The code size in bytes.", + "x-example": 128, + "format": "int32" + }, + "buildSize": { + "type": "integer", + "description": "The build output size in bytes.", + "x-example": 128, + "format": "int32" + }, + "totalSize": { + "type": "integer", + "description": "The total size in bytes (source and build output).", + "x-example": 128, + "format": "int32" + }, + "buildId": { + "type": "string", + "description": "The current build ID.", + "x-example": "5e5ea5c16897e" + }, + "activate": { + "type": "boolean", + "description": "Whether the deployment should be automatically activated.", + "x-example": true + }, + "screenshotLight": { + "type": "string", + "description": "Screenshot with light theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "screenshotDark": { + "type": "string", + "description": "Screenshot with dark theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "status": { + "type": "string", + "description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, + "buildLogs": { + "type": "string", + "description": "The build logs.", + "x-example": "Compiling source files..." + }, + "buildDuration": { + "type": "integer", + "description": "The current build time in seconds.", + "x-example": 128, + "format": "int32" + }, + "providerRepositoryName": { + "type": "string", + "description": "The name of the vcs provider repository", + "x-example": "database" + }, + "providerRepositoryOwner": { + "type": "string", + "description": "The name of the vcs provider repository owner", + "x-example": "utopia" + }, + "providerRepositoryUrl": { + "type": "string", + "description": "The url of the vcs provider repository", + "x-example": "https:\/\/github.com\/vermakhushboo\/g4-node-function" + }, + "providerBranch": { + "type": "string", + "description": "The branch of the vcs repository", + "x-example": "0.7.x" + }, + "providerCommitHash": { + "type": "string", + "description": "The commit hash of the vcs commit", + "x-example": "7c3f25d" + }, + "providerCommitAuthorUrl": { + "type": "string", + "description": "The url of vcs commit author", + "x-example": "https:\/\/github.com\/vermakhushboo" + }, + "providerCommitAuthor": { + "type": "string", + "description": "The name of vcs commit author", + "x-example": "Khushboo Verma" + }, + "providerCommitMessage": { + "type": "string", + "description": "The commit message", + "x-example": "Update index.js" + }, + "providerCommitUrl": { + "type": "string", + "description": "The url of the vcs commit", + "x-example": "https:\/\/github.com\/vermakhushboo\/g4-node-function\/commit\/60c0416257a9cbcdd96b2d370c38d8f8d150ccfb" + }, + "providerBranchUrl": { + "type": "string", + "description": "The branch of the vcs repository", + "x-example": "https:\/\/github.com\/vermakhushboo\/appwrite\/tree\/0.7.x" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "type", + "resourceId", + "resourceType", + "entrypoint", + "sourceSize", + "buildSize", + "totalSize", + "buildId", + "activate", + "screenshotLight", + "screenshotDark", + "status", + "buildLogs", + "buildDuration", + "providerRepositoryName", + "providerRepositoryOwner", + "providerRepositoryUrl", + "providerBranch", + "providerCommitHash", + "providerCommitAuthorUrl", + "providerCommitAuthor", + "providerCommitMessage", + "providerCommitUrl", + "providerBranchUrl" + ] + }, + "execution": { + "description": "Execution", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Execution ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Execution creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Execution upate date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Execution roles.", + "items": { + "type": "string" + }, + "x-example": [ + "any" + ] + }, + "functionId": { + "type": "string", + "description": "Function ID.", + "x-example": "5e5ea6g16897e" + }, + "trigger": { + "type": "string", + "description": "The trigger that caused the function to execute. Possible values can be: `http`, `schedule`, or `event`.", + "x-example": "http" + }, + "status": { + "type": "string", + "description": "The status of the function execution. Possible values can be: `waiting`, `processing`, `completed`, or `failed`.", + "x-example": "processing" + }, + "requestMethod": { + "type": "string", + "description": "HTTP request method type.", + "x-example": "GET" + }, + "requestPath": { + "type": "string", + "description": "HTTP request path and query.", + "x-example": "\/articles?id=5" + }, + "requestHeaders": { + "type": "array", + "description": "HTTP response headers as a key-value object. This will return only whitelisted headers. All headers are returned if execution is created as synchronous.", + "items": { + "$ref": "#\/components\/schemas\/headers" + }, + "x-example": [ + { + "Content-Type": "application\/json" + } + ] + }, + "responseStatusCode": { + "type": "integer", + "description": "HTTP response status code.", + "x-example": 200, + "format": "int32" + }, + "responseBody": { + "type": "string", + "description": "HTTP response body. This will return empty unless execution is created as synchronous.", + "x-example": "" + }, + "responseHeaders": { + "type": "array", + "description": "HTTP response headers as a key-value object. This will return only whitelisted headers. All headers are returned if execution is created as synchronous.", + "items": { + "$ref": "#\/components\/schemas\/headers" + }, + "x-example": [ + { + "Content-Type": "application\/json" + } + ] + }, + "logs": { + "type": "string", + "description": "Function logs. Includes the last 4,000 characters. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.", + "x-example": "" + }, + "errors": { + "type": "string", + "description": "Function errors. Includes the last 4,000 characters. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.", + "x-example": "" + }, + "duration": { + "type": "number", + "description": "Resource(function\/site) execution duration in seconds.", + "x-example": 0.4, + "format": "double" + }, + "scheduledAt": { + "type": "string", + "description": "The scheduled time for execution. If left empty, execution will be queued immediately.", + "x-example": "2020-10-15T06:38:00.000+00:00", + "nullable": true + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "$permissions", + "functionId", + "trigger", + "status", + "requestMethod", + "requestPath", + "requestHeaders", + "responseStatusCode", + "responseBody", + "responseHeaders", + "logs", + "errors", + "duration" + ] + }, + "project": { + "description": "Project", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Project ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Project creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Project update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Project name.", + "x-example": "New Project" + }, + "description": { + "type": "string", + "description": "Project description.", + "x-example": "This is a new project." + }, + "teamId": { + "type": "string", + "description": "Project team ID.", + "x-example": "1592981250" + }, + "logo": { + "type": "string", + "description": "Project logo file ID.", + "x-example": "5f5c451b403cb" + }, + "url": { + "type": "string", + "description": "Project website URL.", + "x-example": "5f5c451b403cb" + }, + "legalName": { + "type": "string", + "description": "Company legal name.", + "x-example": "Company LTD." + }, + "legalCountry": { + "type": "string", + "description": "Country code in [ISO 3166-1](http:\/\/en.wikipedia.org\/wiki\/ISO_3166-1) two-character format.", + "x-example": "US" + }, + "legalState": { + "type": "string", + "description": "State name.", + "x-example": "New York" + }, + "legalCity": { + "type": "string", + "description": "City name.", + "x-example": "New York City." + }, + "legalAddress": { + "type": "string", + "description": "Company Address.", + "x-example": "620 Eighth Avenue, New York, NY 10018" + }, + "legalTaxId": { + "type": "string", + "description": "Company Tax ID.", + "x-example": "131102020" + }, + "authDuration": { + "type": "integer", + "description": "Session duration in seconds.", + "x-example": 60, + "format": "int32" + }, + "authLimit": { + "type": "integer", + "description": "Max users allowed. 0 is unlimited.", + "x-example": 100, + "format": "int32" + }, + "authSessionsLimit": { + "type": "integer", + "description": "Max sessions allowed per user. 100 maximum.", + "x-example": 10, + "format": "int32" + }, + "authPasswordHistory": { + "type": "integer", + "description": "Max allowed passwords in the history list per user. Max passwords limit allowed in history is 20. Use 0 for disabling password history.", + "x-example": 5, + "format": "int32" + }, + "authPasswordDictionary": { + "type": "boolean", + "description": "Whether or not to check user's password against most commonly used passwords.", + "x-example": true + }, + "authPersonalDataCheck": { + "type": "boolean", + "description": "Whether or not to check the user password for similarity with their personal data.", + "x-example": true + }, + "authMockNumbers": { + "type": "array", + "description": "An array of mock numbers and their corresponding verification codes (OTPs).", + "items": { + "$ref": "#\/components\/schemas\/mockNumber" + }, + "x-example": [ + {} + ] + }, + "authSessionAlerts": { + "type": "boolean", + "description": "Whether or not to send session alert emails to users.", + "x-example": true + }, + "authMembershipsUserName": { + "type": "boolean", + "description": "Whether or not to show user names in the teams membership response.", + "x-example": true + }, + "authMembershipsUserEmail": { + "type": "boolean", + "description": "Whether or not to show user emails in the teams membership response.", + "x-example": true + }, + "authMembershipsMfa": { + "type": "boolean", + "description": "Whether or not to show user MFA status in the teams membership response.", + "x-example": true + }, + "oAuthProviders": { + "type": "array", + "description": "List of Auth Providers.", + "items": { + "$ref": "#\/components\/schemas\/authProvider" + }, + "x-example": [ + {} + ] + }, + "platforms": { + "type": "array", + "description": "List of Platforms.", + "items": { + "$ref": "#\/components\/schemas\/platform" + }, + "x-example": {} + }, + "webhooks": { + "type": "array", + "description": "List of Webhooks.", + "items": { + "$ref": "#\/components\/schemas\/webhook" + }, + "x-example": {} + }, + "keys": { + "type": "array", + "description": "List of API Keys.", + "items": { + "$ref": "#\/components\/schemas\/key" + }, + "x-example": {} + }, + "devKeys": { + "type": "array", + "description": "List of dev keys.", + "items": { + "$ref": "#\/components\/schemas\/devKey" + }, + "x-example": {} + }, + "smtpEnabled": { + "type": "boolean", + "description": "Status for custom SMTP", + "x-example": false + }, + "smtpSenderName": { + "type": "string", + "description": "SMTP sender name", + "x-example": "John Appwrite" + }, + "smtpSenderEmail": { + "type": "string", + "description": "SMTP sender email", + "x-example": "john@appwrite.io" + }, + "smtpReplyTo": { + "type": "string", + "description": "SMTP reply to email", + "x-example": "support@appwrite.io" + }, + "smtpHost": { + "type": "string", + "description": "SMTP server host name", + "x-example": "mail.appwrite.io" + }, + "smtpPort": { + "type": "integer", + "description": "SMTP server port", + "x-example": 25, + "format": "int32" + }, + "smtpUsername": { + "type": "string", + "description": "SMTP server username", + "x-example": "emailuser" + }, + "smtpPassword": { + "type": "string", + "description": "SMTP server password", + "x-example": "securepassword" + }, + "smtpSecure": { + "type": "string", + "description": "SMTP server secure protocol", + "x-example": "tls" + }, + "pingCount": { + "type": "integer", + "description": "Number of times the ping was received for this project.", + "x-example": 1, + "format": "int32" + }, + "pingedAt": { + "type": "string", + "description": "Last ping datetime in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "authEmailPassword": { + "type": "boolean", + "description": "Email\/Password auth method status", + "x-example": true + }, + "authUsersAuthMagicURL": { + "type": "boolean", + "description": "Magic URL auth method status", + "x-example": true + }, + "authEmailOtp": { + "type": "boolean", + "description": "Email (OTP) auth method status", + "x-example": true + }, + "authAnonymous": { + "type": "boolean", + "description": "Anonymous auth method status", + "x-example": true + }, + "authInvites": { + "type": "boolean", + "description": "Invites auth method status", + "x-example": true + }, + "authJWT": { + "type": "boolean", + "description": "JWT auth method status", + "x-example": true + }, + "authPhone": { + "type": "boolean", + "description": "Phone auth method status", + "x-example": true + }, + "serviceStatusForAccount": { + "type": "boolean", + "description": "Account service status", + "x-example": true + }, + "serviceStatusForAvatars": { + "type": "boolean", + "description": "Avatars service status", + "x-example": true + }, + "serviceStatusForDatabases": { + "type": "boolean", + "description": "Databases service status", + "x-example": true + }, + "serviceStatusForLocale": { + "type": "boolean", + "description": "Locale service status", + "x-example": true + }, + "serviceStatusForHealth": { + "type": "boolean", + "description": "Health service status", + "x-example": true + }, + "serviceStatusForStorage": { + "type": "boolean", + "description": "Storage service status", + "x-example": true + }, + "serviceStatusForTeams": { + "type": "boolean", + "description": "Teams service status", + "x-example": true + }, + "serviceStatusForUsers": { + "type": "boolean", + "description": "Users service status", + "x-example": true + }, + "serviceStatusForSites": { + "type": "boolean", + "description": "Sites service status", + "x-example": true + }, + "serviceStatusForFunctions": { + "type": "boolean", + "description": "Functions service status", + "x-example": true + }, + "serviceStatusForGraphql": { + "type": "boolean", + "description": "GraphQL service status", + "x-example": true + }, + "serviceStatusForMessaging": { + "type": "boolean", + "description": "Messaging service status", + "x-example": true + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "description", + "teamId", + "logo", + "url", + "legalName", + "legalCountry", + "legalState", + "legalCity", + "legalAddress", + "legalTaxId", + "authDuration", + "authLimit", + "authSessionsLimit", + "authPasswordHistory", + "authPasswordDictionary", + "authPersonalDataCheck", + "authMockNumbers", + "authSessionAlerts", + "authMembershipsUserName", + "authMembershipsUserEmail", + "authMembershipsMfa", + "oAuthProviders", + "platforms", + "webhooks", + "keys", + "devKeys", + "smtpEnabled", + "smtpSenderName", + "smtpSenderEmail", + "smtpReplyTo", + "smtpHost", + "smtpPort", + "smtpUsername", + "smtpPassword", + "smtpSecure", + "pingCount", + "pingedAt", + "authEmailPassword", + "authUsersAuthMagicURL", + "authEmailOtp", + "authAnonymous", + "authInvites", + "authJWT", + "authPhone", + "serviceStatusForAccount", + "serviceStatusForAvatars", + "serviceStatusForDatabases", + "serviceStatusForLocale", + "serviceStatusForHealth", + "serviceStatusForStorage", + "serviceStatusForTeams", + "serviceStatusForUsers", + "serviceStatusForSites", + "serviceStatusForFunctions", + "serviceStatusForGraphql", + "serviceStatusForMessaging" + ] + }, + "webhook": { + "description": "Webhook", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Webhook ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Webhook creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Webhook update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Webhook name.", + "x-example": "My Webhook" + }, + "url": { + "type": "string", + "description": "Webhook URL endpoint.", + "x-example": "https:\/\/example.com\/webhook" + }, + "events": { + "type": "array", + "description": "Webhook trigger events.", + "items": { + "type": "string" + }, + "x-example": "database.collections.update" + }, + "security": { + "type": "boolean", + "description": "Indicated if SSL \/ TLS Certificate verification is enabled.", + "x-example": true + }, + "httpUser": { + "type": "string", + "description": "HTTP basic authentication username.", + "x-example": "username" + }, + "httpPass": { + "type": "string", + "description": "HTTP basic authentication password.", + "x-example": "password" + }, + "signatureKey": { + "type": "string", + "description": "Signature key which can be used to validated incoming", + "x-example": "ad3d581ca230e2b7059c545e5a" + }, + "enabled": { + "type": "boolean", + "description": "Indicates if this webhook is enabled.", + "x-example": true + }, + "logs": { + "type": "string", + "description": "Webhook error logs from the most recent failure.", + "x-example": "Failed to connect to remote server." + }, + "attempts": { + "type": "integer", + "description": "Number of consecutive failed webhook attempts.", + "x-example": 10, + "format": "int32" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "url", + "events", + "security", + "httpUser", + "httpPass", + "signatureKey", + "enabled", + "logs", + "attempts" + ] + }, + "key": { + "description": "Key", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Key ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Key creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Key update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Key name.", + "x-example": "My API Key" + }, + "expire": { + "type": "string", + "description": "Key expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "scopes": { + "type": "array", + "description": "Allowed permission scopes.", + "items": { + "type": "string" + }, + "x-example": "users.read" + }, + "secret": { + "type": "string", + "description": "Secret key.", + "x-example": "919c2d18fb5d4...a2ae413da83346ad2" + }, + "accessedAt": { + "type": "string", + "description": "Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "sdks": { + "type": "array", + "description": "List of SDK user agents that used this key.", + "items": { + "type": "string" + }, + "x-example": "appwrite:flutter" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "expire", + "scopes", + "secret", + "accessedAt", + "sdks" + ] + }, + "devKey": { + "description": "DevKey", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Key ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Key creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Key update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Key name.", + "x-example": "Dev API Key" + }, + "expire": { + "type": "string", + "description": "Key expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "secret": { + "type": "string", + "description": "Secret key.", + "x-example": "919c2d18fb5d4...a2ae413da83346ad2" + }, + "accessedAt": { + "type": "string", + "description": "Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "sdks": { + "type": "array", + "description": "List of SDK user agents that used this key.", + "items": { + "type": "string" + }, + "x-example": "appwrite:flutter" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "expire", + "secret", + "accessedAt", + "sdks" + ] + }, + "mockNumber": { + "description": "Mock Number", + "type": "object", + "properties": { + "phone": { + "type": "string", + "description": "Mock phone number for testing phone authentication. Useful for testing phone authentication without sending an SMS.", + "x-example": "+1612842323" + }, + "otp": { + "type": "string", + "description": "Mock OTP for the number. ", + "x-example": "123456" + } + }, + "required": [ + "phone", + "otp" + ] + }, + "authProvider": { + "description": "AuthProvider", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Auth Provider.", + "x-example": "github" + }, + "name": { + "type": "string", + "description": "Auth Provider name.", + "x-example": "GitHub" + }, + "appId": { + "type": "string", + "description": "OAuth 2.0 application ID.", + "x-example": "259125845563242502" + }, + "secret": { + "type": "string", + "description": "OAuth 2.0 application secret. Might be JSON string if provider requires extra configuration.", + "x-example": "Bpw_g9c2TGXxfgLshDbSaL8tsCcqgczQ" + }, + "enabled": { + "type": "boolean", + "description": "Auth Provider is active and can be used to create session.", + "x-example": "" + } + }, + "required": [ + "key", + "name", + "appId", + "secret", + "enabled" + ] + }, + "platform": { + "description": "Platform", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Platform ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Platform creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Platform update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Platform name.", + "x-example": "My Web App" + }, + "type": { + "type": "string", + "description": "Platform type. Possible values are: web, flutter-web, flutter-ios, flutter-android, ios, android, and unity.", + "x-example": "web" + }, + "key": { + "type": "string", + "description": "Platform Key. iOS bundle ID or Android package name. Empty string for other platforms.", + "x-example": "com.company.appname" + }, + "store": { + "type": "string", + "description": "App store or Google Play store ID.", + "x-example": "" + }, + "hostname": { + "type": "string", + "description": "Web app hostname. Empty string for other platforms.", + "x-example": true + }, + "httpUser": { + "type": "string", + "description": "HTTP basic authentication username.", + "x-example": "username" + }, + "httpPass": { + "type": "string", + "description": "HTTP basic authentication password.", + "x-example": "password" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "type", + "key", + "store", + "hostname", + "httpUser", + "httpPass" + ] + }, + "variable": { + "description": "Variable", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Variable ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Variable creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Variable creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "key": { + "type": "string", + "description": "Variable key.", + "x-example": "API_KEY" + }, + "value": { + "type": "string", + "description": "Variable value.", + "x-example": "myPa$$word1" + }, + "secret": { + "type": "boolean", + "description": "Variable secret flag. Secret variables can only be updated or deleted, but never read.", + "x-example": false + }, + "resourceType": { + "type": "string", + "description": "Service to which the variable belongs. Possible values are \"project\", \"function\"", + "x-example": "function" + }, + "resourceId": { + "type": "string", + "description": "ID of resource to which the variable belongs. If resourceType is \"project\", it is empty. If resourceType is \"function\", it is ID of the function.", + "x-example": "myAwesomeFunction" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "key", + "value", + "secret", + "resourceType", + "resourceId" + ] + }, + "country": { + "description": "Country", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + }, + "code": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + } + }, + "required": [ + "name", + "code" + ] + }, + "continent": { + "description": "Continent", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Continent name.", + "x-example": "Europe" + }, + "code": { + "type": "string", + "description": "Continent two letter code.", + "x-example": "EU" + } + }, + "required": [ + "name", + "code" + ] + }, + "language": { + "description": "Language", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Language name.", + "x-example": "Italian" + }, + "code": { + "type": "string", + "description": "Language two-character ISO 639-1 codes.", + "x-example": "it" + }, + "nativeName": { + "type": "string", + "description": "Language native name.", + "x-example": "Italiano" + } + }, + "required": [ + "name", + "code", + "nativeName" + ] + }, + "currency": { + "description": "Currency", + "type": "object", + "properties": { + "symbol": { + "type": "string", + "description": "Currency symbol.", + "x-example": "$" + }, + "name": { + "type": "string", + "description": "Currency name.", + "x-example": "US dollar" + }, + "symbolNative": { + "type": "string", + "description": "Currency native symbol.", + "x-example": "$" + }, + "decimalDigits": { + "type": "integer", + "description": "Number of decimal digits.", + "x-example": 2, + "format": "int32" + }, + "rounding": { + "type": "number", + "description": "Currency digit rounding.", + "x-example": 0, + "format": "double" + }, + "code": { + "type": "string", + "description": "Currency code in [ISO 4217-1](http:\/\/en.wikipedia.org\/wiki\/ISO_4217) three-character format.", + "x-example": "USD" + }, + "namePlural": { + "type": "string", + "description": "Currency plural name", + "x-example": "US dollars" + } + }, + "required": [ + "symbol", + "name", + "symbolNative", + "decimalDigits", + "rounding", + "code", + "namePlural" + ] + }, + "phone": { + "description": "Phone", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Phone code.", + "x-example": "+1" + }, + "countryCode": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + }, + "countryName": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + } + }, + "required": [ + "code", + "countryCode", + "countryName" + ] + }, + "healthAntivirus": { + "description": "Health Antivirus", + "type": "object", + "properties": { + "version": { + "type": "string", + "description": "Antivirus version.", + "x-example": "1.0.0" + }, + "status": { + "type": "string", + "description": "Antivirus status. Possible values can are: `disabled`, `offline`, `online`", + "x-example": "online" + } + }, + "required": [ + "version", + "status" + ] + }, + "healthQueue": { + "description": "Health Queue", + "type": "object", + "properties": { + "size": { + "type": "integer", + "description": "Amount of actions in the queue.", + "x-example": 8, + "format": "int32" + } + }, + "required": [ + "size" + ] + }, + "healthStatus": { + "description": "Health Status", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the service.", + "x-example": "database" + }, + "ping": { + "type": "integer", + "description": "Duration in milliseconds how long the health check took.", + "x-example": 128, + "format": "int32" + }, + "status": { + "type": "string", + "description": "Service status. Possible values can are: `pass`, `fail`", + "x-example": "pass" + } + }, + "required": [ + "name", + "ping", + "status" + ] + }, + "healthCertificate": { + "description": "Health Certificate", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Certificate name", + "x-example": "\/CN=www.google.com" + }, + "subjectSN": { + "type": "string", + "description": "Subject SN", + "x-example": "" + }, + "issuerOrganisation": { + "type": "string", + "description": "Issuer organisation", + "x-example": "" + }, + "validFrom": { + "type": "string", + "description": "Valid from", + "x-example": "1704200998" + }, + "validTo": { + "type": "string", + "description": "Valid to", + "x-example": "1711458597" + }, + "signatureTypeSN": { + "type": "string", + "description": "Signature type SN", + "x-example": "RSA-SHA256" + } + }, + "required": [ + "name", + "subjectSN", + "issuerOrganisation", + "validFrom", + "validTo", + "signatureTypeSN" + ] + }, + "healthTime": { + "description": "Health Time", + "type": "object", + "properties": { + "remoteTime": { + "type": "integer", + "description": "Current unix timestamp on trustful remote server.", + "x-example": 1639490751, + "format": "int32" + }, + "localTime": { + "type": "integer", + "description": "Current unix timestamp of local server where Appwrite runs.", + "x-example": 1639490844, + "format": "int32" + }, + "diff": { + "type": "integer", + "description": "Difference of unix remote and local timestamps in milliseconds.", + "x-example": 93, + "format": "int32" + } + }, + "required": [ + "remoteTime", + "localTime", + "diff" + ] + }, + "metric": { + "description": "Metric", + "type": "object", + "properties": { + "value": { + "type": "integer", + "description": "The value of this metric at the timestamp.", + "x-example": 1, + "format": "int32" + }, + "date": { + "type": "string", + "description": "The date at which this metric was aggregated in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "value", + "date" + ] + }, + "metricBreakdown": { + "description": "Metric Breakdown", + "type": "object", + "properties": { + "resourceId": { + "type": "string", + "description": "Resource ID.", + "x-example": "5e5ea5c16897e", + "nullable": true + }, + "name": { + "type": "string", + "description": "Resource name.", + "x-example": "Documents" + }, + "value": { + "type": "integer", + "description": "The value of this metric at the timestamp.", + "x-example": 1, + "format": "int32" + }, + "estimate": { + "type": "number", + "description": "The estimated value of this metric at the end of the period.", + "x-example": 1, + "format": "double", + "nullable": true + } + }, + "required": [ + "name", + "value" + ] + }, + "usageDatabases": { + "description": "UsageDatabases", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "databasesTotal": { + "type": "integer", + "description": "Total aggregated number of databases.", + "x-example": 0, + "format": "int32" + }, + "collectionsTotal": { + "type": "integer", + "description": "Total aggregated number of collections.", + "x-example": 0, + "format": "int32" + }, + "documentsTotal": { + "type": "integer", + "description": "Total aggregated number of documents.", + "x-example": 0, + "format": "int32" + }, + "storageTotal": { + "type": "integer", + "description": "Total aggregated number of total databases storage in bytes.", + "x-example": 0, + "format": "int32" + }, + "databasesReadsTotal": { + "type": "integer", + "description": "Total number of databases reads.", + "x-example": 0, + "format": "int32" + }, + "databasesWritesTotal": { + "type": "integer", + "description": "Total number of databases writes.", + "x-example": 0, + "format": "int32" + }, + "databases": { + "type": "array", + "description": "Aggregated number of databases per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "collections": { + "type": "array", + "description": "Aggregated number of collections per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "documents": { + "type": "array", + "description": "Aggregated number of documents per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "storage": { + "type": "array", + "description": "An array of the aggregated number of databases storage in bytes per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "databasesReads": { + "type": "array", + "description": "An array of aggregated number of database reads.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "databasesWrites": { + "type": "array", + "description": "An array of aggregated number of database writes.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "databasesTotal", + "collectionsTotal", + "documentsTotal", + "storageTotal", + "databasesReadsTotal", + "databasesWritesTotal", + "databases", + "collections", + "documents", + "storage", + "databasesReads", + "databasesWrites" + ] + }, + "usageDatabase": { + "description": "UsageDatabase", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "collectionsTotal": { + "type": "integer", + "description": "Total aggregated number of collections.", + "x-example": 0, + "format": "int32" + }, + "documentsTotal": { + "type": "integer", + "description": "Total aggregated number of documents.", + "x-example": 0, + "format": "int32" + }, + "storageTotal": { + "type": "integer", + "description": "Total aggregated number of total storage used in bytes.", + "x-example": 0, + "format": "int32" + }, + "databaseReadsTotal": { + "type": "integer", + "description": "Total number of databases reads.", + "x-example": 0, + "format": "int32" + }, + "databaseWritesTotal": { + "type": "integer", + "description": "Total number of databases writes.", + "x-example": 0, + "format": "int32" + }, + "collections": { + "type": "array", + "description": "Aggregated number of collections per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "documents": { + "type": "array", + "description": "Aggregated number of documents per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "storage": { + "type": "array", + "description": "Aggregated storage used in bytes per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "databaseReads": { + "type": "array", + "description": "An array of aggregated number of database reads.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "databaseWrites": { + "type": "array", + "description": "An array of aggregated number of database writes.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "collectionsTotal", + "documentsTotal", + "storageTotal", + "databaseReadsTotal", + "databaseWritesTotal", + "collections", + "documents", + "storage", + "databaseReads", + "databaseWrites" + ] + }, + "usageCollection": { + "description": "UsageCollection", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "documentsTotal": { + "type": "integer", + "description": "Total aggregated number of of documents.", + "x-example": 0, + "format": "int32" + }, + "documents": { + "type": "array", + "description": "Aggregated number of documents per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "documentsTotal", + "documents" + ] + }, + "usageUsers": { + "description": "UsageUsers", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "usersTotal": { + "type": "integer", + "description": "Total aggregated number of statistics of users.", + "x-example": 0, + "format": "int32" + }, + "sessionsTotal": { + "type": "integer", + "description": "Total aggregated number of active sessions.", + "x-example": 0, + "format": "int32" + }, + "users": { + "type": "array", + "description": "Aggregated number of users per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "sessions": { + "type": "array", + "description": "Aggregated number of active sessions per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "usersTotal", + "sessionsTotal", + "users", + "sessions" + ] + }, + "usageStorage": { + "description": "StorageUsage", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "bucketsTotal": { + "type": "integer", + "description": "Total aggregated number of buckets", + "x-example": 0, + "format": "int32" + }, + "filesTotal": { + "type": "integer", + "description": "Total aggregated number of files.", + "x-example": 0, + "format": "int32" + }, + "filesStorageTotal": { + "type": "integer", + "description": "Total aggregated number of files storage (in bytes).", + "x-example": 0, + "format": "int32" + }, + "buckets": { + "type": "array", + "description": "Aggregated number of buckets per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "files": { + "type": "array", + "description": "Aggregated number of files per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "storage": { + "type": "array", + "description": "Aggregated number of files storage (in bytes) per period .", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "bucketsTotal", + "filesTotal", + "filesStorageTotal", + "buckets", + "files", + "storage" + ] + }, + "usageBuckets": { + "description": "UsageBuckets", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "filesTotal": { + "type": "integer", + "description": "Total aggregated number of bucket files.", + "x-example": 0, + "format": "int32" + }, + "filesStorageTotal": { + "type": "integer", + "description": "Total aggregated number of bucket files storage (in bytes).", + "x-example": 0, + "format": "int32" + }, + "files": { + "type": "array", + "description": "Aggregated number of bucket files per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "storage": { + "type": "array", + "description": "Aggregated number of bucket storage files (in bytes) per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "imageTransformations": { + "type": "array", + "description": "Aggregated number of files transformations per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "imageTransformationsTotal": { + "type": "integer", + "description": "Total aggregated number of files transformations.", + "x-example": 0, + "format": "int32" + } + }, + "required": [ + "range", + "filesTotal", + "filesStorageTotal", + "files", + "storage", + "imageTransformations", + "imageTransformationsTotal" + ] + }, + "usageFunctions": { + "description": "UsageFunctions", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "functionsTotal": { + "type": "integer", + "description": "Total aggregated number of functions.", + "x-example": 0, + "format": "int32" + }, + "deploymentsTotal": { + "type": "integer", + "description": "Total aggregated number of functions deployments.", + "x-example": 0, + "format": "int32" + }, + "deploymentsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of functions deployment storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTotal": { + "type": "integer", + "description": "Total aggregated number of functions build.", + "x-example": 0, + "format": "int32" + }, + "buildsStorageTotal": { + "type": "integer", + "description": "total aggregated sum of functions build storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of functions build compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of functions build mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "executionsTotal": { + "type": "integer", + "description": "Total aggregated number of functions execution.", + "x-example": 0, + "format": "int32" + }, + "executionsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of functions execution compute time.", + "x-example": 0, + "format": "int32" + }, + "executionsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of functions execution mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "functions": { + "type": "array", + "description": "Aggregated number of functions per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": 0 + }, + "deployments": { + "type": "array", + "description": "Aggregated number of functions deployment per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "deploymentsStorage": { + "type": "array", + "description": "Aggregated number of functions deployment storage per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsSuccessTotal": { + "type": "integer", + "description": "Total aggregated number of successful function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsFailedTotal": { + "type": "integer", + "description": "Total aggregated number of failed function builds.", + "x-example": 0, + "format": "int32" + }, + "builds": { + "type": "array", + "description": "Aggregated number of functions build per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsStorage": { + "type": "array", + "description": "Aggregated sum of functions build storage per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsTime": { + "type": "array", + "description": "Aggregated sum of functions build compute time per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsMbSeconds": { + "type": "array", + "description": "Aggregated sum of functions build mbSeconds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executions": { + "type": "array", + "description": "Aggregated number of functions execution per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executionsTime": { + "type": "array", + "description": "Aggregated number of functions execution compute time per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executionsMbSeconds": { + "type": "array", + "description": "Aggregated number of functions mbSeconds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsSuccess": { + "type": "array", + "description": "Aggregated number of successful function builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsFailed": { + "type": "array", + "description": "Aggregated number of failed function builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "functionsTotal", + "deploymentsTotal", + "deploymentsStorageTotal", + "buildsTotal", + "buildsStorageTotal", + "buildsTimeTotal", + "buildsMbSecondsTotal", + "executionsTotal", + "executionsTimeTotal", + "executionsMbSecondsTotal", + "functions", + "deployments", + "deploymentsStorage", + "buildsSuccessTotal", + "buildsFailedTotal", + "builds", + "buildsStorage", + "buildsTime", + "buildsMbSeconds", + "executions", + "executionsTime", + "executionsMbSeconds", + "buildsSuccess", + "buildsFailed" + ] + }, + "usageFunction": { + "description": "UsageFunction", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "The time range of the usage stats.", + "x-example": "30d" + }, + "deploymentsTotal": { + "type": "integer", + "description": "Total aggregated number of function deployments.", + "x-example": 0, + "format": "int32" + }, + "deploymentsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of function deployments storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTotal": { + "type": "integer", + "description": "Total aggregated number of function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsSuccessTotal": { + "type": "integer", + "description": "Total aggregated number of successful function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsFailedTotal": { + "type": "integer", + "description": "Total aggregated number of failed function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsStorageTotal": { + "type": "integer", + "description": "total aggregated sum of function builds storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of function builds compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeAverage": { + "type": "integer", + "description": "Average builds compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of function builds mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "executionsTotal": { + "type": "integer", + "description": "Total aggregated number of function executions.", + "x-example": 0, + "format": "int32" + }, + "executionsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of function executions compute time.", + "x-example": 0, + "format": "int32" + }, + "executionsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of function executions mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "deployments": { + "type": "array", + "description": "Aggregated number of function deployments per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "deploymentsStorage": { + "type": "array", + "description": "Aggregated number of function deployments storage per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "builds": { + "type": "array", + "description": "Aggregated number of function builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsStorage": { + "type": "array", + "description": "Aggregated sum of function builds storage per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsTime": { + "type": "array", + "description": "Aggregated sum of function builds compute time per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsMbSeconds": { + "type": "array", + "description": "Aggregated number of function builds mbSeconds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executions": { + "type": "array", + "description": "Aggregated number of function executions per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executionsTime": { + "type": "array", + "description": "Aggregated number of function executions compute time per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executionsMbSeconds": { + "type": "array", + "description": "Aggregated number of function mbSeconds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsSuccess": { + "type": "array", + "description": "Aggregated number of successful builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsFailed": { + "type": "array", + "description": "Aggregated number of failed builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "deploymentsTotal", + "deploymentsStorageTotal", + "buildsTotal", + "buildsSuccessTotal", + "buildsFailedTotal", + "buildsStorageTotal", + "buildsTimeTotal", + "buildsTimeAverage", + "buildsMbSecondsTotal", + "executionsTotal", + "executionsTimeTotal", + "executionsMbSecondsTotal", + "deployments", + "deploymentsStorage", + "builds", + "buildsStorage", + "buildsTime", + "buildsMbSeconds", + "executions", + "executionsTime", + "executionsMbSeconds", + "buildsSuccess", + "buildsFailed" + ] + }, + "usageSites": { + "description": "UsageSites", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "deploymentsTotal": { + "type": "integer", + "description": "Total aggregated number of functions deployments.", + "x-example": 0, + "format": "int32" + }, + "deploymentsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of functions deployment storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTotal": { + "type": "integer", + "description": "Total aggregated number of functions build.", + "x-example": 0, + "format": "int32" + }, + "buildsStorageTotal": { + "type": "integer", + "description": "total aggregated sum of functions build storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of functions build compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of functions build mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "executionsTotal": { + "type": "integer", + "description": "Total aggregated number of functions execution.", + "x-example": 0, + "format": "int32" + }, + "executionsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of functions execution compute time.", + "x-example": 0, + "format": "int32" + }, + "executionsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of functions execution mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "deployments": { + "type": "array", + "description": "Aggregated number of functions deployment per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "deploymentsStorage": { + "type": "array", + "description": "Aggregated number of functions deployment storage per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsSuccessTotal": { + "type": "integer", + "description": "Total aggregated number of successful function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsFailedTotal": { + "type": "integer", + "description": "Total aggregated number of failed function builds.", + "x-example": 0, + "format": "int32" + }, + "builds": { + "type": "array", + "description": "Aggregated number of functions build per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsStorage": { + "type": "array", + "description": "Aggregated sum of functions build storage per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsTime": { + "type": "array", + "description": "Aggregated sum of functions build compute time per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsMbSeconds": { + "type": "array", + "description": "Aggregated sum of functions build mbSeconds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executions": { + "type": "array", + "description": "Aggregated number of functions execution per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executionsTime": { + "type": "array", + "description": "Aggregated number of functions execution compute time per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executionsMbSeconds": { + "type": "array", + "description": "Aggregated number of functions mbSeconds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsSuccess": { + "type": "array", + "description": "Aggregated number of successful function builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsFailed": { + "type": "array", + "description": "Aggregated number of failed function builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "sitesTotal": { + "type": "integer", + "description": "Total aggregated number of sites.", + "x-example": 0, + "format": "int32" + }, + "sites": { + "type": "array", + "description": "Aggregated number of sites per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "requestsTotal": { + "type": "integer", + "description": "Total aggregated number of requests.", + "x-example": 0, + "format": "int32" + }, + "requests": { + "type": "array", + "description": "Aggregated number of requests per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "inboundTotal": { + "type": "integer", + "description": "Total aggregated inbound bandwidth.", + "x-example": 0, + "format": "int32" + }, + "inbound": { + "type": "array", + "description": "Aggregated number of inbound bandwidth per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "outboundTotal": { + "type": "integer", + "description": "Total aggregated outbound bandwidth.", + "x-example": 0, + "format": "int32" + }, + "outbound": { + "type": "array", + "description": "Aggregated number of outbound bandwidth per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "deploymentsTotal", + "deploymentsStorageTotal", + "buildsTotal", + "buildsStorageTotal", + "buildsTimeTotal", + "buildsMbSecondsTotal", + "executionsTotal", + "executionsTimeTotal", + "executionsMbSecondsTotal", + "deployments", + "deploymentsStorage", + "buildsSuccessTotal", + "buildsFailedTotal", + "builds", + "buildsStorage", + "buildsTime", + "buildsMbSeconds", + "executions", + "executionsTime", + "executionsMbSeconds", + "buildsSuccess", + "buildsFailed", + "sitesTotal", + "sites", + "requestsTotal", + "requests", + "inboundTotal", + "inbound", + "outboundTotal", + "outbound" + ] + }, + "usageSite": { + "description": "UsageSite", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "The time range of the usage stats.", + "x-example": "30d" + }, + "deploymentsTotal": { + "type": "integer", + "description": "Total aggregated number of function deployments.", + "x-example": 0, + "format": "int32" + }, + "deploymentsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of function deployments storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTotal": { + "type": "integer", + "description": "Total aggregated number of function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsSuccessTotal": { + "type": "integer", + "description": "Total aggregated number of successful function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsFailedTotal": { + "type": "integer", + "description": "Total aggregated number of failed function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsStorageTotal": { + "type": "integer", + "description": "total aggregated sum of function builds storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of function builds compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeAverage": { + "type": "integer", + "description": "Average builds compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of function builds mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "executionsTotal": { + "type": "integer", + "description": "Total aggregated number of function executions.", + "x-example": 0, + "format": "int32" + }, + "executionsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of function executions compute time.", + "x-example": 0, + "format": "int32" + }, + "executionsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of function executions mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "deployments": { + "type": "array", + "description": "Aggregated number of function deployments per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "deploymentsStorage": { + "type": "array", + "description": "Aggregated number of function deployments storage per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "builds": { + "type": "array", + "description": "Aggregated number of function builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsStorage": { + "type": "array", + "description": "Aggregated sum of function builds storage per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsTime": { + "type": "array", + "description": "Aggregated sum of function builds compute time per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsMbSeconds": { + "type": "array", + "description": "Aggregated number of function builds mbSeconds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executions": { + "type": "array", + "description": "Aggregated number of function executions per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executionsTime": { + "type": "array", + "description": "Aggregated number of function executions compute time per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executionsMbSeconds": { + "type": "array", + "description": "Aggregated number of function mbSeconds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsSuccess": { + "type": "array", + "description": "Aggregated number of successful builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "buildsFailed": { + "type": "array", + "description": "Aggregated number of failed builds per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "requestsTotal": { + "type": "integer", + "description": "Total aggregated number of requests.", + "x-example": 0, + "format": "int32" + }, + "requests": { + "type": "array", + "description": "Aggregated number of requests per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "inboundTotal": { + "type": "integer", + "description": "Total aggregated inbound bandwidth.", + "x-example": 0, + "format": "int32" + }, + "inbound": { + "type": "array", + "description": "Aggregated number of inbound bandwidth per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "outboundTotal": { + "type": "integer", + "description": "Total aggregated outbound bandwidth.", + "x-example": 0, + "format": "int32" + }, + "outbound": { + "type": "array", + "description": "Aggregated number of outbound bandwidth per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "deploymentsTotal", + "deploymentsStorageTotal", + "buildsTotal", + "buildsSuccessTotal", + "buildsFailedTotal", + "buildsStorageTotal", + "buildsTimeTotal", + "buildsTimeAverage", + "buildsMbSecondsTotal", + "executionsTotal", + "executionsTimeTotal", + "executionsMbSecondsTotal", + "deployments", + "deploymentsStorage", + "builds", + "buildsStorage", + "buildsTime", + "buildsMbSeconds", + "executions", + "executionsTime", + "executionsMbSeconds", + "buildsSuccess", + "buildsFailed", + "requestsTotal", + "requests", + "inboundTotal", + "inbound", + "outboundTotal", + "outbound" + ] + }, + "usageProject": { + "description": "UsageProject", + "type": "object", + "properties": { + "executionsTotal": { + "type": "integer", + "description": "Total aggregated number of function executions.", + "x-example": 0, + "format": "int32" + }, + "documentsTotal": { + "type": "integer", + "description": "Total aggregated number of documents.", + "x-example": 0, + "format": "int32" + }, + "databasesTotal": { + "type": "integer", + "description": "Total aggregated number of databases.", + "x-example": 0, + "format": "int32" + }, + "databasesStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of databases storage size (in bytes).", + "x-example": 0, + "format": "int32" + }, + "usersTotal": { + "type": "integer", + "description": "Total aggregated number of users.", + "x-example": 0, + "format": "int32" + }, + "filesStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of files storage size (in bytes).", + "x-example": 0, + "format": "int32" + }, + "functionsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of functions storage size (in bytes).", + "x-example": 0, + "format": "int32" + }, + "buildsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of builds storage size (in bytes).", + "x-example": 0, + "format": "int32" + }, + "deploymentsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of deployments storage size (in bytes).", + "x-example": 0, + "format": "int32" + }, + "bucketsTotal": { + "type": "integer", + "description": "Total aggregated number of buckets.", + "x-example": 0, + "format": "int32" + }, + "executionsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated number of function executions mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "buildsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated number of function builds mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "databasesReadsTotal": { + "type": "integer", + "description": "Total number of databases reads.", + "x-example": 0, + "format": "int32" + }, + "databasesWritesTotal": { + "type": "integer", + "description": "Total number of databases writes.", + "x-example": 0, + "format": "int32" + }, + "requests": { + "type": "array", + "description": "Aggregated number of requests per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "network": { + "type": "array", + "description": "Aggregated number of consumed bandwidth per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "users": { + "type": "array", + "description": "Aggregated number of users per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executions": { + "type": "array", + "description": "Aggregated number of executions per period.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "executionsBreakdown": { + "type": "array", + "description": "Aggregated breakdown in totals of executions by functions.", + "items": { + "$ref": "#\/components\/schemas\/metricBreakdown" + }, + "x-example": [] + }, + "bucketsBreakdown": { + "type": "array", + "description": "Aggregated breakdown in totals of usage by buckets.", + "items": { + "$ref": "#\/components\/schemas\/metricBreakdown" + }, + "x-example": [] + }, + "databasesStorageBreakdown": { + "type": "array", + "description": "An array of the aggregated breakdown of storage usage by databases.", + "items": { + "$ref": "#\/components\/schemas\/metricBreakdown" + }, + "x-example": [] + }, + "executionsMbSecondsBreakdown": { + "type": "array", + "description": "Aggregated breakdown in totals of execution mbSeconds by functions.", + "items": { + "$ref": "#\/components\/schemas\/metricBreakdown" + }, + "x-example": [] + }, + "buildsMbSecondsBreakdown": { + "type": "array", + "description": "Aggregated breakdown in totals of build mbSeconds by functions.", + "items": { + "$ref": "#\/components\/schemas\/metricBreakdown" + }, + "x-example": [] + }, + "functionsStorageBreakdown": { + "type": "array", + "description": "Aggregated breakdown in totals of functions storage size (in bytes).", + "items": { + "$ref": "#\/components\/schemas\/metricBreakdown" + }, + "x-example": [] + }, + "authPhoneTotal": { + "type": "integer", + "description": "Total aggregated number of phone auth.", + "x-example": 0, + "format": "int32" + }, + "authPhoneEstimate": { + "type": "number", + "description": "Estimated total aggregated cost of phone auth.", + "x-example": 0, + "format": "double" + }, + "authPhoneCountryBreakdown": { + "type": "array", + "description": "Aggregated breakdown in totals of phone auth by country.", + "items": { + "$ref": "#\/components\/schemas\/metricBreakdown" + }, + "x-example": [] + }, + "databasesReads": { + "type": "array", + "description": "An array of aggregated number of database reads.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "databasesWrites": { + "type": "array", + "description": "An array of aggregated number of database writes.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "imageTransformations": { + "type": "array", + "description": "An array of aggregated number of image transformations.", + "items": { + "$ref": "#\/components\/schemas\/metric" + }, + "x-example": [] + }, + "imageTransformationsTotal": { + "type": "integer", + "description": "Total aggregated number of image transformations.", + "x-example": 0, + "format": "int32" + } + }, + "required": [ + "executionsTotal", + "documentsTotal", + "databasesTotal", + "databasesStorageTotal", + "usersTotal", + "filesStorageTotal", + "functionsStorageTotal", + "buildsStorageTotal", + "deploymentsStorageTotal", + "bucketsTotal", + "executionsMbSecondsTotal", + "buildsMbSecondsTotal", + "databasesReadsTotal", + "databasesWritesTotal", + "requests", + "network", + "users", + "executions", + "executionsBreakdown", + "bucketsBreakdown", + "databasesStorageBreakdown", + "executionsMbSecondsBreakdown", + "buildsMbSecondsBreakdown", + "functionsStorageBreakdown", + "authPhoneTotal", + "authPhoneEstimate", + "authPhoneCountryBreakdown", + "databasesReads", + "databasesWrites", + "imageTransformations", + "imageTransformationsTotal" + ] + }, + "headers": { + "description": "Headers", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Header name.", + "x-example": "Content-Type" + }, + "value": { + "type": "string", + "description": "Header value.", + "x-example": "application\/json" + } + }, + "required": [ + "name", + "value" + ] + }, + "specification": { + "description": "Specification", + "type": "object", + "properties": { + "memory": { + "type": "integer", + "description": "Memory size in MB.", + "x-example": 512, + "format": "int32" + }, + "cpus": { + "type": "number", + "description": "Number of CPUs.", + "x-example": 1, + "format": "double" + }, + "enabled": { + "type": "boolean", + "description": "Is size enabled.", + "x-example": true + }, + "slug": { + "type": "string", + "description": "Size slug.", + "x-example": "s-1vcpu-512mb" + } + }, + "required": [ + "memory", + "cpus", + "enabled", + "slug" + ] + }, + "proxyRule": { + "description": "Rule", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Rule ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Rule creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Rule update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "domain": { + "type": "string", + "description": "Domain name.", + "x-example": "appwrite.company.com" + }, + "type": { + "type": "string", + "description": "Action definition for the rule. Possible values are \"api\", \"deployment\", or \"redirect\"", + "x-example": "deployment" + }, + "trigger": { + "type": "string", + "description": "Defines how the rule was created. Possible values are \"manual\" or \"deployment\"", + "x-example": "manual" + }, + "redirectUrl": { + "type": "string", + "description": "URL to redirect to. Used if type is \"redirect\"", + "x-example": "https:\/\/appwrite.io\/docs" + }, + "redirectStatusCode": { + "type": "integer", + "description": "Status code to apply during redirect. Used if type is \"redirect\"", + "x-example": 301, + "format": "int32" + }, + "deploymentId": { + "type": "string", + "description": "ID of deployment. Used if type is \"deployment\"", + "x-example": "n3u9feiwmf" + }, + "deploymentResourceType": { + "type": "string", + "description": "Type of deployment. Possible values are \"function\", \"site\". Used if rule's type is \"deployment\".", + "x-example": "function" + }, + "deploymentResourceId": { + "type": "string", + "description": "ID deployment's resource. Used if type is \"deployment\"", + "x-example": "n3u9feiwmf" + }, + "deploymentVcsProviderBranch": { + "type": "string", + "description": "Name of Git branch that updates rule. Used if type is \"deployment\"", + "x-example": "function" + }, + "status": { + "type": "string", + "description": "Domain verification status. Possible values are \"created\", \"verifying\", \"verified\" and \"unverified\"", + "x-example": "verified" + }, + "logs": { + "type": "string", + "description": "Certificate generation logs. This will return an empty string if generation did not run, or succeeded.", + "x-example": "HTTP challegne failed." + }, + "renewAt": { + "type": "string", + "description": "Certificate auto-renewal date in ISO 8601 format.", + "x-example": "datetime" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "domain", + "type", + "trigger", + "redirectUrl", + "redirectStatusCode", + "deploymentId", + "deploymentResourceType", + "deploymentResourceId", + "deploymentVcsProviderBranch", + "status", + "logs", + "renewAt" + ] + }, + "smsTemplate": { + "description": "SmsTemplate", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Template type", + "x-example": "verification" + }, + "locale": { + "type": "string", + "description": "Template locale", + "x-example": "en_us" + }, + "message": { + "type": "string", + "description": "Template message", + "x-example": "Click on the link to verify your account." + } + }, + "required": [ + "type", + "locale", + "message" + ] + }, + "emailTemplate": { + "description": "EmailTemplate", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Template type", + "x-example": "verification" + }, + "locale": { + "type": "string", + "description": "Template locale", + "x-example": "en_us" + }, + "message": { + "type": "string", + "description": "Template message", + "x-example": "Click on the link to verify your account." + }, + "senderName": { + "type": "string", + "description": "Name of the sender", + "x-example": "My User" + }, + "senderEmail": { + "type": "string", + "description": "Email of the sender", + "x-example": "mail@appwrite.io" + }, + "replyTo": { + "type": "string", + "description": "Reply to email address", + "x-example": "emails@appwrite.io" + }, + "subject": { + "type": "string", + "description": "Email subject", + "x-example": "Please verify your email address" + } + }, + "required": [ + "type", + "locale", + "message", + "senderName", + "senderEmail", + "replyTo", + "subject" + ] + }, + "consoleVariables": { + "description": "Console Variables", + "type": "object", + "properties": { + "_APP_DOMAIN_TARGET_CNAME": { + "type": "string", + "description": "CNAME target for your Appwrite custom domains.", + "x-example": "appwrite.io" + }, + "_APP_DOMAIN_TARGET_A": { + "type": "string", + "description": "A target for your Appwrite custom domains.", + "x-example": "127.0.0.1" + }, + "_APP_DOMAIN_TARGET_AAAA": { + "type": "string", + "description": "AAAA target for your Appwrite custom domains.", + "x-example": "::1" + }, + "_APP_STORAGE_LIMIT": { + "type": "integer", + "description": "Maximum file size allowed for file upload in bytes.", + "x-example": "30000000", + "format": "int32" + }, + "_APP_COMPUTE_SIZE_LIMIT": { + "type": "integer", + "description": "Maximum file size allowed for deployment in bytes.", + "x-example": "30000000", + "format": "int32" + }, + "_APP_USAGE_STATS": { + "type": "string", + "description": "Defines if usage stats are enabled. This value is set to 'enabled' by default, to disable the usage stats set the value to 'disabled'.", + "x-example": "enabled" + }, + "_APP_VCS_ENABLED": { + "type": "boolean", + "description": "Defines if VCS (Version Control System) is enabled.", + "x-example": true + }, + "_APP_DOMAIN_ENABLED": { + "type": "boolean", + "description": "Defines if main domain is configured. If so, custom domains can be created.", + "x-example": true + }, + "_APP_ASSISTANT_ENABLED": { + "type": "boolean", + "description": "Defines if AI assistant is enabled.", + "x-example": true + }, + "_APP_DOMAIN_SITES": { + "type": "string", + "description": "A domain to use for site URLs.", + "x-example": "sites.localhost" + }, + "_APP_DOMAIN_FUNCTIONS": { + "type": "string", + "description": "A domain to use for function URLs.", + "x-example": "functions.localhost" + }, + "_APP_OPTIONS_FORCE_HTTPS": { + "type": "string", + "description": "Defines if HTTPS is enforced for all requests.", + "x-example": "enabled" + }, + "_APP_DOMAINS_NAMESERVERS": { + "type": "string", + "description": "Comma-separated list of nameservers.", + "x-example": "ns1.example.com,ns2.example.com" + } + }, + "required": [ + "_APP_DOMAIN_TARGET_CNAME", + "_APP_DOMAIN_TARGET_A", + "_APP_DOMAIN_TARGET_AAAA", + "_APP_STORAGE_LIMIT", + "_APP_COMPUTE_SIZE_LIMIT", + "_APP_USAGE_STATS", + "_APP_VCS_ENABLED", + "_APP_DOMAIN_ENABLED", + "_APP_ASSISTANT_ENABLED", + "_APP_DOMAIN_SITES", + "_APP_DOMAIN_FUNCTIONS", + "_APP_OPTIONS_FORCE_HTTPS", + "_APP_DOMAINS_NAMESERVERS" + ] + }, + "mfaChallenge": { + "description": "MFA Challenge", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Token ID.", + "x-example": "bb8ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Token creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c168bb8" + }, + "expire": { + "type": "string", + "description": "Token expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "userId", + "expire" + ] + }, + "mfaRecoveryCodes": { + "description": "MFA Recovery Codes", + "type": "object", + "properties": { + "recoveryCodes": { + "type": "array", + "description": "Recovery codes.", + "items": { + "type": "string" + }, + "x-example": [ + "a3kf0-s0cl2", + "s0co1-as98s" + ] + } + }, + "required": [ + "recoveryCodes" + ] + }, + "mfaType": { + "description": "MFAType", + "type": "object", + "properties": { + "secret": { + "type": "string", + "description": "Secret token used for TOTP factor.", + "x-example": true + }, + "uri": { + "type": "string", + "description": "URI for authenticator apps.", + "x-example": true + } + }, + "required": [ + "secret", + "uri" + ] + }, + "mfaFactors": { + "description": "MFAFactors", + "type": "object", + "properties": { + "totp": { + "type": "boolean", + "description": "Can TOTP be used for MFA challenge for this account.", + "x-example": true + }, + "phone": { + "type": "boolean", + "description": "Can phone (SMS) be used for MFA challenge for this account.", + "x-example": true + }, + "email": { + "type": "boolean", + "description": "Can email be used for MFA challenge for this account.", + "x-example": true + }, + "recoveryCode": { + "type": "boolean", + "description": "Can recovery code be used for MFA challenge for this account.", + "x-example": true + } + }, + "required": [ + "totp", + "phone", + "email", + "recoveryCode" + ] + }, + "provider": { + "description": "Provider", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Provider ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Provider creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Provider update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "The name for the provider instance.", + "x-example": "Mailgun" + }, + "provider": { + "type": "string", + "description": "The name of the provider service.", + "x-example": "mailgun" + }, + "enabled": { + "type": "boolean", + "description": "Is provider enabled?", + "x-example": true + }, + "type": { + "type": "string", + "description": "Type of provider.", + "x-example": "sms" + }, + "credentials": { + "type": "object", + "description": "Provider credentials.", + "x-example": { + "key": "123456789" + } + }, + "options": { + "type": "object", + "description": "Provider options.", + "x-example": { + "from": "sender-email@mydomain" + }, + "nullable": true + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "provider", + "enabled", + "type", + "credentials" + ] + }, + "message": { + "description": "Message", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Message ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Message creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Message update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "providerType": { + "type": "string", + "description": "Message provider type.", + "x-example": "email" + }, + "topics": { + "type": "array", + "description": "Topic IDs set as recipients.", + "items": { + "type": "string" + }, + "x-example": [ + "5e5ea5c16897e" + ] + }, + "users": { + "type": "array", + "description": "User IDs set as recipients.", + "items": { + "type": "string" + }, + "x-example": [ + "5e5ea5c16897e" + ] + }, + "targets": { + "type": "array", + "description": "Target IDs set as recipients.", + "items": { + "type": "string" + }, + "x-example": [ + "5e5ea5c16897e" + ] + }, + "scheduledAt": { + "type": "string", + "description": "The scheduled time for message.", + "x-example": "2020-10-15T06:38:00.000+00:00", + "nullable": true + }, + "deliveredAt": { + "type": "string", + "description": "The time when the message was delivered.", + "x-example": "2020-10-15T06:38:00.000+00:00", + "nullable": true + }, + "deliveryErrors": { + "type": "array", + "description": "Delivery errors if any.", + "items": { + "type": "string" + }, + "x-example": [ + "Failed to send message to target 5e5ea5c16897e: Credentials not valid." + ], + "nullable": true + }, + "deliveredTotal": { + "type": "integer", + "description": "Number of recipients the message was delivered to.", + "x-example": 1, + "format": "int32" + }, + "data": { + "type": "object", + "description": "Data of the message.", + "x-example": { + "subject": "Welcome to Appwrite", + "content": "Hi there, welcome to Appwrite family." + } + }, + "status": { + "type": "string", + "description": "Status of delivery.", + "x-example": "Message status can be one of the following: draft, processing, scheduled, sent, or failed." + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "providerType", + "topics", + "users", + "targets", + "deliveredTotal", + "data", + "status" + ] + }, + "topic": { + "description": "Topic", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Topic ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Topic creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Topic update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "The name of the topic.", + "x-example": "events" + }, + "emailTotal": { + "type": "integer", + "description": "Total count of email subscribers subscribed to the topic.", + "x-example": 100, + "format": "int32" + }, + "smsTotal": { + "type": "integer", + "description": "Total count of SMS subscribers subscribed to the topic.", + "x-example": 100, + "format": "int32" + }, + "pushTotal": { + "type": "integer", + "description": "Total count of push subscribers subscribed to the topic.", + "x-example": 100, + "format": "int32" + }, + "subscribe": { + "type": "array", + "description": "Subscribe permissions.", + "items": { + "type": "string" + }, + "x-example": "users" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "emailTotal", + "smsTotal", + "pushTotal", + "subscribe" + ] + }, + "subscriber": { + "description": "Subscriber", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Subscriber ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Subscriber creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Subscriber update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "targetId": { + "type": "string", + "description": "Target ID.", + "x-example": "259125845563242502" + }, + "target": { + "type": "object", + "description": "Target.", + "x-example": { + "$id": "259125845563242502", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "providerType": "email", + "providerId": "259125845563242502", + "name": "ageon-app-email", + "identifier": "random-mail@email.org", + "userId": "5e5ea5c16897e" + }, + "items": { + "$ref": "#\/components\/schemas\/target" + } + }, + "userId": { + "type": "string", + "description": "Topic ID.", + "x-example": "5e5ea5c16897e" + }, + "userName": { + "type": "string", + "description": "User Name.", + "x-example": "Aegon Targaryen" + }, + "topicId": { + "type": "string", + "description": "Topic ID.", + "x-example": "259125845563242502" + }, + "providerType": { + "type": "string", + "description": "The target provider type. Can be one of the following: `email`, `sms` or `push`.", + "x-example": "email" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "targetId", + "target", + "userId", + "userName", + "topicId", + "providerType" + ] + }, + "target": { + "description": "Target", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Target ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Target creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Target update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Target Name.", + "x-example": "Apple iPhone 12" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "259125845563242502" + }, + "providerId": { + "type": "string", + "description": "Provider ID.", + "x-example": "259125845563242502", + "nullable": true + }, + "providerType": { + "type": "string", + "description": "The target provider type. Can be one of the following: `email`, `sms` or `push`.", + "x-example": "email" + }, + "identifier": { + "type": "string", + "description": "The target identifier.", + "x-example": "token" + }, + "expired": { + "type": "boolean", + "description": "Is the target expired.", + "x-example": false + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "userId", + "providerType", + "identifier", + "expired" + ] + }, + "migration": { + "description": "Migration", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Migration ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Migration creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Variable creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "string", + "description": "Migration status ( pending, processing, failed, completed ) ", + "x-example": "pending" + }, + "stage": { + "type": "string", + "description": "Migration stage ( init, processing, source-check, destination-check, migrating, finished )", + "x-example": "init" + }, + "source": { + "type": "string", + "description": "A string containing the type of source of the migration.", + "x-example": "Appwrite" + }, + "destination": { + "type": "string", + "description": "A string containing the type of destination of the migration.", + "x-example": "Appwrite" + }, + "resources": { + "type": "array", + "description": "Resources to migrate.", + "items": { + "type": "string" + }, + "x-example": [ + "user" + ] + }, + "resourceId": { + "type": "string", + "description": "Id of the resource to migrate.", + "x-example": "databaseId:collectionId" + }, + "statusCounters": { + "type": "object", + "description": "A group of counters that represent the total progress of the migration.", + "x-example": "{\"Database\": {\"PENDING\": 0, \"SUCCESS\": 1, \"ERROR\": 0, \"SKIP\": 0, \"PROCESSING\": 0, \"WARNING\": 0}}" + }, + "resourceData": { + "type": "object", + "description": "An array of objects containing the report data of the resources that were migrated.", + "x-example": "[{\"resource\":\"Database\",\"id\":\"public\",\"status\":\"SUCCESS\",\"message\":\"\"}]" + }, + "errors": { + "type": "array", + "description": "All errors that occurred during the migration process.", + "items": { + "type": "string" + }, + "x-example": [] + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "status", + "stage", + "source", + "destination", + "resources", + "resourceId", + "statusCounters", + "resourceData", + "errors" + ] + }, + "migrationReport": { + "description": "Migration Report", + "type": "object", + "properties": { + "user": { + "type": "integer", + "description": "Number of users to be migrated.", + "x-example": 20, + "format": "int32" + }, + "team": { + "type": "integer", + "description": "Number of teams to be migrated.", + "x-example": 20, + "format": "int32" + }, + "database": { + "type": "integer", + "description": "Number of databases to be migrated.", + "x-example": 20, + "format": "int32" + }, + "document": { + "type": "integer", + "description": "Number of documents to be migrated.", + "x-example": 20, + "format": "int32" + }, + "file": { + "type": "integer", + "description": "Number of files to be migrated.", + "x-example": 20, + "format": "int32" + }, + "bucket": { + "type": "integer", + "description": "Number of buckets to be migrated.", + "x-example": 20, + "format": "int32" + }, + "function": { + "type": "integer", + "description": "Number of functions to be migrated.", + "x-example": 20, + "format": "int32" + }, + "size": { + "type": "integer", + "description": "Size of files to be migrated in mb.", + "x-example": 30000, + "format": "int32" + }, + "version": { + "type": "string", + "description": "Version of the Appwrite instance to be migrated.", + "x-example": "1.4.0" + } + }, + "required": [ + "user", + "team", + "database", + "document", + "file", + "bucket", + "function", + "size", + "version" + ] + } + }, + "securitySchemes": { + "Project": { + "type": "apiKey", + "name": "X-Appwrite-Project", + "description": "Your project ID", + "in": "header", + "x-appwrite": { + "demo": "<YOUR_PROJECT_ID>" + } + }, + "Key": { + "type": "apiKey", + "name": "X-Appwrite-Key", + "description": "Your secret API key", + "in": "header", + "x-appwrite": { + "demo": "<YOUR_API_KEY>" + } + }, + "JWT": { + "type": "apiKey", + "name": "X-Appwrite-JWT", + "description": "Your secret JSON Web Token", + "in": "header" + }, + "Locale": { + "type": "apiKey", + "name": "X-Appwrite-Locale", + "description": "", + "in": "header", + "x-appwrite": { + "demo": "en" + } + }, + "Mode": { + "type": "apiKey", + "name": "X-Appwrite-Mode", + "description": "", + "in": "header", + "x-appwrite": { + "demo": "" + } + } + } + }, + "externalDocs": { + "description": "Full API docs, specs and tutorials", + "url": "https:\/\/appwrite.io\/docs" + } +} \ No newline at end of file diff --git a/app/config/specs/open-api3-1.8.x-server.json b/app/config/specs/open-api3-1.8.x-server.json new file mode 100644 index 0000000000..871f5a1e57 --- /dev/null +++ b/app/config/specs/open-api3-1.8.x-server.json @@ -0,0 +1,30573 @@ +{ + "openapi": "3.0.0", + "info": { + "version": "1.7.4", + "title": "Appwrite", + "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", + "termsOfService": "https:\/\/appwrite.io\/policy\/terms", + "contact": { + "name": "Appwrite Team", + "url": "https:\/\/appwrite.io\/support", + "email": "team@appwrite.io" + }, + "license": { + "name": "BSD-3-Clause", + "url": "https:\/\/raw.githubusercontent.com\/appwrite\/appwrite\/master\/LICENSE" + } + }, + "servers": [ + { + "url": "https:\/\/cloud.appwrite.io\/v1" + }, + { + "url": "https:\/\/<REGION>.cloud.appwrite.io\/v1" + } + ], + "paths": { + "\/account": { + "get": { + "summary": "Get account", + "operationId": "accountGet", + "tags": [ + "account" + ], + "description": "Get the currently logged in user.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": "account", + "weight": 10, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "post": { + "summary": "Create account", + "operationId": "accountCreate", + "tags": [ + "account" + ], + "description": "Use this endpoint to allow a new user to register a new account in your project. After the user registration completes successfully, you can use the [\/account\/verfication](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createVerification) route to start verifying the user email address. To allow the new user to login to their new account, you need to create a new [account session](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createEmailSession).", + "responses": { + "201": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "create", + "group": "account", + "weight": 9, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "New user password. Must be between 8 and 256 chars.", + "x-example": null + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + } + } + } + }, + "\/account\/email": { + "patch": { + "summary": "Update email", + "operationId": "accountUpdateEmail", + "tags": [ + "account" + ], + "description": "Update currently logged in user account email address. After changing user address, the user confirmation status will get reset. A new confirmation email is not sent automatically however you can use the send confirmation email endpoint again to send the confirmation email. For security measures, user password is required to complete this request.\nThis endpoint can also be used to convert an anonymous account to a normal one, by passing an email address and a new password.\n", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateEmail", + "group": "account", + "weight": 35, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-email.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password. Must be at least 8 chars.", + "x-example": "password" + } + }, + "required": [ + "email", + "password" + ] + } + } + } + } + } + }, + "\/account\/identities": { + "get": { + "summary": "List identities", + "operationId": "accountListIdentities", + "tags": [ + "account" + ], + "description": "Get the list of identities for the currently logged in user.", + "responses": { + "200": { + "description": "Identities List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/identityList" + } + } + } + } + }, + "x-appwrite": { + "method": "listIdentities", + "group": "identities", + "weight": 58, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-identities.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-identities.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, provider, providerUid, providerEmail, providerAccessTokenExpiry", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/account\/identities\/{identityId}": { + "delete": { + "summary": "Delete identity", + "operationId": "accountDeleteIdentity", + "tags": [ + "account" + ], + "description": "Delete an identity by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteIdentity", + "group": "identities", + "weight": 59, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-identity.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-identity.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "identityId", + "description": "Identity ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<IDENTITY_ID>" + }, + "in": "path" + } + ] + } + }, + "\/account\/jwts": { + "post": { + "summary": "Create JWT", + "operationId": "accountCreateJWT", + "tags": [ + "account" + ], + "description": "Use this endpoint to create a JSON Web Token. You can use the resulting JWT to authenticate on behalf of the current user when working with the Appwrite server-side API and SDKs. The JWT secret is valid for 15 minutes from its creation and will be invalid if the user will logout in that time frame.", + "responses": { + "201": { + "description": "JWT", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/jwt" + } + } + } + } + }, + "x-appwrite": { + "method": "createJWT", + "group": "tokens", + "weight": 30, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-j-w-t.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-jwt.md", + "rate-limit": 100, + "rate-time": 3600, + "rate-key": "url:{url},userId:{userId}", + "scope": "account", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ] + } + }, + "\/account\/logs": { + "get": { + "summary": "List logs", + "operationId": "accountListLogs", + "tags": [ + "account" + ], + "description": "Get the list of latest security activity logs for the currently logged in user. Each log returns user IP address, location and date and time of log.", + "responses": { + "200": { + "description": "Logs List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/logList" + } + } + } + } + }, + "x-appwrite": { + "method": "listLogs", + "group": "logs", + "weight": 32, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/account\/mfa": { + "patch": { + "summary": "Update MFA", + "operationId": "accountUpdateMFA", + "tags": [ + "account" + ], + "description": "Enable or disable MFA on an account.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMFA", + "group": "mfa", + "weight": 45, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-m-f-a.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "mfa": { + "type": "boolean", + "description": "Enable or disable MFA.", + "x-example": false + } + }, + "required": [ + "mfa" + ] + } + } + } + } + } + }, + "\/account\/mfa\/authenticators\/{type}": { + "post": { + "summary": "Create authenticator", + "operationId": "accountCreateMfaAuthenticator", + "tags": [ + "account" + ], + "description": "Add an authenticator app to be used as an MFA factor. Verify the authenticator using the [verify authenticator](\/docs\/references\/cloud\/client-web\/account#updateMfaAuthenticator) method.", + "responses": { + "200": { + "description": "MFAType", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaType" + } + } + } + } + }, + "x-appwrite": { + "method": "createMfaAuthenticator", + "group": "mfa", + "weight": 47, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "type", + "description": "Type of authenticator. Must be `totp`", + "required": true, + "schema": { + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [] + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update authenticator (confirmation)", + "operationId": "accountUpdateMfaAuthenticator", + "tags": [ + "account" + ], + "description": "Verify an authenticator app after adding it using the [add authenticator](\/docs\/references\/cloud\/client-web\/account#createMfaAuthenticator) method.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMfaAuthenticator", + "group": "mfa", + "weight": 48, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "type", + "description": "Type of authenticator.", + "required": true, + "schema": { + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [] + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "otp": { + "type": "string", + "description": "Valid verification token.", + "x-example": "<OTP>" + } + }, + "required": [ + "otp" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete authenticator", + "operationId": "accountDeleteMfaAuthenticator", + "tags": [ + "account" + ], + "description": "Delete an authenticator for a user by ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteMfaAuthenticator", + "group": "mfa", + "weight": 52, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "type", + "description": "Type of authenticator.", + "required": true, + "schema": { + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [] + }, + "in": "path" + } + ] + } + }, + "\/account\/mfa\/challenge": { + "post": { + "summary": "Create MFA challenge", + "operationId": "accountCreateMfaChallenge", + "tags": [ + "account" + ], + "description": "Begin the process of MFA verification after sign-in. Finish the flow with [updateMfaChallenge](\/docs\/references\/cloud\/client-web\/account#updateMfaChallenge) method.", + "responses": { + "201": { + "description": "MFA Challenge", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaChallenge" + } + } + } + } + }, + "x-appwrite": { + "method": "createMfaChallenge", + "group": "mfa", + "weight": 53, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-mfa-challenge.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-mfa-challenge.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{userId}", + "scope": "account", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "factor": { + "type": "string", + "description": "Factor used for verification. Must be one of following: `email`, `phone`, `totp`, `recoveryCode`.", + "x-example": "email", + "enum": [ + "email", + "phone", + "totp", + "recoverycode" + ], + "x-enum-name": "AuthenticationFactor", + "x-enum-keys": [] + } + }, + "required": [ + "factor" + ] + } + } + } + } + }, + "put": { + "summary": "Update MFA challenge (confirmation)", + "operationId": "accountUpdateMfaChallenge", + "tags": [ + "account" + ], + "description": "Complete the MFA challenge by providing the one-time password. Finish the process of MFA verification by providing the one-time password. To begin the flow, use [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method.", + "responses": { + "200": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMfaChallenge", + "group": "mfa", + "weight": 54, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-mfa-challenge.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa-challenge.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},challengeId:{param-challengeId}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "challengeId": { + "type": "string", + "description": "ID of the challenge.", + "x-example": "<CHALLENGE_ID>" + }, + "otp": { + "type": "string", + "description": "Valid verification token.", + "x-example": "<OTP>" + } + }, + "required": [ + "challengeId", + "otp" + ] + } + } + } + } + } + }, + "\/account\/mfa\/factors": { + "get": { + "summary": "List factors", + "operationId": "accountListMfaFactors", + "tags": [ + "account" + ], + "description": "List the factors available on the account to be used as a MFA challange.", + "responses": { + "200": { + "description": "MFAFactors", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaFactors" + } + } + } + } + }, + "x-appwrite": { + "method": "listMfaFactors", + "group": "mfa", + "weight": 46, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-mfa-factors.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-mfa-factors.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/account\/mfa\/recovery-codes": { + "get": { + "summary": "List MFA recovery codes", + "operationId": "accountGetMfaRecoveryCodes", + "tags": [ + "account" + ], + "description": "Get recovery codes that can be used as backup for MFA flow. Before getting codes, they must be generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method. An OTP challenge is required to read recovery codes.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaRecoveryCodes" + } + } + } + } + }, + "x-appwrite": { + "method": "getMfaRecoveryCodes", + "group": "mfa", + "weight": 51, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "post": { + "summary": "Create MFA recovery codes", + "operationId": "accountCreateMfaRecoveryCodes", + "tags": [ + "account" + ], + "description": "Generate recovery codes as backup for MFA flow. It's recommended to generate and show then immediately after user successfully adds their authehticator. Recovery codes can be used as a MFA verification type in [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method.", + "responses": { + "201": { + "description": "MFA Recovery Codes", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaRecoveryCodes" + } + } + } + } + }, + "x-appwrite": { + "method": "createMfaRecoveryCodes", + "group": "mfa", + "weight": 49, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "patch": { + "summary": "Update MFA recovery codes (regenerate)", + "operationId": "accountUpdateMfaRecoveryCodes", + "tags": [ + "account" + ], + "description": "Regenerate recovery codes that can be used as backup for MFA flow. Before regenerating codes, they must be first generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method. An OTP challenge is required to regenreate recovery codes.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaRecoveryCodes" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMfaRecoveryCodes", + "group": "mfa", + "weight": 50, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/account\/name": { + "patch": { + "summary": "Update name", + "operationId": "accountUpdateName", + "tags": [ + "account" + ], + "description": "Update currently logged in user account name.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateName", + "group": "account", + "weight": 33, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-name.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-name.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "name" + ] + } + } + } + } + } + }, + "\/account\/password": { + "patch": { + "summary": "Update password", + "operationId": "accountUpdatePassword", + "tags": [ + "account" + ], + "description": "Update currently logged in user password. For validation, user is required to pass in the new password, and the old password. For users created with OAuth, Team Invites and Magic URL, oldPassword is optional.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePassword", + "group": "account", + "weight": 34, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-password.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-password.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "password": { + "type": "string", + "description": "New user password. Must be at least 8 chars.", + "x-example": null + }, + "oldPassword": { + "type": "string", + "description": "Current user password. Must be at least 8 chars.", + "x-example": "password" + } + }, + "required": [ + "password" + ] + } + } + } + } + } + }, + "\/account\/phone": { + "patch": { + "summary": "Update phone", + "operationId": "accountUpdatePhone", + "tags": [ + "account" + ], + "description": "Update the currently logged in user's phone number. After updating the phone number, the phone verification status will be reset. A confirmation SMS is not sent automatically, however you can use the [POST \/account\/verification\/phone](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createPhoneVerification) endpoint to send a confirmation SMS.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePhone", + "group": "account", + "weight": 36, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-phone.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-phone.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "x-example": "+12065550100" + }, + "password": { + "type": "string", + "description": "User password. Must be at least 8 chars.", + "x-example": "password" + } + }, + "required": [ + "phone", + "password" + ] + } + } + } + } + } + }, + "\/account\/prefs": { + "get": { + "summary": "Get account preferences", + "operationId": "accountGetPrefs", + "tags": [ + "account" + ], + "description": "Get the preferences as a key-value object for the currently logged in user.", + "responses": { + "200": { + "description": "Preferences", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/preferences" + } + } + } + } + }, + "x-appwrite": { + "method": "getPrefs", + "group": "account", + "weight": 31, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "patch": { + "summary": "Update preferences", + "operationId": "accountUpdatePrefs", + "tags": [ + "account" + ], + "description": "Update currently logged in user account preferences. The object you pass is stored as is, and replaces any previous value. The maximum allowed prefs size is 64kB and throws error if exceeded.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePrefs", + "group": "account", + "weight": 37, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "prefs": { + "type": "object", + "description": "Prefs key-value JSON object.", + "x-example": "{}" + } + }, + "required": [ + "prefs" + ] + } + } + } + } + } + }, + "\/account\/recovery": { + "post": { + "summary": "Create password recovery", + "operationId": "accountCreateRecovery", + "tags": [ + "account" + ], + "description": "Sends the user an email with a temporary secret key for password reset. When the user clicks the confirmation link he is redirected back to your app password reset URL with the secret key and email address values attached to the URL query string. Use the query string params to submit a request to the [PUT \/account\/recovery](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updateRecovery) endpoint to complete the process. The verification link sent to the user's email address is valid for 1 hour.", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createRecovery", + "group": "recovery", + "weight": 39, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-recovery.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-recovery.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},email:{param-email}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "x-example": "https:\/\/example.com" + } + }, + "required": [ + "email", + "url" + ] + } + } + } + } + }, + "put": { + "summary": "Update password recovery (confirmation)", + "operationId": "accountUpdateRecovery", + "tags": [ + "account" + ], + "description": "Use this endpoint to complete the user account password reset. Both the **userId** and **secret** arguments will be passed as query parameters to the redirect URL you have provided when sending your request to the [POST \/account\/recovery](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createRecovery) endpoint.\n\nPlease note that in order to avoid a [Redirect Attack](https:\/\/github.com\/OWASP\/CheatSheetSeries\/blob\/master\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) the only valid redirect URLs are the ones from domains you have set when adding your platforms in the console interface.", + "responses": { + "200": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "updateRecovery", + "group": "recovery", + "weight": 40, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-recovery.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-recovery.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid reset token.", + "x-example": "<SECRET>" + }, + "password": { + "type": "string", + "description": "New user password. Must be between 8 and 256 chars.", + "x-example": null + } + }, + "required": [ + "userId", + "secret", + "password" + ] + } + } + } + } + } + }, + "\/account\/sessions": { + "get": { + "summary": "List sessions", + "operationId": "accountListSessions", + "tags": [ + "account" + ], + "description": "Get the list of active sessions across different devices for the currently logged in user.", + "responses": { + "200": { + "description": "Sessions List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/sessionList" + } + } + } + } + }, + "x-appwrite": { + "method": "listSessions", + "group": "sessions", + "weight": 12, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-sessions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "delete": { + "summary": "Delete sessions", + "operationId": "accountDeleteSessions", + "tags": [ + "account" + ], + "description": "Delete all sessions from the user account and remove any sessions cookies from the end client.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSessions", + "group": "sessions", + "weight": 13, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-sessions.md", + "rate-limit": 100, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/account\/sessions\/anonymous": { + "post": { + "summary": "Create anonymous session", + "operationId": "accountCreateAnonymousSession", + "tags": [ + "account" + ], + "description": "Use this endpoint to allow a new user to register an anonymous account in your project. This route will also create a new session for the user. To allow the new user to convert an anonymous account to a normal account, you need to update its [email and password](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updateEmail) or create an [OAuth2 session](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#CreateOAuth2Session).", + "responses": { + "201": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "createAnonymousSession", + "group": "sessions", + "weight": 18, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-anonymous-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session-anonymous.md", + "rate-limit": 50, + "rate-time": 3600, + "rate-key": "ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ] + } + }, + "\/account\/sessions\/email": { + "post": { + "summary": "Create email password session", + "operationId": "accountCreateEmailPasswordSession", + "tags": [ + "account" + ], + "description": "Allow the user to login into their account by providing a valid email and password combination. This route will create a new session for the user.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "201": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "createEmailPasswordSession", + "group": "sessions", + "weight": 17, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-email-password-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session-email-password.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},email:{param-email}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password. Must be at least 8 chars.", + "x-example": "password" + } + }, + "required": [ + "email", + "password" + ] + } + } + } + } + } + }, + "\/account\/sessions\/magic-url": { + "put": { + "summary": "Update magic URL session", + "operationId": "accountUpdateMagicURLSession", + "tags": [ + "account" + ], + "description": "Use this endpoint to create a session from token. Provide the **userId** and **secret** parameters from the successful response of authentication flows initiated by token creation. For example, magic URL and phone login.", + "responses": { + "201": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMagicURLSession", + "group": "sessions", + "weight": 27, + "cookies": false, + "type": "", + "deprecated": true, + "demo": "account\/update-magic-u-r-l-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "ip:{ip},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + } + } + } + }, + "\/account\/sessions\/phone": { + "put": { + "summary": "Update phone session", + "operationId": "accountUpdatePhoneSession", + "tags": [ + "account" + ], + "description": "Use this endpoint to create a session from token. Provide the **userId** and **secret** parameters from the successful response of authentication flows initiated by token creation. For example, magic URL and phone login.", + "responses": { + "201": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePhoneSession", + "group": "sessions", + "weight": 28, + "cookies": false, + "type": "", + "deprecated": true, + "demo": "account\/update-phone-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "ip:{ip},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + } + } + } + }, + "\/account\/sessions\/token": { + "post": { + "summary": "Create session", + "operationId": "accountCreateSession", + "tags": [ + "account" + ], + "description": "Use this endpoint to create a session from token. Provide the **userId** and **secret** parameters from the successful response of authentication flows initiated by token creation. For example, magic URL and phone login.", + "responses": { + "201": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "createSession", + "group": "sessions", + "weight": 19, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "ip:{ip},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Secret of a token generated by login methods. For example, the `createMagicURLToken` or `createPhoneToken` methods.", + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + } + } + } + }, + "\/account\/sessions\/{sessionId}": { + "get": { + "summary": "Get session", + "operationId": "accountGetSession", + "tags": [ + "account" + ], + "description": "Use this endpoint to get a logged in user's session using a Session ID. Inputting 'current' will return the current session being used.", + "responses": { + "200": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "getSession", + "group": "sessions", + "weight": 14, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get-session.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "description": "Session ID. Use the string 'current' to get the current device session.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SESSION_ID>" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update session", + "operationId": "accountUpdateSession", + "tags": [ + "account" + ], + "description": "Use this endpoint to extend a session's length. Extending a session is useful when session expiry is short. If the session was created using an OAuth provider, this endpoint refreshes the access token from the provider.", + "responses": { + "200": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "updateSession", + "group": "sessions", + "weight": 16, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "description": "Session ID. Use the string 'current' to update the current device session.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SESSION_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete session", + "operationId": "accountDeleteSession", + "tags": [ + "account" + ], + "description": "Logout the user. Use 'current' as the session ID to logout on this device, use a session ID to logout on another device. If you're looking to logout the user on all devices, use [Delete Sessions](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#deleteSessions) instead.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSession", + "group": "sessions", + "weight": 15, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-session.md", + "rate-limit": 100, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "description": "Session ID. Use the string 'current' to delete the current device session.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SESSION_ID>" + }, + "in": "path" + } + ] + } + }, + "\/account\/status": { + "patch": { + "summary": "Update status", + "operationId": "accountUpdateStatus", + "tags": [ + "account" + ], + "description": "Block the currently logged in user account. Behind the scene, the user record is not deleted but permanently blocked from any access. To completely delete a user, use the Users API instead.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateStatus", + "group": "account", + "weight": 38, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/account\/tokens\/email": { + "post": { + "summary": "Create email token (OTP)", + "operationId": "accountCreateEmailToken", + "tags": [ + "account" + ], + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not be registered, a new user will be created. Use the returned user ID and secret and submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The secret sent to the user's email is valid for 15 minutes.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createEmailToken", + "group": "tokens", + "weight": 26, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-email-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-email.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},email:{param-email}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "phrase": { + "type": "boolean", + "description": "Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.", + "x-example": false + } + }, + "required": [ + "userId", + "email" + ] + } + } + } + } + } + }, + "\/account\/tokens\/magic-url": { + "post": { + "summary": "Create magic URL token", + "operationId": "accountCreateMagicURLToken", + "tags": [ + "account" + ], + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createMagicURLToken", + "group": "tokens", + "weight": 25, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-magic-u-r-l-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-magic-url.md", + "rate-limit": 60, + "rate-time": 3600, + "rate-key": [ + "url:{url},email:{param-email}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "x-example": "https:\/\/example.com" + }, + "phrase": { + "type": "boolean", + "description": "Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.", + "x-example": false + } + }, + "required": [ + "userId", + "email" + ] + } + } + } + } + } + }, + "\/account\/tokens\/oauth2\/{provider}": { + "get": { + "summary": "Create OAuth2 token", + "operationId": "accountCreateOAuth2Token", + "tags": [ + "account" + ], + "description": "Allow the user to login to their account using the OAuth2 provider of their choice. Each OAuth2 provider should be enabled from the Appwrite console first. Use the success and failure arguments to provide a redirect URL's back to your app when login is completed. \n\nIf authentication succeeds, `userId` and `secret` of a token will be appended to the success URL as query parameters. These can be used to create a new session using the [Create session](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "301": { + "description": "File" + } + }, + "x-appwrite": { + "method": "createOAuth2Token", + "group": "tokens", + "weight": 24, + "cookies": false, + "type": "webAuth", + "deprecated": false, + "demo": "account\/create-o-auth2token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-oauth2.md", + "rate-limit": 50, + "rate-time": 3600, + "rate-key": "ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "provider", + "description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.", + "required": true, + "schema": { + "type": "string", + "x-example": "amazon", + "enum": [ + "amazon", + "apple", + "auth0", + "authentik", + "autodesk", + "bitbucket", + "bitly", + "box", + "dailymotion", + "discord", + "disqus", + "dropbox", + "etsy", + "facebook", + "figma", + "github", + "gitlab", + "google", + "linkedin", + "microsoft", + "notion", + "oidc", + "okta", + "paypal", + "paypalSandbox", + "podio", + "salesforce", + "slack", + "spotify", + "stripe", + "tradeshift", + "tradeshiftBox", + "twitch", + "wordpress", + "yahoo", + "yammer", + "yandex", + "zoho", + "zoom", + "mock" + ], + "x-enum-name": "OAuthProvider", + "x-enum-keys": [] + }, + "in": "path" + }, + { + "name": "success", + "description": "URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "schema": { + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "" + }, + "in": "query" + }, + { + "name": "failure", + "description": "URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "schema": { + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "" + }, + "in": "query" + }, + { + "name": "scopes", + "description": "A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of 100 scopes are allowed, each 4096 characters long.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/account\/tokens\/phone": { + "post": { + "summary": "Create phone token", + "operationId": "accountCreatePhoneToken", + "tags": [ + "account" + ], + "description": "Sends the user an SMS with a secret key for creating a session. If the provided user ID has not be registered, a new user will be created. Use the returned user ID and secret and submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The secret sent to the user's phone is valid for 15 minutes.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createPhoneToken", + "group": "tokens", + "weight": 29, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-phone-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-phone.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},phone:{param-phone}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "x-example": "+12065550100" + } + }, + "required": [ + "userId", + "phone" + ] + } + } + } + } + } + }, + "\/account\/verification": { + "post": { + "summary": "Create email verification", + "operationId": "accountCreateVerification", + "tags": [ + "account" + ], + "description": "Use this endpoint to send a verification message to your user email address to confirm they are the valid owners of that address. Both the **userId** and **secret** arguments will be passed as query parameters to the URL you have provided to be attached to the verification email. The provided URL should redirect the user back to your app and allow you to complete the verification process by verifying both the **userId** and **secret** parameters. Learn more about how to [complete the verification process](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updateVerification). The verification link sent to the user's email address is valid for 7 days.\n\nPlease note that in order to avoid a [Redirect Attack](https:\/\/github.com\/OWASP\/CheatSheetSeries\/blob\/master\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md), the only valid redirect URLs are the ones from domains you have set when adding your platforms in the console interface.\n", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createVerification", + "group": "verification", + "weight": 41, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-email-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{userId}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "x-example": "https:\/\/example.com" + } + }, + "required": [ + "url" + ] + } + } + } + } + }, + "put": { + "summary": "Update email verification (confirmation)", + "operationId": "accountUpdateVerification", + "tags": [ + "account" + ], + "description": "Use this endpoint to complete the user email verification process. Use both the **userId** and **secret** parameters that were attached to your app URL to verify the user email ownership. If confirmed this route will return a 200 status code.", + "responses": { + "200": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "updateVerification", + "group": "verification", + "weight": 42, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-email-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{param-userId}", + "scope": "public", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + } + } + } + }, + "\/account\/verification\/phone": { + "post": { + "summary": "Create phone verification", + "operationId": "accountCreatePhoneVerification", + "tags": [ + "account" + ], + "description": "Use this endpoint to send a verification SMS to the currently logged in user. This endpoint is meant for use after updating a user's phone number using the [accountUpdatePhone](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updatePhone) endpoint. Learn more about how to [complete the verification process](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updatePhoneVerification). The verification code sent to the user's phone number is valid for 15 minutes.", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createPhoneVerification", + "group": "verification", + "weight": 43, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-phone-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-phone-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},userId:{userId}", + "url:{url},ip:{ip}" + ], + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "put": { + "summary": "Update phone verification (confirmation)", + "operationId": "accountUpdatePhoneVerification", + "tags": [ + "account" + ], + "description": "Use this endpoint to complete the user phone verification process. Use the **userId** and **secret** that were sent to your user's phone number to verify the user email ownership. If confirmed this route will return a 200 status code.", + "responses": { + "200": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePhoneVerification", + "group": "verification", + "weight": 44, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-phone-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-phone-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "userId:{param-userId}", + "scope": "public", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + } + } + } + }, + "\/avatars\/browsers\/{code}": { + "get": { + "summary": "Get browser icon", + "operationId": "avatarsGetBrowser", + "tags": [ + "avatars" + ], + "description": "You can use this endpoint to show different browser icons to your users. The code argument receives the browser code as it appears in your user [GET \/account\/sessions](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#getSessions) endpoint. Use width, height and quality arguments to change the output settings.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getBrowser", + "group": null, + "weight": 61, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-browser.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-browser.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "code", + "description": "Browser Code.", + "required": true, + "schema": { + "type": "string", + "x-example": "aa", + "enum": [ + "aa", + "an", + "ch", + "ci", + "cm", + "cr", + "ff", + "sf", + "mf", + "ps", + "oi", + "om", + "op", + "on" + ], + "x-enum-name": "Browser", + "x-enum-keys": [ + "Avant Browser", + "Android WebView Beta", + "Google Chrome", + "Google Chrome (iOS)", + "Google Chrome (Mobile)", + "Chromium", + "Mozilla Firefox", + "Safari", + "Mobile Safari", + "Microsoft Edge", + "Microsoft Edge (iOS)", + "Opera Mini", + "Opera", + "Opera (Next)" + ] + }, + "in": "path" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "in": "query" + }, + { + "name": "quality", + "description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1 + }, + "in": "query" + } + ] + } + }, + "\/avatars\/credit-cards\/{code}": { + "get": { + "summary": "Get credit card icon", + "operationId": "avatarsGetCreditCard", + "tags": [ + "avatars" + ], + "description": "The credit card endpoint will return you the icon of the credit card provider you need. Use width, height and quality arguments to change the output settings.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.\n", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getCreditCard", + "group": null, + "weight": 60, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-credit-card.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-credit-card.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "code", + "description": "Credit Card Code. Possible values: amex, argencard, cabal, cencosud, diners, discover, elo, hipercard, jcb, mastercard, naranja, targeta-shopping, union-china-pay, visa, mir, maestro, rupay.", + "required": true, + "schema": { + "type": "string", + "x-example": "amex", + "enum": [ + "amex", + "argencard", + "cabal", + "cencosud", + "diners", + "discover", + "elo", + "hipercard", + "jcb", + "mastercard", + "naranja", + "targeta-shopping", + "union-china-pay", + "visa", + "mir", + "maestro", + "rupay" + ], + "x-enum-name": "CreditCard", + "x-enum-keys": [ + "American Express", + "Argencard", + "Cabal", + "Cencosud", + "Diners Club", + "Discover", + "Elo", + "Hipercard", + "JCB", + "Mastercard", + "Naranja", + "Tarjeta Shopping", + "Union China Pay", + "Visa", + "MIR", + "Maestro", + "Rupay" + ] + }, + "in": "path" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "in": "query" + }, + { + "name": "quality", + "description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1 + }, + "in": "query" + } + ] + } + }, + "\/avatars\/favicon": { + "get": { + "summary": "Get favicon", + "operationId": "avatarsGetFavicon", + "tags": [ + "avatars" + ], + "description": "Use this endpoint to fetch the favorite icon (AKA favicon) of any remote website URL.\n\nThis endpoint does not follow HTTP redirects.", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getFavicon", + "group": null, + "weight": 64, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-favicon.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-favicon.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "url", + "description": "Website URL which you want to fetch the favicon from.", + "required": true, + "schema": { + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com" + }, + "in": "query" + } + ] + } + }, + "\/avatars\/flags\/{code}": { + "get": { + "summary": "Get country flag", + "operationId": "avatarsGetFlag", + "tags": [ + "avatars" + ], + "description": "You can use this endpoint to show different country flags icons to your users. The code argument receives the 2 letter country code. Use width, height and quality arguments to change the output settings. Country codes follow the [ISO 3166-1](https:\/\/en.wikipedia.org\/wiki\/ISO_3166-1) standard.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.\n", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getFlag", + "group": null, + "weight": 62, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-flag.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-flag.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "code", + "description": "Country Code. ISO Alpha-2 country code format.", + "required": true, + "schema": { + "type": "string", + "x-example": "af", + "enum": [ + "af", + "ao", + "al", + "ad", + "ae", + "ar", + "am", + "ag", + "au", + "at", + "az", + "bi", + "be", + "bj", + "bf", + "bd", + "bg", + "bh", + "bs", + "ba", + "by", + "bz", + "bo", + "br", + "bb", + "bn", + "bt", + "bw", + "cf", + "ca", + "ch", + "cl", + "cn", + "ci", + "cm", + "cd", + "cg", + "co", + "km", + "cv", + "cr", + "cu", + "cy", + "cz", + "de", + "dj", + "dm", + "dk", + "do", + "dz", + "ec", + "eg", + "er", + "es", + "ee", + "et", + "fi", + "fj", + "fr", + "fm", + "ga", + "gb", + "ge", + "gh", + "gn", + "gm", + "gw", + "gq", + "gr", + "gd", + "gt", + "gy", + "hn", + "hr", + "ht", + "hu", + "id", + "in", + "ie", + "ir", + "iq", + "is", + "il", + "it", + "jm", + "jo", + "jp", + "kz", + "ke", + "kg", + "kh", + "ki", + "kn", + "kr", + "kw", + "la", + "lb", + "lr", + "ly", + "lc", + "li", + "lk", + "ls", + "lt", + "lu", + "lv", + "ma", + "mc", + "md", + "mg", + "mv", + "mx", + "mh", + "mk", + "ml", + "mt", + "mm", + "me", + "mn", + "mz", + "mr", + "mu", + "mw", + "my", + "na", + "ne", + "ng", + "ni", + "nl", + "no", + "np", + "nr", + "nz", + "om", + "pk", + "pa", + "pe", + "ph", + "pw", + "pg", + "pl", + "pf", + "kp", + "pt", + "py", + "qa", + "ro", + "ru", + "rw", + "sa", + "sd", + "sn", + "sg", + "sb", + "sl", + "sv", + "sm", + "so", + "rs", + "ss", + "st", + "sr", + "sk", + "si", + "se", + "sz", + "sc", + "sy", + "td", + "tg", + "th", + "tj", + "tm", + "tl", + "to", + "tt", + "tn", + "tr", + "tv", + "tz", + "ug", + "ua", + "uy", + "us", + "uz", + "va", + "vc", + "ve", + "vn", + "vu", + "ws", + "ye", + "za", + "zm", + "zw" + ], + "x-enum-name": "Flag", + "x-enum-keys": [ + "Afghanistan", + "Angola", + "Albania", + "Andorra", + "United Arab Emirates", + "Argentina", + "Armenia", + "Antigua and Barbuda", + "Australia", + "Austria", + "Azerbaijan", + "Burundi", + "Belgium", + "Benin", + "Burkina Faso", + "Bangladesh", + "Bulgaria", + "Bahrain", + "Bahamas", + "Bosnia and Herzegovina", + "Belarus", + "Belize", + "Bolivia", + "Brazil", + "Barbados", + "Brunei Darussalam", + "Bhutan", + "Botswana", + "Central African Republic", + "Canada", + "Switzerland", + "Chile", + "China", + "C\u00f4te d'Ivoire", + "Cameroon", + "Democratic Republic of the Congo", + "Republic of the Congo", + "Colombia", + "Comoros", + "Cape Verde", + "Costa Rica", + "Cuba", + "Cyprus", + "Czech Republic", + "Germany", + "Djibouti", + "Dominica", + "Denmark", + "Dominican Republic", + "Algeria", + "Ecuador", + "Egypt", + "Eritrea", + "Spain", + "Estonia", + "Ethiopia", + "Finland", + "Fiji", + "France", + "Micronesia (Federated States of)", + "Gabon", + "United Kingdom", + "Georgia", + "Ghana", + "Guinea", + "Gambia", + "Guinea-Bissau", + "Equatorial Guinea", + "Greece", + "Grenada", + "Guatemala", + "Guyana", + "Honduras", + "Croatia", + "Haiti", + "Hungary", + "Indonesia", + "India", + "Ireland", + "Iran (Islamic Republic of)", + "Iraq", + "Iceland", + "Israel", + "Italy", + "Jamaica", + "Jordan", + "Japan", + "Kazakhstan", + "Kenya", + "Kyrgyzstan", + "Cambodia", + "Kiribati", + "Saint Kitts and Nevis", + "South Korea", + "Kuwait", + "Lao People's Democratic Republic", + "Lebanon", + "Liberia", + "Libya", + "Saint Lucia", + "Liechtenstein", + "Sri Lanka", + "Lesotho", + "Lithuania", + "Luxembourg", + "Latvia", + "Morocco", + "Monaco", + "Moldova", + "Madagascar", + "Maldives", + "Mexico", + "Marshall Islands", + "North Macedonia", + "Mali", + "Malta", + "Myanmar", + "Montenegro", + "Mongolia", + "Mozambique", + "Mauritania", + "Mauritius", + "Malawi", + "Malaysia", + "Namibia", + "Niger", + "Nigeria", + "Nicaragua", + "Netherlands", + "Norway", + "Nepal", + "Nauru", + "New Zealand", + "Oman", + "Pakistan", + "Panama", + "Peru", + "Philippines", + "Palau", + "Papua New Guinea", + "Poland", + "French Polynesia", + "North Korea", + "Portugal", + "Paraguay", + "Qatar", + "Romania", + "Russia", + "Rwanda", + "Saudi Arabia", + "Sudan", + "Senegal", + "Singapore", + "Solomon Islands", + "Sierra Leone", + "El Salvador", + "San Marino", + "Somalia", + "Serbia", + "South Sudan", + "Sao Tome and Principe", + "Suriname", + "Slovakia", + "Slovenia", + "Sweden", + "Eswatini", + "Seychelles", + "Syria", + "Chad", + "Togo", + "Thailand", + "Tajikistan", + "Turkmenistan", + "Timor-Leste", + "Tonga", + "Trinidad and Tobago", + "Tunisia", + "Turkey", + "Tuvalu", + "Tanzania", + "Uganda", + "Ukraine", + "Uruguay", + "United States", + "Uzbekistan", + "Vatican City", + "Saint Vincent and the Grenadines", + "Venezuela", + "Vietnam", + "Vanuatu", + "Samoa", + "Yemen", + "South Africa", + "Zambia", + "Zimbabwe" + ] + }, + "in": "path" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100 + }, + "in": "query" + }, + { + "name": "quality", + "description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1 + }, + "in": "query" + } + ] + } + }, + "\/avatars\/image": { + "get": { + "summary": "Get image from URL", + "operationId": "avatarsGetImage", + "tags": [ + "avatars" + ], + "description": "Use this endpoint to fetch a remote image URL and crop it to any image size you want. This endpoint is very useful if you need to crop and display remote images in your app or in case you want to make sure a 3rd party image is properly served using a TLS protocol.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 400x400px.\n\nThis endpoint does not follow HTTP redirects.", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getImage", + "group": null, + "weight": 63, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-image.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-image.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "url", + "description": "Image URL which you want to crop.", + "required": true, + "schema": { + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com" + }, + "in": "query" + }, + { + "name": "width", + "description": "Resize preview image width, Pass an integer between 0 to 2000. Defaults to 400.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 400 + }, + "in": "query" + }, + { + "name": "height", + "description": "Resize preview image height, Pass an integer between 0 to 2000. Defaults to 400.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 400 + }, + "in": "query" + } + ] + } + }, + "\/avatars\/initials": { + "get": { + "summary": "Get user initials", + "operationId": "avatarsGetInitials", + "tags": [ + "avatars" + ], + "description": "Use this endpoint to show your user initials avatar icon on your website or app. By default, this route will try to print your logged-in user name or email initials. You can also overwrite the user name if you pass the 'name' parameter. If no name is given and no user is logged, an empty avatar will be returned.\n\nYou can use the color and background params to change the avatar colors. By default, a random theme will be selected. The random theme will persist for the user's initials when reloading the same theme will always return for the same initials.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.\n", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getInitials", + "group": null, + "weight": 66, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-initials.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-initials.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "name", + "description": "Full Name. When empty, current user name or email will be used. Max length: 128 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<NAME>", + "default": "" + }, + "in": "query" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 500 + }, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 500 + }, + "in": "query" + }, + { + "name": "background", + "description": "Changes background color. By default a random color will be picked and stay will persistent to the given name.", + "required": false, + "schema": { + "type": "string", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/avatars\/qr": { + "get": { + "summary": "Get QR code", + "operationId": "avatarsGetQR", + "tags": [ + "avatars" + ], + "description": "Converts a given plain text to a QR code image. You can use the query parameters to change the size and style of the resulting image.\n", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getQR", + "group": null, + "weight": 65, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-q-r.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-qr.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "text", + "description": "Plain text to be converted to QR code image.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEXT>" + }, + "in": "query" + }, + { + "name": "size", + "description": "QR code size. Pass an integer between 1 to 1000. Defaults to 400.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 1, + "default": 400 + }, + "in": "query" + }, + { + "name": "margin", + "description": "Margin from edge. Pass an integer between 0 to 10. Defaults to 1.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 1 + }, + "in": "query" + }, + { + "name": "download", + "description": "Return resulting image with 'Content-Disposition: attachment ' headers for the browser to start downloading it. Pass 0 for no header, or 1 for otherwise. Default value is set to 0.", + "required": false, + "schema": { + "type": "boolean", + "x-example": false, + "default": false + }, + "in": "query" + } + ] + } + }, + "\/databases": { + "get": { + "summary": "List databases", + "operationId": "databasesList", + "tags": [ + "databases" + ], + "description": "Get a list of all databases from the current Appwrite project. You can use the search parameter to filter your results.", + "responses": { + "200": { + "description": "Databases List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/databaseList" + } + } + } + } + }, + "x-appwrite": { + "method": "list", + "group": "databases", + "weight": 71, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create database", + "operationId": "databasesCreate", + "tags": [ + "databases" + ], + "description": "Create a new Database.\n", + "responses": { + "201": { + "description": "Database", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/database" + } + } + } + } + }, + "x-appwrite": { + "method": "create", + "group": "databases", + "weight": 70, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "databaseId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<DATABASE_ID>" + }, + "name": { + "type": "string", + "description": "Database name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Is the database enabled? When set to 'disabled', users cannot access the database but Server SDKs with an API key can still read and write to the database. No data is lost when this is toggled.", + "x-example": false + } + }, + "required": [ + "databaseId", + "name" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}": { + "get": { + "summary": "Get database", + "operationId": "databasesGet", + "tags": [ + "databases" + ], + "description": "Get a database by its unique ID. This endpoint response returns a JSON object with the database metadata.", + "responses": { + "200": { + "description": "Database", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/database" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": "databases", + "weight": 72, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update database", + "operationId": "databasesUpdate", + "tags": [ + "databases" + ], + "description": "Update a database by its unique ID.", + "responses": { + "200": { + "description": "Database", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/database" + } + } + } + } + }, + "x-appwrite": { + "method": "update", + "group": "databases", + "weight": 74, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Database name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Is database enabled? When set to 'disabled', users cannot access the database but Server SDKs with an API key can still read and write to the database. No data is lost when this is toggled.", + "x-example": false + } + }, + "required": [ + "name" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete database", + "operationId": "databasesDelete", + "tags": [ + "databases" + ], + "description": "Delete a database by its unique ID. Only API keys with with databases.write scope can delete a database.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "databases", + "weight": 75, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections": { + "get": { + "summary": "List collections", + "operationId": "databasesListCollections", + "tags": [ + "databases" + ], + "description": "Get a list of all collections that belong to the provided databaseId. You can use the search parameter to filter your results.", + "responses": { + "200": { + "description": "Collections List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/collectionList" + } + } + } + } + }, + "x-appwrite": { + "method": "listCollections", + "group": "collections", + "weight": 77, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-collections.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-collections.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, enabled, documentSecurity", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create collection", + "operationId": "databasesCreateCollection", + "tags": [ + "databases" + ], + "description": "Create a new Collection. Before using this route, you should create a new database resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "201": { + "description": "Collection", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/collection" + } + } + } + } + }, + "x-appwrite": { + "method": "createCollection", + "group": "collections", + "weight": 76, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-collection.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-collection.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "collectionId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<COLLECTION_ID>" + }, + "name": { + "type": "string", + "description": "Collection name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "documentSecurity": { + "type": "boolean", + "description": "Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Is collection enabled? When set to 'disabled', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.", + "x-example": false + } + }, + "required": [ + "collectionId", + "name" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}": { + "get": { + "summary": "Get collection", + "operationId": "databasesGetCollection", + "tags": [ + "databases" + ], + "description": "Get a collection by its unique ID. This endpoint response returns a JSON object with the collection metadata.", + "responses": { + "200": { + "description": "Collection", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/collection" + } + } + } + } + }, + "x-appwrite": { + "method": "getCollection", + "group": "collections", + "weight": 78, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-collection.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-collection.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update collection", + "operationId": "databasesUpdateCollection", + "tags": [ + "databases" + ], + "description": "Update a collection by its unique ID.", + "responses": { + "200": { + "description": "Collection", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/collection" + } + } + } + } + }, + "x-appwrite": { + "method": "updateCollection", + "group": "collections", + "weight": 80, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-collection.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-collection.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Collection name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "permissions": { + "type": "array", + "description": "An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "documentSecurity": { + "type": "boolean", + "description": "Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Is collection enabled? When set to 'disabled', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.", + "x-example": false + } + }, + "required": [ + "name" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete collection", + "operationId": "databasesDeleteCollection", + "tags": [ + "databases" + ], + "description": "Delete a collection by its unique ID. Only users with write permissions have access to delete this resource.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteCollection", + "group": "collections", + "weight": 81, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-collection.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-collection.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes": { + "get": { + "summary": "List attributes", + "operationId": "databasesListAttributes", + "tags": [ + "databases" + ], + "description": "List attributes in the collection.", + "responses": { + "200": { + "description": "Attributes List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeList" + } + } + } + } + }, + "x-appwrite": { + "method": "listAttributes", + "group": "attributes", + "weight": 92, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-attributes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-attributes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: key, type, size, required, array, status, error", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/boolean": { + "post": { + "summary": "Create boolean attribute", + "operationId": "databasesCreateBooleanAttribute", + "tags": [ + "databases" + ], + "description": "Create a boolean attribute.\n", + "responses": { + "202": { + "description": "AttributeBoolean", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeBoolean" + } + } + } + } + }, + "x-appwrite": { + "method": "createBooleanAttribute", + "group": "attributes", + "weight": 89, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-boolean-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-boolean-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "boolean", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": false + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/boolean\/{key}": { + "patch": { + "summary": "Update boolean attribute", + "operationId": "databasesUpdateBooleanAttribute", + "tags": [ + "databases" + ], + "description": "Update a boolean attribute. Changing the `default` value will not update already existing documents.", + "responses": { + "200": { + "description": "AttributeBoolean", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeBoolean" + } + } + } + } + }, + "x-appwrite": { + "method": "updateBooleanAttribute", + "group": "attributes", + "weight": 101, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-boolean-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-boolean-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "boolean", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": false, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/datetime": { + "post": { + "summary": "Create datetime attribute", + "operationId": "databasesCreateDatetimeAttribute", + "tags": [ + "databases" + ], + "description": "Create a date time attribute according to the ISO 8601 standard.", + "responses": { + "202": { + "description": "AttributeDatetime", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeDatetime" + } + } + } + } + }, + "x-appwrite": { + "method": "createDatetimeAttribute", + "group": "attributes", + "weight": 90, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-datetime-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-datetime-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for the attribute in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when attribute is required.", + "x-example": null + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/datetime\/{key}": { + "patch": { + "summary": "Update dateTime attribute", + "operationId": "databasesUpdateDatetimeAttribute", + "tags": [ + "databases" + ], + "description": "Update a date time attribute. Changing the `default` value will not update already existing documents.", + "responses": { + "200": { + "description": "AttributeDatetime", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeDatetime" + } + } + } + } + }, + "x-appwrite": { + "method": "updateDatetimeAttribute", + "group": "attributes", + "weight": 102, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-datetime-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-datetime-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": null, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/email": { + "post": { + "summary": "Create email attribute", + "operationId": "databasesCreateEmailAttribute", + "tags": [ + "databases" + ], + "description": "Create an email attribute.\n", + "responses": { + "202": { + "description": "AttributeEmail", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeEmail" + } + } + } + } + }, + "x-appwrite": { + "method": "createEmailAttribute", + "group": "attributes", + "weight": 83, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-email-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-email-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "email@example.com" + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/email\/{key}": { + "patch": { + "summary": "Update email attribute", + "operationId": "databasesUpdateEmailAttribute", + "tags": [ + "databases" + ], + "description": "Update an email attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeEmail", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeEmail" + } + } + } + } + }, + "x-appwrite": { + "method": "updateEmailAttribute", + "group": "attributes", + "weight": 95, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-email-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-email-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "email@example.com", + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/enum": { + "post": { + "summary": "Create enum attribute", + "operationId": "databasesCreateEnumAttribute", + "tags": [ + "databases" + ], + "description": "Create an enumeration attribute. The `elements` param acts as a white-list of accepted values for this attribute. \n", + "responses": { + "202": { + "description": "AttributeEnum", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeEnum" + } + } + } + } + }, + "x-appwrite": { + "method": "createEnumAttribute", + "group": "attributes", + "weight": 84, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-enum-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-attribute-enum.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "elements": { + "type": "array", + "description": "Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of 100 elements are allowed, each 255 characters long.", + "x-example": null, + "items": { + "type": "string" + } + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "<DEFAULT>" + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false + } + }, + "required": [ + "key", + "elements", + "required" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/enum\/{key}": { + "patch": { + "summary": "Update enum attribute", + "operationId": "databasesUpdateEnumAttribute", + "tags": [ + "databases" + ], + "description": "Update an enum attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeEnum", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeEnum" + } + } + } + } + }, + "x-appwrite": { + "method": "updateEnumAttribute", + "group": "attributes", + "weight": 96, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-enum-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-enum-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "elements": { + "type": "array", + "description": "Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of 100 elements are allowed, each 255 characters long.", + "x-example": null, + "items": { + "type": "string" + } + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "<DEFAULT>", + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + }, + "required": [ + "elements", + "required", + "default" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/float": { + "post": { + "summary": "Create float attribute", + "operationId": "databasesCreateFloatAttribute", + "tags": [ + "databases" + ], + "description": "Create a float attribute. Optionally, minimum and maximum values can be provided.\n", + "responses": { + "202": { + "description": "AttributeFloat", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeFloat" + } + } + } + } + }, + "x-appwrite": { + "method": "createFloatAttribute", + "group": "attributes", + "weight": 88, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-float-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-float-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "min": { + "type": "number", + "description": "Minimum value to enforce on new documents", + "x-example": null + }, + "max": { + "type": "number", + "description": "Maximum value to enforce on new documents", + "x-example": null + }, + "default": { + "type": "number", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": null + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/float\/{key}": { + "patch": { + "summary": "Update float attribute", + "operationId": "databasesUpdateFloatAttribute", + "tags": [ + "databases" + ], + "description": "Update a float attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeFloat", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeFloat" + } + } + } + } + }, + "x-appwrite": { + "method": "updateFloatAttribute", + "group": "attributes", + "weight": 100, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-float-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-float-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "min": { + "type": "number", + "description": "Minimum value to enforce on new documents", + "x-example": null + }, + "max": { + "type": "number", + "description": "Maximum value to enforce on new documents", + "x-example": null + }, + "default": { + "type": "number", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": null, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/integer": { + "post": { + "summary": "Create integer attribute", + "operationId": "databasesCreateIntegerAttribute", + "tags": [ + "databases" + ], + "description": "Create an integer attribute. Optionally, minimum and maximum values can be provided.\n", + "responses": { + "202": { + "description": "AttributeInteger", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeInteger" + } + } + } + } + }, + "x-appwrite": { + "method": "createIntegerAttribute", + "group": "attributes", + "weight": 87, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-integer-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-integer-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "min": { + "type": "integer", + "description": "Minimum value to enforce on new documents", + "x-example": null + }, + "max": { + "type": "integer", + "description": "Maximum value to enforce on new documents", + "x-example": null + }, + "default": { + "type": "integer", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": null + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/integer\/{key}": { + "patch": { + "summary": "Update integer attribute", + "operationId": "databasesUpdateIntegerAttribute", + "tags": [ + "databases" + ], + "description": "Update an integer attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeInteger", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeInteger" + } + } + } + } + }, + "x-appwrite": { + "method": "updateIntegerAttribute", + "group": "attributes", + "weight": 99, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-integer-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-integer-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "min": { + "type": "integer", + "description": "Minimum value to enforce on new documents", + "x-example": null + }, + "max": { + "type": "integer", + "description": "Maximum value to enforce on new documents", + "x-example": null + }, + "default": { + "type": "integer", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": null, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/ip": { + "post": { + "summary": "Create IP address attribute", + "operationId": "databasesCreateIpAttribute", + "tags": [ + "databases" + ], + "description": "Create IP address attribute.\n", + "responses": { + "202": { + "description": "AttributeIP", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeIp" + } + } + } + } + }, + "x-appwrite": { + "method": "createIpAttribute", + "group": "attributes", + "weight": 85, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-ip-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-ip-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": null + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/ip\/{key}": { + "patch": { + "summary": "Update IP address attribute", + "operationId": "databasesUpdateIpAttribute", + "tags": [ + "databases" + ], + "description": "Update an ip attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeIP", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeIp" + } + } + } + } + }, + "x-appwrite": { + "method": "updateIpAttribute", + "group": "attributes", + "weight": 97, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-ip-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-ip-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": null, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/relationship": { + "post": { + "summary": "Create relationship attribute", + "operationId": "databasesCreateRelationshipAttribute", + "tags": [ + "databases" + ], + "description": "Create relationship attribute. [Learn more about relationship attributes](https:\/\/appwrite.io\/docs\/databases-relationships#relationship-attributes).\n", + "responses": { + "202": { + "description": "AttributeRelationship", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeRelationship" + } + } + } + } + }, + "x-appwrite": { + "method": "createRelationshipAttribute", + "group": "attributes", + "weight": 91, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-relationship-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-relationship-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "relatedCollectionId": { + "type": "string", + "description": "Related Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "x-example": "<RELATED_COLLECTION_ID>" + }, + "type": { + "type": "string", + "description": "Relation type", + "x-example": "oneToOne", + "enum": [ + "oneToOne", + "manyToOne", + "manyToMany", + "oneToMany" + ], + "x-enum-name": "RelationshipType", + "x-enum-keys": [] + }, + "twoWay": { + "type": "boolean", + "description": "Is Two Way?", + "x-example": false + }, + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "twoWayKey": { + "type": "string", + "description": "Two Way Attribute Key.", + "x-example": null + }, + "onDelete": { + "type": "string", + "description": "Constraints option", + "x-example": "cascade", + "enum": [ + "cascade", + "restrict", + "setNull" + ], + "x-enum-name": "RelationMutate", + "x-enum-keys": [] + } + }, + "required": [ + "relatedCollectionId", + "type" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/string": { + "post": { + "summary": "Create string attribute", + "operationId": "databasesCreateStringAttribute", + "tags": [ + "databases" + ], + "description": "Create a string attribute.\n", + "responses": { + "202": { + "description": "AttributeString", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeString" + } + } + } + } + }, + "x-appwrite": { + "method": "createStringAttribute", + "group": "attributes", + "weight": 82, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-string-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-string-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "size": { + "type": "integer", + "description": "Attribute size for text attributes, in number of characters.", + "x-example": 1 + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "<DEFAULT>" + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false + }, + "encrypt": { + "type": "boolean", + "description": "Toggle encryption for the attribute. Encryption enhances security by not storing any plain text values in the database. However, encrypted attributes cannot be queried.", + "x-example": false + } + }, + "required": [ + "key", + "size", + "required" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/string\/{key}": { + "patch": { + "summary": "Update string attribute", + "operationId": "databasesUpdateStringAttribute", + "tags": [ + "databases" + ], + "description": "Update a string attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeString", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeString" + } + } + } + } + }, + "x-appwrite": { + "method": "updateStringAttribute", + "group": "attributes", + "weight": 94, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-string-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-string-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "<DEFAULT>", + "x-nullable": true + }, + "size": { + "type": "integer", + "description": "Maximum size of the string attribute.", + "x-example": 1 + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/url": { + "post": { + "summary": "Create URL attribute", + "operationId": "databasesCreateUrlAttribute", + "tags": [ + "databases" + ], + "description": "Create a URL attribute.\n", + "responses": { + "202": { + "description": "AttributeURL", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeUrl" + } + } + } + } + }, + "x-appwrite": { + "method": "createUrlAttribute", + "group": "attributes", + "weight": 86, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-url-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-url-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "https:\/\/example.com" + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/url\/{key}": { + "patch": { + "summary": "Update URL attribute", + "operationId": "databasesUpdateUrlAttribute", + "tags": [ + "databases" + ], + "description": "Update an url attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeURL", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeUrl" + } + } + } + } + }, + "x-appwrite": { + "method": "updateUrlAttribute", + "group": "attributes", + "weight": 98, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-url-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-url-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "https:\/\/example.com", + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/{key}": { + "get": { + "summary": "Get attribute", + "operationId": "databasesGetAttribute", + "tags": [ + "databases" + ], + "description": "Get attribute by ID.", + "responses": { + "200": { + "description": "AttributeBoolean, or AttributeInteger, or AttributeFloat, or AttributeEmail, or AttributeEnum, or AttributeURL, or AttributeIP, or AttributeDatetime, or AttributeRelationship, or AttributeString", + "content": { + "application\/json": { + "schema": { + "oneOf": [ + { + "$ref": "#\/components\/schemas\/attributeBoolean" + }, + { + "$ref": "#\/components\/schemas\/attributeInteger" + }, + { + "$ref": "#\/components\/schemas\/attributeFloat" + }, + { + "$ref": "#\/components\/schemas\/attributeEmail" + }, + { + "$ref": "#\/components\/schemas\/attributeEnum" + }, + { + "$ref": "#\/components\/schemas\/attributeUrl" + }, + { + "$ref": "#\/components\/schemas\/attributeIp" + }, + { + "$ref": "#\/components\/schemas\/attributeDatetime" + }, + { + "$ref": "#\/components\/schemas\/attributeRelationship" + }, + { + "$ref": "#\/components\/schemas\/attributeString" + } + ] + } + } + } + } + }, + "x-appwrite": { + "method": "getAttribute", + "group": "attributes", + "weight": 93, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete attribute", + "operationId": "databasesDeleteAttribute", + "tags": [ + "databases" + ], + "description": "Deletes an attribute.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteAttribute", + "group": "attributes", + "weight": 104, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/{key}\/relationship": { + "patch": { + "summary": "Update relationship attribute", + "operationId": "databasesUpdateRelationshipAttribute", + "tags": [ + "databases" + ], + "description": "Update relationship attribute. [Learn more about relationship attributes](https:\/\/appwrite.io\/docs\/databases-relationships#relationship-attributes).\n", + "responses": { + "200": { + "description": "AttributeRelationship", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/attributeRelationship" + } + } + } + } + }, + "x-appwrite": { + "method": "updateRelationshipAttribute", + "group": "attributes", + "weight": 103, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-relationship-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-relationship-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "onDelete": { + "type": "string", + "description": "Constraints option", + "x-example": "cascade", + "enum": [ + "cascade", + "restrict", + "setNull" + ], + "x-enum-name": "RelationMutate", + "x-enum-keys": [] + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "x-example": null + } + } + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents": { + "get": { + "summary": "List documents", + "operationId": "databasesListDocuments", + "tags": [ + "databases" + ], + "description": "Get a list of all the user's documents in a given collection. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Documents List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/documentList" + } + } + } + } + }, + "x-appwrite": { + "method": "listDocuments", + "group": "documents", + "weight": 110, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-documents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-documents.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create document", + "operationId": "databasesCreateDocument", + "tags": [ + "databases" + ], + "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "201": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "createDocument", + "group": "documents", + "weight": 109, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "methods": [ + { + "name": "createDocument", + "auth": { + "Session": [], + "Key": [], + "JWT": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documentId", + "data", + "permissions" + ], + "required": [ + "databaseId", + "collectionId", + "documentId", + "data" + ], + "responses": [ + { + "code": 201, + "model": "#\/components\/schemas\/document" + } + ], + "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/components\/schemas\/documentList" + } + ], + "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + } + ], + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection). Make sure to define attributes before creating documents.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "documentId": { + "type": "string", + "description": "Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<DOCUMENT_ID>" + }, + "data": { + "type": "object", + "description": "Document data as JSON object.", + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "documents": { + "type": "array", + "description": "Array of documents data as JSON objects.", + "x-example": null, + "items": { + "type": "object" + } + } + } + } + } + } + } + }, + "put": { + "summary": "Create or update documents", + "operationId": "databasesUpsertDocuments", + "tags": [ + "databases" + ], + "description": "Create or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n", + "responses": { + "200": { + "description": "Documents List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/documentList" + } + } + } + } + }, + "x-appwrite": { + "method": "upsertDocuments", + "group": "documents", + "weight": 118, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-documents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-documents.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "documents": { + "type": "array", + "description": "Array of document data as JSON objects. May contain partial documents.", + "x-example": null, + "items": { + "type": "object" + } + } + }, + "required": [ + "documents" + ] + } + } + } + } + }, + "patch": { + "summary": "Update documents", + "operationId": "databasesUpdateDocuments", + "tags": [ + "databases" + ], + "description": "Update all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", + "responses": { + "200": { + "description": "Documents List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/documentList" + } + } + } + } + }, + "x-appwrite": { + "method": "updateDocuments", + "group": "documents", + "weight": 117, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-documents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-documents.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include only attribute and value pairs to be updated.", + "x-example": "{}" + }, + "queries": { + "type": "array", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "x-example": null, + "items": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete documents", + "operationId": "databasesDeleteDocuments", + "tags": [ + "databases" + ], + "description": "Bulk delete documents using queries, if no queries are passed then all documents are deleted.", + "responses": { + "200": { + "description": "Documents List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/documentList" + } + } + } + } + }, + "x-appwrite": { + "method": "deleteDocuments", + "group": "documents", + "weight": 120, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-documents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-documents.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "queries": { + "type": "array", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "x-example": null, + "items": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}": { + "get": { + "summary": "Get document", + "operationId": "databasesGetDocument", + "tags": [ + "databases" + ], + "description": "Get a document by its unique ID. This endpoint response returns a JSON object with the document data.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "getDocument", + "group": "documents", + "weight": 111, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-document.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DOCUMENT_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "put": { + "summary": "Upsert document", + "operationId": "databasesUpsertDocument", + "tags": [ + "databases" + ], + "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "upsertDocument", + "group": "documents", + "weight": 114, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DOCUMENT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include all required attributes of the document to be created or updated.", + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "data" + ] + } + } + } + } + }, + "patch": { + "summary": "Update document", + "operationId": "databasesUpdateDocument", + "tags": [ + "databases" + ], + "description": "Update a document by its unique ID. Using the patch method you can pass only specific fields that will get updated.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "updateDocument", + "group": "documents", + "weight": 113, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DOCUMENT_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include only attribute and value pairs to be updated.", + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete document", + "operationId": "databasesDeleteDocument", + "tags": [ + "databases" + ], + "description": "Delete a document by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDocument", + "group": "documents", + "weight": 119, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-document.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DOCUMENT_ID>" + }, + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/decrement": { + "patch": { + "summary": "Decrement document attribute", + "operationId": "databasesDecrementDocumentAttribute", + "tags": [ + "databases" + ], + "description": "Decrement a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "decrementDocumentAttribute", + "group": "documents", + "weight": 116, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/decrement-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/decrement-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DOCUMENT_ID>" + }, + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to decrement the attribute by. The value must be a number.", + "x-example": null + }, + "min": { + "type": "mixed", + "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", + "x-example": null + } + } + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/increment": { + "patch": { + "summary": "Increment document attribute", + "operationId": "databasesIncrementDocumentAttribute", + "tags": [ + "databases" + ], + "description": "Increment a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "incrementDocumentAttribute", + "group": "documents", + "weight": 115, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/increment-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/increment-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DOCUMENT_ID>" + }, + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to increment the attribute by. The value must be a number.", + "x-example": null + }, + "max": { + "type": "mixed", + "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", + "x-example": null + } + } + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/indexes": { + "get": { + "summary": "List indexes", + "operationId": "databasesListIndexes", + "tags": [ + "databases" + ], + "description": "List indexes in the collection.", + "responses": { + "200": { + "description": "Indexes List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/indexList" + } + } + } + } + }, + "x-appwrite": { + "method": "listIndexes", + "group": "indexes", + "weight": 106, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-indexes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-indexes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: key, type, status, attributes, error", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create index", + "operationId": "databasesCreateIndex", + "tags": [ + "databases" + ], + "description": "Creates an index on the attributes listed. Your index should include all the attributes you will query in a single request.\nAttributes can be `key`, `fulltext`, and `unique`.", + "responses": { + "202": { + "description": "Index", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/index" + } + } + } + } + }, + "x-appwrite": { + "method": "createIndex", + "group": "collections", + "weight": 105, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-index.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-index.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Index Key.", + "x-example": null + }, + "type": { + "type": "string", + "description": "Index type.", + "x-example": "key", + "enum": [ + "key", + "fulltext", + "unique" + ], + "x-enum-name": "IndexType", + "x-enum-keys": [] + }, + "attributes": { + "type": "array", + "description": "Array of attributes to index. Maximum of 100 attributes are allowed, each 32 characters long.", + "x-example": null, + "items": { + "type": "string" + } + }, + "orders": { + "type": "array", + "description": "Array of index orders. Maximum of 100 orders are allowed.", + "x-example": null, + "items": { + "type": "string" + } + }, + "lengths": { + "type": "array", + "description": "Length of index. Maximum of 100", + "x-example": null, + "items": { + "type": "integer" + } + } + }, + "required": [ + "key", + "type", + "attributes" + ] + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/indexes\/{key}": { + "get": { + "summary": "Get index", + "operationId": "databasesGetIndex", + "tags": [ + "databases" + ], + "description": "Get index by ID.", + "responses": { + "200": { + "description": "Index", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/index" + } + } + } + } + }, + "x-appwrite": { + "method": "getIndex", + "group": "indexes", + "weight": 107, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-index.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-index.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "key", + "description": "Index Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete index", + "operationId": "databasesDeleteIndex", + "tags": [ + "databases" + ], + "description": "Delete an index.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteIndex", + "group": "indexes", + "weight": 108, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-index.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-index.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "key", + "description": "Index Key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ] + } + }, + "\/functions": { + "get": { + "summary": "List functions", + "operationId": "functionsList", + "tags": [ + "functions" + ], + "description": "Get a list of all the project's functions. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Functions List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/functionList" + } + } + } + } + }, + "x-appwrite": { + "method": "list", + "group": "functions", + "weight": 378, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the project's functions. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, enabled, runtime, deploymentId, schedule, scheduleNext, schedulePrevious, timeout, entrypoint, commands, installationId", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create function", + "operationId": "functionsCreate", + "tags": [ + "functions" + ], + "description": "Create a new function. You can pass a list of [permissions](https:\/\/appwrite.io\/docs\/permissions) to allow different project users or team with access to execute the function using the client API.", + "responses": { + "201": { + "description": "Function", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/function" + } + } + } + } + }, + "x-appwrite": { + "method": "create", + "group": "functions", + "weight": 375, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new function. You can pass a list of [permissions](https:\/\/appwrite.io\/docs\/permissions) to allow different project users or team with access to execute the function using the client API.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "functionId": { + "type": "string", + "description": "Function ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<FUNCTION_ID>" + }, + "name": { + "type": "string", + "description": "Function name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "runtime": { + "type": "string", + "description": "Execution runtime.", + "x-example": "node-14.5", + "enum": [ + "node-14.5", + "node-16.0", + "node-18.0", + "node-19.0", + "node-20.0", + "node-21.0", + "node-22", + "php-8.0", + "php-8.1", + "php-8.2", + "php-8.3", + "ruby-3.0", + "ruby-3.1", + "ruby-3.2", + "ruby-3.3", + "python-3.8", + "python-3.9", + "python-3.10", + "python-3.11", + "python-3.12", + "python-ml-3.11", + "python-ml-3.12", + "deno-1.21", + "deno-1.24", + "deno-1.35", + "deno-1.40", + "deno-1.46", + "deno-2.0", + "dart-2.15", + "dart-2.16", + "dart-2.17", + "dart-2.18", + "dart-2.19", + "dart-3.0", + "dart-3.1", + "dart-3.3", + "dart-3.5", + "dart-3.8", + "dotnet-6.0", + "dotnet-7.0", + "dotnet-8.0", + "java-8.0", + "java-11.0", + "java-17.0", + "java-18.0", + "java-21.0", + "java-22", + "swift-5.5", + "swift-5.8", + "swift-5.9", + "swift-5.10", + "kotlin-1.6", + "kotlin-1.8", + "kotlin-1.9", + "kotlin-2.0", + "cpp-17", + "cpp-20", + "bun-1.0", + "bun-1.1", + "go-1.23", + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29", + "flutter-3.32" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "execute": { + "type": "array", + "description": "An array of role strings with execution permissions. By default no user is granted with any execute permissions. [learn more about roles](https:\/\/appwrite.io\/docs\/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.", + "x-example": "[\"any\"]", + "items": { + "type": "string" + } + }, + "events": { + "type": "array", + "description": "Events list. Maximum of 100 events are allowed.", + "x-example": null, + "items": { + "type": "string" + } + }, + "schedule": { + "type": "string", + "description": "Schedule CRON syntax.", + "x-example": null + }, + "timeout": { + "type": "integer", + "description": "Function maximum execution time in seconds.", + "x-example": 1 + }, + "enabled": { + "type": "boolean", + "description": "Is function enabled? When set to 'disabled', users cannot access the function but Server SDKs with and API key can still access the function. No data is lost when this is toggled.", + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", + "x-example": false + }, + "entrypoint": { + "type": "string", + "description": "Entrypoint File. This path is relative to the \"providerRootDirectory\".", + "x-example": "<ENTRYPOINT>" + }, + "commands": { + "type": "string", + "description": "Build Commands.", + "x-example": "<COMMANDS>" + }, + "scopes": { + "type": "array", + "description": "List of scopes allowed for API key auto-generated for every execution. Maximum of 100 scopes are allowed.", + "x-example": null, + "items": { + "type": "string" + } + }, + "installationId": { + "type": "string", + "description": "Appwrite Installation ID for VCS (Version Control System) deployment.", + "x-example": "<INSTALLATION_ID>" + }, + "providerRepositoryId": { + "type": "string", + "description": "Repository ID of the repo linked to the function.", + "x-example": "<PROVIDER_REPOSITORY_ID>" + }, + "providerBranch": { + "type": "string", + "description": "Production branch for the repo linked to the function.", + "x-example": "<PROVIDER_BRANCH>" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is the VCS (Version Control System) connection in silent mode for the repo linked to the function? In silent mode, comments will not be made on commits and pull requests.", + "x-example": false + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to function code in the linked repo.", + "x-example": "<PROVIDER_ROOT_DIRECTORY>" + }, + "specification": { + "type": "string", + "description": "Runtime specification for the function and builds.", + "x-example": null + } + }, + "required": [ + "functionId", + "name", + "runtime" + ] + } + } + } + } + } + }, + "\/functions\/runtimes": { + "get": { + "summary": "List runtimes", + "operationId": "functionsListRuntimes", + "tags": [ + "functions" + ], + "description": "Get a list of all runtimes that are currently active on your instance.", + "responses": { + "200": { + "description": "Runtimes List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/runtimeList" + } + } + } + } + }, + "x-appwrite": { + "method": "listRuntimes", + "group": "runtimes", + "weight": 380, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-runtimes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all runtimes that are currently active on your instance.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/functions\/specifications": { + "get": { + "summary": "List specifications", + "operationId": "functionsListSpecifications", + "tags": [ + "functions" + ], + "description": "List allowed function specifications for this instance.", + "responses": { + "200": { + "description": "Specifications List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/specificationList" + } + } + } + } + }, + "x-appwrite": { + "method": "listSpecifications", + "group": "runtimes", + "weight": 381, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-specifications.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList allowed function specifications for this instance.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/functions\/{functionId}": { + "get": { + "summary": "Get function", + "operationId": "functionsGet", + "tags": [ + "functions" + ], + "description": "Get a function by its unique ID.", + "responses": { + "200": { + "description": "Function", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/function" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": "functions", + "weight": 376, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update function", + "operationId": "functionsUpdate", + "tags": [ + "functions" + ], + "description": "Update function by its unique ID.", + "responses": { + "200": { + "description": "Function", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/function" + } + } + } + } + }, + "x-appwrite": { + "method": "update", + "group": "functions", + "weight": 377, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/update.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate function by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Function name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "runtime": { + "type": "string", + "description": "Execution runtime.", + "x-example": "node-14.5", + "enum": [ + "node-14.5", + "node-16.0", + "node-18.0", + "node-19.0", + "node-20.0", + "node-21.0", + "node-22", + "php-8.0", + "php-8.1", + "php-8.2", + "php-8.3", + "ruby-3.0", + "ruby-3.1", + "ruby-3.2", + "ruby-3.3", + "python-3.8", + "python-3.9", + "python-3.10", + "python-3.11", + "python-3.12", + "python-ml-3.11", + "python-ml-3.12", + "deno-1.21", + "deno-1.24", + "deno-1.35", + "deno-1.40", + "deno-1.46", + "deno-2.0", + "dart-2.15", + "dart-2.16", + "dart-2.17", + "dart-2.18", + "dart-2.19", + "dart-3.0", + "dart-3.1", + "dart-3.3", + "dart-3.5", + "dart-3.8", + "dotnet-6.0", + "dotnet-7.0", + "dotnet-8.0", + "java-8.0", + "java-11.0", + "java-17.0", + "java-18.0", + "java-21.0", + "java-22", + "swift-5.5", + "swift-5.8", + "swift-5.9", + "swift-5.10", + "kotlin-1.6", + "kotlin-1.8", + "kotlin-1.9", + "kotlin-2.0", + "cpp-17", + "cpp-20", + "bun-1.0", + "bun-1.1", + "go-1.23", + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29", + "flutter-3.32" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "execute": { + "type": "array", + "description": "An array of role strings with execution permissions. By default no user is granted with any execute permissions. [learn more about roles](https:\/\/appwrite.io\/docs\/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.", + "x-example": "[\"any\"]", + "items": { + "type": "string" + } + }, + "events": { + "type": "array", + "description": "Events list. Maximum of 100 events are allowed.", + "x-example": null, + "items": { + "type": "string" + } + }, + "schedule": { + "type": "string", + "description": "Schedule CRON syntax.", + "x-example": null + }, + "timeout": { + "type": "integer", + "description": "Maximum execution time in seconds.", + "x-example": 1 + }, + "enabled": { + "type": "boolean", + "description": "Is function enabled? When set to 'disabled', users cannot access the function but Server SDKs with and API key can still access the function. No data is lost when this is toggled.", + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", + "x-example": false + }, + "entrypoint": { + "type": "string", + "description": "Entrypoint File. This path is relative to the \"providerRootDirectory\".", + "x-example": "<ENTRYPOINT>" + }, + "commands": { + "type": "string", + "description": "Build Commands.", + "x-example": "<COMMANDS>" + }, + "scopes": { + "type": "array", + "description": "List of scopes allowed for API Key auto-generated for every execution. Maximum of 100 scopes are allowed.", + "x-example": null, + "items": { + "type": "string" + } + }, + "installationId": { + "type": "string", + "description": "Appwrite Installation ID for VCS (Version Controle System) deployment.", + "x-example": "<INSTALLATION_ID>" + }, + "providerRepositoryId": { + "type": "string", + "description": "Repository ID of the repo linked to the function", + "x-example": "<PROVIDER_REPOSITORY_ID>", + "x-nullable": true + }, + "providerBranch": { + "type": "string", + "description": "Production branch for the repo linked to the function", + "x-example": "<PROVIDER_BRANCH>" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is the VCS (Version Control System) connection in silent mode for the repo linked to the function? In silent mode, comments will not be made on commits and pull requests.", + "x-example": false + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to function code in the linked repo.", + "x-example": "<PROVIDER_ROOT_DIRECTORY>" + }, + "specification": { + "type": "string", + "description": "Runtime specification for the function and builds.", + "x-example": null + } + }, + "required": [ + "name" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete function", + "operationId": "functionsDelete", + "tags": [ + "functions" + ], + "description": "Delete a function by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "functions", + "weight": 379, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a function by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + } + ] + } + }, + "\/functions\/{functionId}\/deployment": { + "patch": { + "summary": "Update function's deployment", + "operationId": "functionsUpdateFunctionDeployment", + "tags": [ + "functions" + ], + "description": "Update the function active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your function.", + "responses": { + "200": { + "description": "Function", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/function" + } + } + } + } + }, + "x-appwrite": { + "method": "updateFunctionDeployment", + "group": "functions", + "weight": 384, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/update-function-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate the function active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your function.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "deploymentId": { + "type": "string", + "description": "Deployment ID.", + "x-example": "<DEPLOYMENT_ID>" + } + }, + "required": [ + "deploymentId" + ] + } + } + } + } + } + }, + "\/functions\/{functionId}\/deployments": { + "get": { + "summary": "List deployments", + "operationId": "functionsListDeployments", + "tags": [ + "functions" + ], + "description": "Get a list of all the function's code deployments. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Deployments List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deploymentList" + } + } + } + } + }, + "x-appwrite": { + "method": "listDeployments", + "group": "deployments", + "weight": 385, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-deployments.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the function's code deployments. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create deployment", + "operationId": "functionsCreateDeployment", + "tags": [ + "functions" + ], + "description": "Create a new function code deployment. Use this endpoint to upload a new version of your code function. To execute your newly uploaded code, you'll need to update the function's deployment to use your new deployment UID.\n\nThis endpoint accepts a tar.gz file compressed with your code. Make sure to include any dependencies your code has within the compressed file. You can learn more about code packaging in the [Appwrite Cloud Functions tutorial](https:\/\/appwrite.io\/docs\/functions).\n\nUse the \"command\" param to set the entrypoint used to execute your code.", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createDeployment", + "group": "deployments", + "weight": 382, + "cookies": false, + "type": "upload", + "deprecated": false, + "demo": "functions\/create-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new function code deployment. Use this endpoint to upload a new version of your code function. To execute your newly uploaded code, you'll need to update the function's deployment to use your new deployment UID.\n\nThis endpoint accepts a tar.gz file compressed with your code. Make sure to include any dependencies your code has within the compressed file. You can learn more about code packaging in the [Appwrite Cloud Functions tutorial](https:\/\/appwrite.io\/docs\/functions).\n\nUse the \"command\" param to set the entrypoint used to execute your code.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": true, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "multipart\/form-data": { + "schema": { + "type": "object", + "properties": { + "entrypoint": { + "type": "string", + "description": "Entrypoint File.", + "x-example": "<ENTRYPOINT>" + }, + "commands": { + "type": "string", + "description": "Build Commands.", + "x-example": "<COMMANDS>" + }, + "code": { + "type": "string", + "description": "Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.", + "x-example": null + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "x-example": false + } + }, + "required": [ + "code", + "activate" + ] + } + } + } + } + } + }, + "\/functions\/{functionId}\/deployments\/duplicate": { + "post": { + "summary": "Create duplicate deployment", + "operationId": "functionsCreateDuplicateDeployment", + "tags": [ + "functions" + ], + "description": "Create a new build for an existing function deployment. This endpoint allows you to rebuild a deployment with the updated function configuration, including its entrypoint and build commands if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createDuplicateDeployment", + "group": "deployments", + "weight": 390, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-duplicate-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new build for an existing function deployment. This endpoint allows you to rebuild a deployment with the updated function configuration, including its entrypoint and build commands if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "deploymentId": { + "type": "string", + "description": "Deployment ID.", + "x-example": "<DEPLOYMENT_ID>" + }, + "buildId": { + "type": "string", + "description": "Build unique ID.", + "x-example": "<BUILD_ID>" + } + }, + "required": [ + "deploymentId" + ] + } + } + } + } + } + }, + "\/functions\/{functionId}\/deployments\/template": { + "post": { + "summary": "Create template deployment", + "operationId": "functionsCreateTemplateDeployment", + "tags": [ + "functions" + ], + "description": "Create a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/functions#listTemplates) to find the template details.", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createTemplateDeployment", + "group": "deployments", + "weight": 387, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-template-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/functions#listTemplates) to find the template details.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "repository": { + "type": "string", + "description": "Repository name of the template.", + "x-example": "<REPOSITORY>" + }, + "owner": { + "type": "string", + "description": "The name of the owner of the template.", + "x-example": "<OWNER>" + }, + "rootDirectory": { + "type": "string", + "description": "Path to function code in the template repo.", + "x-example": "<ROOT_DIRECTORY>" + }, + "version": { + "type": "string", + "description": "Version (tag) for the repo linked to the function template.", + "x-example": "<VERSION>" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "x-example": false + } + }, + "required": [ + "repository", + "owner", + "rootDirectory", + "version" + ] + } + } + } + } + } + }, + "\/functions\/{functionId}\/deployments\/vcs": { + "post": { + "summary": "Create VCS deployment", + "operationId": "functionsCreateVcsDeployment", + "tags": [ + "functions" + ], + "description": "Create a deployment when a function is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createVcsDeployment", + "group": "deployments", + "weight": 388, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-vcs-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment when a function is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Type of reference passed. Allowed values are: branch, commit", + "x-example": "branch", + "enum": [ + "branch", + "commit" + ], + "x-enum-name": "VCSDeploymentType", + "x-enum-keys": [] + }, + "reference": { + "type": "string", + "description": "VCS reference to create deployment from. Depending on type this can be: branch name, commit hash", + "x-example": "<REFERENCE>" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "x-example": false + } + }, + "required": [ + "type", + "reference" + ] + } + } + } + } + } + }, + "\/functions\/{functionId}\/deployments\/{deploymentId}": { + "get": { + "summary": "Get deployment", + "operationId": "functionsGetDeployment", + "tags": [ + "functions" + ], + "description": "Get a function deployment by its unique ID.", + "responses": { + "200": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "getDeployment", + "group": "deployments", + "weight": 383, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function deployment by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DEPLOYMENT_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete deployment", + "operationId": "functionsDeleteDeployment", + "tags": [ + "functions" + ], + "description": "Delete a code deployment by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDeployment", + "group": "deployments", + "weight": 386, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/delete-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a code deployment by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DEPLOYMENT_ID>" + }, + "in": "path" + } + ] + } + }, + "\/functions\/{functionId}\/deployments\/{deploymentId}\/download": { + "get": { + "summary": "Get deployment download", + "operationId": "functionsGetDeploymentDownload", + "tags": [ + "functions" + ], + "description": "Get a function deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "responses": { + "200": { + "description": "File" + } + }, + "x-appwrite": { + "method": "getDeploymentDownload", + "group": "deployments", + "weight": 389, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "functions\/get-deployment-download.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DEPLOYMENT_ID>" + }, + "in": "path" + }, + { + "name": "type", + "description": "Deployment file to download. Can be: \"source\", \"output\".", + "required": false, + "schema": { + "type": "string", + "x-example": "source", + "enum": [ + "source", + "output" + ], + "x-enum-name": "DeploymentDownloadType", + "x-enum-keys": [], + "default": "source" + }, + "in": "query" + } + ] + } + }, + "\/functions\/{functionId}\/deployments\/{deploymentId}\/status": { + "patch": { + "summary": "Update deployment status", + "operationId": "functionsUpdateDeploymentStatus", + "tags": [ + "functions" + ], + "description": "Cancel an ongoing function deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", + "responses": { + "200": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "updateDeploymentStatus", + "group": "deployments", + "weight": 391, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/update-deployment-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCancel an ongoing function deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DEPLOYMENT_ID>" + }, + "in": "path" + } + ] + } + }, + "\/functions\/{functionId}\/executions": { + "get": { + "summary": "List executions", + "operationId": "functionsListExecutions", + "tags": [ + "functions" + ], + "description": "Get a list of all the current user function execution logs. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Executions List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/executionList" + } + } + } + } + }, + "x-appwrite": { + "method": "listExecutions", + "group": "executions", + "weight": 394, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-executions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the current user function execution logs. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: trigger, status, responseStatusCode, duration, requestMethod, requestPath, deploymentId", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create execution", + "operationId": "functionsCreateExecution", + "tags": [ + "functions" + ], + "description": "Trigger a function execution. The returned object will return you the current execution status. You can ping the `Get Execution` endpoint to get updates on the current execution status. Once this endpoint is called, your function execution process will start asynchronously.", + "responses": { + "201": { + "description": "Execution", + "content": { + "multipart\/form-data": { + "schema": { + "$ref": "#\/components\/schemas\/execution" + } + } + } + } + }, + "x-appwrite": { + "method": "createExecution", + "group": "executions", + "weight": 392, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-execution.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterTrigger a function execution. The returned object will return you the current execution status. You can ping the `Get Execution` endpoint to get updates on the current execution status. Once this endpoint is called, your function execution process will start asynchronously.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "body": { + "type": "string", + "description": "HTTP body of execution. Default value is empty string.", + "x-example": "<BODY>" + }, + "async": { + "type": "boolean", + "description": "Execute code in the background. Default value is false.", + "x-example": false + }, + "path": { + "type": "string", + "description": "HTTP path of execution. Path can include query params. Default value is \/", + "x-example": "<PATH>" + }, + "method": { + "type": "string", + "description": "HTTP method of execution. Default value is GET.", + "x-example": "GET", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE", + "OPTIONS" + ], + "x-enum-name": "ExecutionMethod", + "x-enum-keys": [] + }, + "headers": { + "type": "string", + "description": "HTTP headers of execution. Defaults to empty.", + "x-example": null + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled execution time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes.", + "x-example": null + } + } + } + } + } + } + } + }, + "\/functions\/{functionId}\/executions\/{executionId}": { + "get": { + "summary": "Get execution", + "operationId": "functionsGetExecution", + "tags": [ + "functions" + ], + "description": "Get a function execution log by its unique ID.", + "responses": { + "200": { + "description": "Execution", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/execution" + } + } + } + } + }, + "x-appwrite": { + "method": "getExecution", + "group": "executions", + "weight": 393, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get-execution.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function execution log by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + }, + { + "name": "executionId", + "description": "Execution ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<EXECUTION_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete execution", + "operationId": "functionsDeleteExecution", + "tags": [ + "functions" + ], + "description": "Delete a function execution by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteExecution", + "group": "executions", + "weight": 395, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/delete-execution.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a function execution by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + }, + { + "name": "executionId", + "description": "Execution ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<EXECUTION_ID>" + }, + "in": "path" + } + ] + } + }, + "\/functions\/{functionId}\/variables": { + "get": { + "summary": "List variables", + "operationId": "functionsListVariables", + "tags": [ + "functions" + ], + "description": "Get a list of all variables of a specific function.", + "responses": { + "200": { + "description": "Variables List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variableList" + } + } + } + } + }, + "x-appwrite": { + "method": "listVariables", + "group": "variables", + "weight": 400, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-variables.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all variables of a specific function.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + } + ] + }, + "post": { + "summary": "Create variable", + "operationId": "functionsCreateVariable", + "tags": [ + "functions" + ], + "description": "Create a new function environment variable. These variables can be accessed in the function at runtime as environment variables.", + "responses": { + "201": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "createVariable", + "group": "variables", + "weight": 398, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new function environment variable. These variables can be accessed in the function at runtime as environment variables.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "x-example": "<KEY>" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "x-example": "<VALUE>" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only functions can read them during build and runtime.", + "x-example": false + } + }, + "required": [ + "key", + "value" + ] + } + } + } + } + } + }, + "\/functions\/{functionId}\/variables\/{variableId}": { + "get": { + "summary": "Get variable", + "operationId": "functionsGetVariable", + "tags": [ + "functions" + ], + "description": "Get a variable by its unique ID.", + "responses": { + "200": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "getVariable", + "group": "variables", + "weight": 399, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<VARIABLE_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update variable", + "operationId": "functionsUpdateVariable", + "tags": [ + "functions" + ], + "description": "Update variable by its unique ID.", + "responses": { + "200": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "updateVariable", + "group": "variables", + "weight": 401, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/update-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<VARIABLE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "x-example": "<KEY>" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "x-example": "<VALUE>" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only functions can read them during build and runtime.", + "x-example": false + } + }, + "required": [ + "key" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete variable", + "operationId": "functionsDeleteVariable", + "tags": [ + "functions" + ], + "description": "Delete a variable by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteVariable", + "group": "variables", + "weight": 402, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/delete-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FUNCTION_ID>" + }, + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<VARIABLE_ID>" + }, + "in": "path" + } + ] + } + }, + "\/graphql": { + "post": { + "summary": "GraphQL endpoint", + "operationId": "graphqlQuery", + "tags": [ + "graphql" + ], + "description": "Execute a GraphQL mutation.", + "responses": { + "200": { + "description": "Any", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/any" + } + } + } + } + }, + "x-appwrite": { + "method": "query", + "group": "graphql", + "weight": 308, + "cookies": false, + "type": "graphql", + "deprecated": false, + "demo": "graphql\/query.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/graphql\/post.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "url:{url},ip:{ip}", + "scope": "graphql", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/graphql\/mutation": { + "post": { + "summary": "GraphQL endpoint", + "operationId": "graphqlMutation", + "tags": [ + "graphql" + ], + "description": "Execute a GraphQL mutation.", + "responses": { + "200": { + "description": "Any", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/any" + } + } + } + } + }, + "x-appwrite": { + "method": "mutation", + "group": "graphql", + "weight": 307, + "cookies": false, + "type": "graphql", + "deprecated": false, + "demo": "graphql\/mutation.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/graphql\/post.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "url:{url},ip:{ip}", + "scope": "graphql", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/health": { + "get": { + "summary": "Get HTTP", + "operationId": "healthGet", + "tags": [ + "health" + ], + "description": "Check the Appwrite HTTP server is up and responsive.", + "responses": { + "200": { + "description": "Health Status", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthStatus" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": "health", + "weight": 132, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/anti-virus": { + "get": { + "summary": "Get antivirus", + "operationId": "healthGetAntivirus", + "tags": [ + "health" + ], + "description": "Check the Appwrite Antivirus server is up and connection is successful.", + "responses": { + "200": { + "description": "Health Antivirus", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthAntivirus" + } + } + } + } + }, + "x-appwrite": { + "method": "getAntivirus", + "group": "health", + "weight": 153, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-antivirus.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-storage-anti-virus.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/cache": { + "get": { + "summary": "Get cache", + "operationId": "healthGetCache", + "tags": [ + "health" + ], + "description": "Check the Appwrite in-memory cache servers are up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthStatus" + } + } + } + } + }, + "x-appwrite": { + "method": "getCache", + "group": "health", + "weight": 135, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-cache.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-cache.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/certificate": { + "get": { + "summary": "Get the SSL certificate for a domain", + "operationId": "healthGetCertificate", + "tags": [ + "health" + ], + "description": "Get the SSL certificate for a domain", + "responses": { + "200": { + "description": "Health Certificate", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthCertificate" + } + } + } + } + }, + "x-appwrite": { + "method": "getCertificate", + "group": "health", + "weight": 140, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-certificate.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-certificate.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "domain", + "description": "string", + "required": false, + "schema": { + "type": "string" + }, + "in": "query" + } + ] + } + }, + "\/health\/db": { + "get": { + "summary": "Get DB", + "operationId": "healthGetDB", + "tags": [ + "health" + ], + "description": "Check the Appwrite database servers are up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthStatus" + } + } + } + } + }, + "x-appwrite": { + "method": "getDB", + "group": "health", + "weight": 134, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-d-b.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-db.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/pubsub": { + "get": { + "summary": "Get pubsub", + "operationId": "healthGetPubSub", + "tags": [ + "health" + ], + "description": "Check the Appwrite pub-sub servers are up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthStatus" + } + } + } + } + }, + "x-appwrite": { + "method": "getPubSub", + "group": "health", + "weight": 136, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-pub-sub.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-pubsub.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/queue\/builds": { + "get": { + "summary": "Get builds queue", + "operationId": "healthGetQueueBuilds", + "tags": [ + "health" + ], + "description": "Get the number of builds that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueBuilds", + "group": "queue", + "weight": 142, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-builds.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-builds.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/certificates": { + "get": { + "summary": "Get certificates queue", + "operationId": "healthGetQueueCertificates", + "tags": [ + "health" + ], + "description": "Get the number of certificates that are waiting to be issued against [Letsencrypt](https:\/\/letsencrypt.org\/) in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueCertificates", + "group": "queue", + "weight": 141, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-certificates.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-certificates.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/databases": { + "get": { + "summary": "Get databases queue", + "operationId": "healthGetQueueDatabases", + "tags": [ + "health" + ], + "description": "Get the number of database changes that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueDatabases", + "group": "queue", + "weight": 143, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-databases.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-databases.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "name", + "description": "Queue name for which to check the queue size", + "required": false, + "schema": { + "type": "string", + "x-example": "<NAME>", + "default": "database_db_main" + }, + "in": "query" + }, + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/deletes": { + "get": { + "summary": "Get deletes queue", + "operationId": "healthGetQueueDeletes", + "tags": [ + "health" + ], + "description": "Get the number of background destructive changes that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueDeletes", + "group": "queue", + "weight": 144, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-deletes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-deletes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/failed\/{name}": { + "get": { + "summary": "Get number of failed queue jobs", + "operationId": "healthGetFailedJobs", + "tags": [ + "health" + ], + "description": "Returns the amount of failed jobs in a given queue.\n", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getFailedJobs", + "group": "queue", + "weight": 154, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-failed-jobs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-failed-queue-jobs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "name", + "description": "The name of the queue", + "required": true, + "schema": { + "type": "string", + "x-example": "v1-database", + "enum": [ + "v1-database", + "v1-deletes", + "v1-audits", + "v1-mails", + "v1-functions", + "v1-stats-resources", + "v1-stats-usage", + "v1-webhooks", + "v1-certificates", + "v1-builds", + "v1-messaging", + "v1-migrations" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "in": "path" + }, + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/functions": { + "get": { + "summary": "Get functions queue", + "operationId": "healthGetQueueFunctions", + "tags": [ + "health" + ], + "description": "Get the number of function executions that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueFunctions", + "group": "queue", + "weight": 148, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-functions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-functions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/logs": { + "get": { + "summary": "Get logs queue", + "operationId": "healthGetQueueLogs", + "tags": [ + "health" + ], + "description": "Get the number of logs that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueLogs", + "group": "queue", + "weight": 139, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/mails": { + "get": { + "summary": "Get mails queue", + "operationId": "healthGetQueueMails", + "tags": [ + "health" + ], + "description": "Get the number of mails that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueMails", + "group": "queue", + "weight": 145, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-mails.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-mails.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/messaging": { + "get": { + "summary": "Get messaging queue", + "operationId": "healthGetQueueMessaging", + "tags": [ + "health" + ], + "description": "Get the number of messages that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueMessaging", + "group": "queue", + "weight": 146, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-messaging.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-messaging.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/migrations": { + "get": { + "summary": "Get migrations queue", + "operationId": "healthGetQueueMigrations", + "tags": [ + "health" + ], + "description": "Get the number of migrations that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueMigrations", + "group": "queue", + "weight": 147, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-migrations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-migrations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/stats-resources": { + "get": { + "summary": "Get stats resources queue", + "operationId": "healthGetQueueStatsResources", + "tags": [ + "health" + ], + "description": "Get the number of metrics that are waiting to be processed in the Appwrite stats resources queue.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueStatsResources", + "group": "queue", + "weight": 149, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-stats-resources.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-resources.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/stats-usage": { + "get": { + "summary": "Get stats usage queue", + "operationId": "healthGetQueueUsage", + "tags": [ + "health" + ], + "description": "Get the number of metrics that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueUsage", + "group": "queue", + "weight": 150, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-usage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/queue\/webhooks": { + "get": { + "summary": "Get webhooks queue", + "operationId": "healthGetQueueWebhooks", + "tags": [ + "health" + ], + "description": "Get the number of webhooks that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthQueue" + } + } + } + } + }, + "x-appwrite": { + "method": "getQueueWebhooks", + "group": "queue", + "weight": 138, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-webhooks.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-webhooks.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "default": 5000 + }, + "in": "query" + } + ] + } + }, + "\/health\/storage": { + "get": { + "summary": "Get storage", + "operationId": "healthGetStorage", + "tags": [ + "health" + ], + "description": "Check the Appwrite storage device is up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthStatus" + } + } + } + } + }, + "x-appwrite": { + "method": "getStorage", + "group": "storage", + "weight": 152, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-storage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-storage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/storage\/local": { + "get": { + "summary": "Get local storage", + "operationId": "healthGetStorageLocal", + "tags": [ + "health" + ], + "description": "Check the Appwrite local storage device is up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthStatus" + } + } + } + } + }, + "x-appwrite": { + "method": "getStorageLocal", + "group": "storage", + "weight": 151, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-storage-local.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-storage-local.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/time": { + "get": { + "summary": "Get time", + "operationId": "healthGetTime", + "tags": [ + "health" + ], + "description": "Check the Appwrite server time is synced with Google remote NTP server. We use this technology to smoothly handle leap seconds with no disruptive events. The [Network Time Protocol](https:\/\/en.wikipedia.org\/wiki\/Network_Time_Protocol) (NTP) is used by hundreds of millions of computers and devices to synchronize their clocks over the Internet. If your computer sets its own clock, it likely uses NTP.", + "responses": { + "200": { + "description": "Health Time", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/healthTime" + } + } + } + } + }, + "x-appwrite": { + "method": "getTime", + "group": "health", + "weight": 137, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-time.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-time.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/locale": { + "get": { + "summary": "Get user locale", + "operationId": "localeGet", + "tags": [ + "locale" + ], + "description": "Get the current user location based on IP. Returns an object with user country code, country name, continent name, continent code, ip address and suggested currency. You can use the locale header to get the data in a supported language.\n\n([IP Geolocation by DB-IP](https:\/\/db-ip.com))", + "responses": { + "200": { + "description": "Locale", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/locale" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": null, + "weight": 124, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/get-locale.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/codes": { + "get": { + "summary": "List locale codes", + "operationId": "localeListCodes", + "tags": [ + "locale" + ], + "description": "List of all locale codes in [ISO 639-1](https:\/\/en.wikipedia.org\/wiki\/List_of_ISO_639-1_codes).", + "responses": { + "200": { + "description": "Locale codes list", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/localeCodeList" + } + } + } + } + }, + "x-appwrite": { + "method": "listCodes", + "group": null, + "weight": 125, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-locale-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/continents": { + "get": { + "summary": "List continents", + "operationId": "localeListContinents", + "tags": [ + "locale" + ], + "description": "List of all continents. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Continents List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/continentList" + } + } + } + } + }, + "x-appwrite": { + "method": "listContinents", + "group": null, + "weight": 129, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-continents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-continents.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/countries": { + "get": { + "summary": "List countries", + "operationId": "localeListCountries", + "tags": [ + "locale" + ], + "description": "List of all countries. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Countries List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/countryList" + } + } + } + } + }, + "x-appwrite": { + "method": "listCountries", + "group": null, + "weight": 126, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-countries.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-countries.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/countries\/eu": { + "get": { + "summary": "List EU countries", + "operationId": "localeListCountriesEU", + "tags": [ + "locale" + ], + "description": "List of all countries that are currently members of the EU. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Countries List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/countryList" + } + } + } + } + }, + "x-appwrite": { + "method": "listCountriesEU", + "group": null, + "weight": 127, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-countries-e-u.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-countries-eu.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/countries\/phones": { + "get": { + "summary": "List countries phone codes", + "operationId": "localeListCountriesPhones", + "tags": [ + "locale" + ], + "description": "List of all countries phone codes. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Phones List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/phoneList" + } + } + } + } + }, + "x-appwrite": { + "method": "listCountriesPhones", + "group": null, + "weight": 128, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-countries-phones.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-countries-phones.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/currencies": { + "get": { + "summary": "List currencies", + "operationId": "localeListCurrencies", + "tags": [ + "locale" + ], + "description": "List of all currencies, including currency symbol, name, plural, and decimal digits for all major and minor currencies. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Currencies List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/currencyList" + } + } + } + } + }, + "x-appwrite": { + "method": "listCurrencies", + "group": null, + "weight": 130, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-currencies.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-currencies.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/languages": { + "get": { + "summary": "List languages", + "operationId": "localeListLanguages", + "tags": [ + "locale" + ], + "description": "List of all languages classified by ISO 639-1 including 2-letter code, name in English, and name in the respective language.", + "responses": { + "200": { + "description": "Languages List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/languageList" + } + } + } + } + }, + "x-appwrite": { + "method": "listLanguages", + "group": null, + "weight": 131, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-languages.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-languages.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/messaging\/messages": { + "get": { + "summary": "List messages", + "operationId": "messagingListMessages", + "tags": [ + "messaging" + ], + "description": "Get a list of all messages from the current Appwrite project.", + "responses": { + "200": { + "description": "Message list", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/messageList" + } + } + } + } + }, + "x-appwrite": { + "method": "listMessages", + "group": "messages", + "weight": 362, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-messages.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-messages.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: scheduledAt, deliveredAt, deliveredTotal, status, description, providerType", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/messaging\/messages\/email": { + "post": { + "summary": "Create email", + "operationId": "messagingCreateEmail", + "tags": [ + "messaging" + ], + "description": "Create a new email message.", + "responses": { + "201": { + "description": "Message", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/message" + } + } + } + } + }, + "x-appwrite": { + "method": "createEmail", + "group": "messages", + "weight": 359, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-email.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "messageId": { + "type": "string", + "description": "Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<MESSAGE_ID>" + }, + "subject": { + "type": "string", + "description": "Email Subject.", + "x-example": "<SUBJECT>" + }, + "content": { + "type": "string", + "description": "Email Content.", + "x-example": "<CONTENT>" + }, + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "cc": { + "type": "array", + "description": "Array of target IDs to be added as CC.", + "x-example": null, + "items": { + "type": "string" + } + }, + "bcc": { + "type": "array", + "description": "Array of target IDs to be added as BCC.", + "x-example": null, + "items": { + "type": "string" + } + }, + "attachments": { + "type": "array", + "description": "Array of compound ID strings of bucket IDs and file IDs to be attached to the email. They should be formatted as <BUCKET_ID>:<FILE_ID>.", + "x-example": null, + "items": { + "type": "string" + } + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "x-example": false + }, + "html": { + "type": "boolean", + "description": "Is content of type HTML", + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "x-example": null + } + }, + "required": [ + "messageId", + "subject", + "content" + ] + } + } + } + } + } + }, + "\/messaging\/messages\/email\/{messageId}": { + "patch": { + "summary": "Update email", + "operationId": "messagingUpdateEmail", + "tags": [ + "messaging" + ], + "description": "Update an email message by its unique ID. This endpoint only works on messages that are in draft status. Messages that are already processing, sent, or failed cannot be updated.\n", + "responses": { + "200": { + "description": "Message", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/message" + } + } + } + } + }, + "x-appwrite": { + "method": "updateEmail", + "group": "messages", + "weight": 366, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-email.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MESSAGE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "subject": { + "type": "string", + "description": "Email Subject.", + "x-example": "<SUBJECT>" + }, + "content": { + "type": "string", + "description": "Email Content.", + "x-example": "<CONTENT>" + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "x-example": false + }, + "html": { + "type": "boolean", + "description": "Is content of type HTML", + "x-example": false + }, + "cc": { + "type": "array", + "description": "Array of target IDs to be added as CC.", + "x-example": null, + "items": { + "type": "string" + } + }, + "bcc": { + "type": "array", + "description": "Array of target IDs to be added as BCC.", + "x-example": null, + "items": { + "type": "string" + } + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "x-example": null + }, + "attachments": { + "type": "array", + "description": "Array of compound ID strings of bucket IDs and file IDs to be attached to the email. They should be formatted as <BUCKET_ID>:<FILE_ID>.", + "x-example": null, + "items": { + "type": "string" + } + } + } + } + } + } + } + } + }, + "\/messaging\/messages\/push": { + "post": { + "summary": "Create push notification", + "operationId": "messagingCreatePush", + "tags": [ + "messaging" + ], + "description": "Create a new push notification.", + "responses": { + "201": { + "description": "Message", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/message" + } + } + } + } + }, + "x-appwrite": { + "method": "createPush", + "group": "messages", + "weight": 361, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-push.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-push.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "messageId": { + "type": "string", + "description": "Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<MESSAGE_ID>" + }, + "title": { + "type": "string", + "description": "Title for push notification.", + "x-example": "<TITLE>" + }, + "body": { + "type": "string", + "description": "Body for push notification.", + "x-example": "<BODY>" + }, + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "data": { + "type": "object", + "description": "Additional key-value pair data for push notification.", + "x-example": "{}" + }, + "action": { + "type": "string", + "description": "Action for push notification.", + "x-example": "<ACTION>" + }, + "image": { + "type": "string", + "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as <BUCKET_ID>:<FILE_ID>.", + "x-example": "[ID1:ID2]" + }, + "icon": { + "type": "string", + "description": "Icon for push notification. Available only for Android and Web Platform.", + "x-example": "<ICON>" + }, + "sound": { + "type": "string", + "description": "Sound for push notification. Available only for Android and iOS Platform.", + "x-example": "<SOUND>" + }, + "color": { + "type": "string", + "description": "Color for push notification. Available only for Android Platform.", + "x-example": "<COLOR>" + }, + "tag": { + "type": "string", + "description": "Tag for push notification. Available only for Android Platform.", + "x-example": "<TAG>" + }, + "badge": { + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "x-example": null + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device state and may not deliver notifications immediately. \"high\" will always attempt to immediately deliver the notification.", + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": "MessagePriority", + "x-enum-keys": [] + } + }, + "required": [ + "messageId" + ] + } + } + } + } + } + }, + "\/messaging\/messages\/push\/{messageId}": { + "patch": { + "summary": "Update push notification", + "operationId": "messagingUpdatePush", + "tags": [ + "messaging" + ], + "description": "Update a push notification by its unique ID. This endpoint only works on messages that are in draft status. Messages that are already processing, sent, or failed cannot be updated.\n", + "responses": { + "200": { + "description": "Message", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/message" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePush", + "group": "messages", + "weight": 368, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-push.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-push.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MESSAGE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "title": { + "type": "string", + "description": "Title for push notification.", + "x-example": "<TITLE>" + }, + "body": { + "type": "string", + "description": "Body for push notification.", + "x-example": "<BODY>" + }, + "data": { + "type": "object", + "description": "Additional Data for push notification.", + "x-example": "{}" + }, + "action": { + "type": "string", + "description": "Action for push notification.", + "x-example": "<ACTION>" + }, + "image": { + "type": "string", + "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as <BUCKET_ID>:<FILE_ID>.", + "x-example": "[ID1:ID2]" + }, + "icon": { + "type": "string", + "description": "Icon for push notification. Available only for Android and Web platforms.", + "x-example": "<ICON>" + }, + "sound": { + "type": "string", + "description": "Sound for push notification. Available only for Android and iOS platforms.", + "x-example": "<SOUND>" + }, + "color": { + "type": "string", + "description": "Color for push notification. Available only for Android platforms.", + "x-example": "<COLOR>" + }, + "tag": { + "type": "string", + "description": "Tag for push notification. Available only for Android platforms.", + "x-example": "<TAG>" + }, + "badge": { + "type": "integer", + "description": "Badge for push notification. Available only for iOS platforms.", + "x-example": null + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": "MessagePriority", + "x-enum-keys": [] + } + } + } + } + } + } + } + }, + "\/messaging\/messages\/sms": { + "post": { + "summary": "Create SMS", + "operationId": "messagingCreateSms", + "tags": [ + "messaging" + ], + "description": "Create a new SMS message.", + "responses": { + "201": { + "description": "Message", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/message" + } + } + } + } + }, + "x-appwrite": { + "method": "createSms", + "group": "messages", + "weight": 360, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-sms.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-sms.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "messageId": { + "type": "string", + "description": "Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<MESSAGE_ID>" + }, + "content": { + "type": "string", + "description": "SMS Content.", + "x-example": "<CONTENT>" + }, + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "x-example": null + } + }, + "required": [ + "messageId", + "content" + ] + } + } + } + } + } + }, + "\/messaging\/messages\/sms\/{messageId}": { + "patch": { + "summary": "Update SMS", + "operationId": "messagingUpdateSms", + "tags": [ + "messaging" + ], + "description": "Update an SMS message by its unique ID. This endpoint only works on messages that are in draft status. Messages that are already processing, sent, or failed cannot be updated.\n", + "responses": { + "200": { + "description": "Message", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/message" + } + } + } + } + }, + "x-appwrite": { + "method": "updateSms", + "group": "messages", + "weight": 367, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-sms.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-sms.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MESSAGE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "x-example": null, + "items": { + "type": "string" + } + }, + "content": { + "type": "string", + "description": "Email Content.", + "x-example": "<CONTENT>" + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "x-example": null + } + } + } + } + } + } + } + }, + "\/messaging\/messages\/{messageId}": { + "get": { + "summary": "Get message", + "operationId": "messagingGetMessage", + "tags": [ + "messaging" + ], + "description": "Get a message by its unique ID.\n", + "responses": { + "200": { + "description": "Message", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/message" + } + } + } + } + }, + "x-appwrite": { + "method": "getMessage", + "group": "messages", + "weight": 365, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/get-message.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/get-message.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MESSAGE_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete message", + "operationId": "messagingDelete", + "tags": [ + "messaging" + ], + "description": "Delete a message. If the message is not a draft or scheduled, but has been sent, this will not recall the message.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "messages", + "weight": 369, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/delete-message.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MESSAGE_ID>" + }, + "in": "path" + } + ] + } + }, + "\/messaging\/messages\/{messageId}\/logs": { + "get": { + "summary": "List message logs", + "operationId": "messagingListMessageLogs", + "tags": [ + "messaging" + ], + "description": "Get the message activity logs listed by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/logList" + } + } + } + } + }, + "x-appwrite": { + "method": "listMessageLogs", + "group": "logs", + "weight": 363, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-message-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-message-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MESSAGE_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/messaging\/messages\/{messageId}\/targets": { + "get": { + "summary": "List message targets", + "operationId": "messagingListTargets", + "tags": [ + "messaging" + ], + "description": "Get a list of the targets associated with a message.", + "responses": { + "200": { + "description": "Target list", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/targetList" + } + } + } + } + }, + "x-appwrite": { + "method": "listTargets", + "group": "messages", + "weight": 364, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-targets.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-message-targets.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MESSAGE_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, providerId, identifier, providerType", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/messaging\/providers": { + "get": { + "summary": "List providers", + "operationId": "messagingListProviders", + "tags": [ + "messaging" + ], + "description": "Get a list of all providers from the current Appwrite project.", + "responses": { + "200": { + "description": "Provider list", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/providerList" + } + } + } + } + }, + "x-appwrite": { + "method": "listProviders", + "group": "providers", + "weight": 334, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-providers.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-providers.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, provider, type, enabled", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/messaging\/providers\/apns": { + "post": { + "summary": "Create APNS provider", + "operationId": "messagingCreateApnsProvider", + "tags": [ + "messaging" + ], + "description": "Create a new Apple Push Notification service provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createApnsProvider", + "group": "providers", + "weight": 333, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-apns-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-apns-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "authKey": { + "type": "string", + "description": "APNS authentication key.", + "x-example": "<AUTH_KEY>" + }, + "authKeyId": { + "type": "string", + "description": "APNS authentication key ID.", + "x-example": "<AUTH_KEY_ID>" + }, + "teamId": { + "type": "string", + "description": "APNS team ID.", + "x-example": "<TEAM_ID>" + }, + "bundleId": { + "type": "string", + "description": "APNS bundle ID.", + "x-example": "<BUNDLE_ID>" + }, + "sandbox": { + "type": "boolean", + "description": "Use APNS sandbox environment.", + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/apns\/{providerId}": { + "patch": { + "summary": "Update APNS provider", + "operationId": "messagingUpdateApnsProvider", + "tags": [ + "messaging" + ], + "description": "Update a Apple Push Notification service provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateApnsProvider", + "group": "providers", + "weight": 346, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-apns-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-apns-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + }, + "authKey": { + "type": "string", + "description": "APNS authentication key.", + "x-example": "<AUTH_KEY>" + }, + "authKeyId": { + "type": "string", + "description": "APNS authentication key ID.", + "x-example": "<AUTH_KEY_ID>" + }, + "teamId": { + "type": "string", + "description": "APNS team ID.", + "x-example": "<TEAM_ID>" + }, + "bundleId": { + "type": "string", + "description": "APNS bundle ID.", + "x-example": "<BUNDLE_ID>" + }, + "sandbox": { + "type": "boolean", + "description": "Use APNS sandbox environment.", + "x-example": false + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/fcm": { + "post": { + "summary": "Create FCM provider", + "operationId": "messagingCreateFcmProvider", + "tags": [ + "messaging" + ], + "description": "Create a new Firebase Cloud Messaging provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createFcmProvider", + "group": "providers", + "weight": 332, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-fcm-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-fcm-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "serviceAccountJSON": { + "type": "object", + "description": "FCM service account JSON.", + "x-example": "{}" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/fcm\/{providerId}": { + "patch": { + "summary": "Update FCM provider", + "operationId": "messagingUpdateFcmProvider", + "tags": [ + "messaging" + ], + "description": "Update a Firebase Cloud Messaging provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateFcmProvider", + "group": "providers", + "weight": 345, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-fcm-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-fcm-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + }, + "serviceAccountJSON": { + "type": "object", + "description": "FCM service account JSON.", + "x-example": "{}" + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/mailgun": { + "post": { + "summary": "Create Mailgun provider", + "operationId": "messagingCreateMailgunProvider", + "tags": [ + "messaging" + ], + "description": "Create a new Mailgun provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createMailgunProvider", + "group": "providers", + "weight": 324, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-mailgun-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-mailgun-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "apiKey": { + "type": "string", + "description": "Mailgun API Key.", + "x-example": "<API_KEY>" + }, + "domain": { + "type": "string", + "description": "Mailgun Domain.", + "x-example": "<DOMAIN>" + }, + "isEuRegion": { + "type": "boolean", + "description": "Set as EU region.", + "x-example": false + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the reply to field for the mail. Default value is sender name. Reply to name must have reply to email as well.", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the reply to field for the mail. Default value is sender email. Reply to email must have reply to name as well.", + "x-example": "email@example.com" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/mailgun\/{providerId}": { + "patch": { + "summary": "Update Mailgun provider", + "operationId": "messagingUpdateMailgunProvider", + "tags": [ + "messaging" + ], + "description": "Update a Mailgun provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMailgunProvider", + "group": "providers", + "weight": 337, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-mailgun-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-mailgun-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "apiKey": { + "type": "string", + "description": "Mailgun API Key.", + "x-example": "<API_KEY>" + }, + "domain": { + "type": "string", + "description": "Mailgun Domain.", + "x-example": "<DOMAIN>" + }, + "isEuRegion": { + "type": "boolean", + "description": "Set as EU region.", + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the reply to field for the mail. Default value is sender name.", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the reply to field for the mail. Default value is sender email.", + "x-example": "<REPLY_TO_EMAIL>" + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/msg91": { + "post": { + "summary": "Create Msg91 provider", + "operationId": "messagingCreateMsg91Provider", + "tags": [ + "messaging" + ], + "description": "Create a new MSG91 provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createMsg91Provider", + "group": "providers", + "weight": 327, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-msg91provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-msg91-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "templateId": { + "type": "string", + "description": "Msg91 template ID", + "x-example": "<TEMPLATE_ID>" + }, + "senderId": { + "type": "string", + "description": "Msg91 sender ID.", + "x-example": "<SENDER_ID>" + }, + "authKey": { + "type": "string", + "description": "Msg91 auth key.", + "x-example": "<AUTH_KEY>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/msg91\/{providerId}": { + "patch": { + "summary": "Update Msg91 provider", + "operationId": "messagingUpdateMsg91Provider", + "tags": [ + "messaging" + ], + "description": "Update a MSG91 provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMsg91Provider", + "group": "providers", + "weight": 340, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-msg91provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-msg91-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + }, + "templateId": { + "type": "string", + "description": "Msg91 template ID.", + "x-example": "<TEMPLATE_ID>" + }, + "senderId": { + "type": "string", + "description": "Msg91 sender ID.", + "x-example": "<SENDER_ID>" + }, + "authKey": { + "type": "string", + "description": "Msg91 auth key.", + "x-example": "<AUTH_KEY>" + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/sendgrid": { + "post": { + "summary": "Create Sendgrid provider", + "operationId": "messagingCreateSendgridProvider", + "tags": [ + "messaging" + ], + "description": "Create a new Sendgrid provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createSendgridProvider", + "group": "providers", + "weight": 325, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-sendgrid-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-sendgrid-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "apiKey": { + "type": "string", + "description": "Sendgrid API key.", + "x-example": "<API_KEY>" + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the reply to field for the mail. Default value is sender name.", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the reply to field for the mail. Default value is sender email.", + "x-example": "email@example.com" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/sendgrid\/{providerId}": { + "patch": { + "summary": "Update Sendgrid provider", + "operationId": "messagingUpdateSendgridProvider", + "tags": [ + "messaging" + ], + "description": "Update a Sendgrid provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateSendgridProvider", + "group": "providers", + "weight": 338, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-sendgrid-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-sendgrid-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + }, + "apiKey": { + "type": "string", + "description": "Sendgrid API key.", + "x-example": "<API_KEY>" + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the Reply To field for the mail. Default value is Sender Name.", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the Reply To field for the mail. Default value is Sender Email.", + "x-example": "<REPLY_TO_EMAIL>" + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/smtp": { + "post": { + "summary": "Create SMTP provider", + "operationId": "messagingCreateSmtpProvider", + "tags": [ + "messaging" + ], + "description": "Create a new SMTP provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createSmtpProvider", + "group": "providers", + "weight": 326, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-smtp-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-smtp-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "host": { + "type": "string", + "description": "SMTP hosts. Either a single hostname or multiple semicolon-delimited hostnames. You can also specify a different port for each host such as `smtp1.example.com:25;smtp2.example.com`. You can also specify encryption type, for example: `tls:\/\/smtp1.example.com:587;ssl:\/\/smtp2.example.com:465\"`. Hosts will be tried in order.", + "x-example": "<HOST>" + }, + "port": { + "type": "integer", + "description": "The default SMTP server port.", + "x-example": 1 + }, + "username": { + "type": "string", + "description": "Authentication username.", + "x-example": "<USERNAME>" + }, + "password": { + "type": "string", + "description": "Authentication password.", + "x-example": "<PASSWORD>" + }, + "encryption": { + "type": "string", + "description": "Encryption type. Can be omitted, 'ssl', or 'tls'", + "x-example": "none", + "enum": [ + "none", + "ssl", + "tls" + ], + "x-enum-name": "SmtpEncryption", + "x-enum-keys": [] + }, + "autoTLS": { + "type": "boolean", + "description": "Enable SMTP AutoTLS feature.", + "x-example": false + }, + "mailer": { + "type": "string", + "description": "The value to use for the X-Mailer header.", + "x-example": "<MAILER>" + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the reply to field for the mail. Default value is sender name.", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the reply to field for the mail. Default value is sender email.", + "x-example": "email@example.com" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name", + "host" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/smtp\/{providerId}": { + "patch": { + "summary": "Update SMTP provider", + "operationId": "messagingUpdateSmtpProvider", + "tags": [ + "messaging" + ], + "description": "Update a SMTP provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateSmtpProvider", + "group": "providers", + "weight": 339, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-smtp-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-smtp-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "host": { + "type": "string", + "description": "SMTP hosts. Either a single hostname or multiple semicolon-delimited hostnames. You can also specify a different port for each host such as `smtp1.example.com:25;smtp2.example.com`. You can also specify encryption type, for example: `tls:\/\/smtp1.example.com:587;ssl:\/\/smtp2.example.com:465\"`. Hosts will be tried in order.", + "x-example": "<HOST>" + }, + "port": { + "type": "integer", + "description": "SMTP port.", + "x-example": 1 + }, + "username": { + "type": "string", + "description": "Authentication username.", + "x-example": "<USERNAME>" + }, + "password": { + "type": "string", + "description": "Authentication password.", + "x-example": "<PASSWORD>" + }, + "encryption": { + "type": "string", + "description": "Encryption type. Can be 'ssl' or 'tls'", + "x-example": "none", + "enum": [ + "none", + "ssl", + "tls" + ], + "x-enum-name": "SmtpEncryption", + "x-enum-keys": [] + }, + "autoTLS": { + "type": "boolean", + "description": "Enable SMTP AutoTLS feature.", + "x-example": false + }, + "mailer": { + "type": "string", + "description": "The value to use for the X-Mailer header.", + "x-example": "<MAILER>" + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the Reply To field for the mail. Default value is Sender Name.", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the Reply To field for the mail. Default value is Sender Email.", + "x-example": "<REPLY_TO_EMAIL>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/telesign": { + "post": { + "summary": "Create Telesign provider", + "operationId": "messagingCreateTelesignProvider", + "tags": [ + "messaging" + ], + "description": "Create a new Telesign provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createTelesignProvider", + "group": "providers", + "weight": 328, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-telesign-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-telesign-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "from": { + "type": "string", + "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "x-example": "+12065550100" + }, + "customerId": { + "type": "string", + "description": "Telesign customer ID.", + "x-example": "<CUSTOMER_ID>" + }, + "apiKey": { + "type": "string", + "description": "Telesign API key.", + "x-example": "<API_KEY>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/telesign\/{providerId}": { + "patch": { + "summary": "Update Telesign provider", + "operationId": "messagingUpdateTelesignProvider", + "tags": [ + "messaging" + ], + "description": "Update a Telesign provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateTelesignProvider", + "group": "providers", + "weight": 341, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-telesign-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-telesign-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + }, + "customerId": { + "type": "string", + "description": "Telesign customer ID.", + "x-example": "<CUSTOMER_ID>" + }, + "apiKey": { + "type": "string", + "description": "Telesign API key.", + "x-example": "<API_KEY>" + }, + "from": { + "type": "string", + "description": "Sender number.", + "x-example": "<FROM>" + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/textmagic": { + "post": { + "summary": "Create Textmagic provider", + "operationId": "messagingCreateTextmagicProvider", + "tags": [ + "messaging" + ], + "description": "Create a new Textmagic provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createTextmagicProvider", + "group": "providers", + "weight": 329, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-textmagic-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-textmagic-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "from": { + "type": "string", + "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "x-example": "+12065550100" + }, + "username": { + "type": "string", + "description": "Textmagic username.", + "x-example": "<USERNAME>" + }, + "apiKey": { + "type": "string", + "description": "Textmagic apiKey.", + "x-example": "<API_KEY>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/textmagic\/{providerId}": { + "patch": { + "summary": "Update Textmagic provider", + "operationId": "messagingUpdateTextmagicProvider", + "tags": [ + "messaging" + ], + "description": "Update a Textmagic provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateTextmagicProvider", + "group": "providers", + "weight": 342, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-textmagic-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-textmagic-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + }, + "username": { + "type": "string", + "description": "Textmagic username.", + "x-example": "<USERNAME>" + }, + "apiKey": { + "type": "string", + "description": "Textmagic apiKey.", + "x-example": "<API_KEY>" + }, + "from": { + "type": "string", + "description": "Sender number.", + "x-example": "<FROM>" + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/twilio": { + "post": { + "summary": "Create Twilio provider", + "operationId": "messagingCreateTwilioProvider", + "tags": [ + "messaging" + ], + "description": "Create a new Twilio provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createTwilioProvider", + "group": "providers", + "weight": 330, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-twilio-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-twilio-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "from": { + "type": "string", + "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "x-example": "+12065550100" + }, + "accountSid": { + "type": "string", + "description": "Twilio account secret ID.", + "x-example": "<ACCOUNT_SID>" + }, + "authToken": { + "type": "string", + "description": "Twilio authentication token.", + "x-example": "<AUTH_TOKEN>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/twilio\/{providerId}": { + "patch": { + "summary": "Update Twilio provider", + "operationId": "messagingUpdateTwilioProvider", + "tags": [ + "messaging" + ], + "description": "Update a Twilio provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateTwilioProvider", + "group": "providers", + "weight": 343, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-twilio-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-twilio-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + }, + "accountSid": { + "type": "string", + "description": "Twilio account secret ID.", + "x-example": "<ACCOUNT_SID>" + }, + "authToken": { + "type": "string", + "description": "Twilio authentication token.", + "x-example": "<AUTH_TOKEN>" + }, + "from": { + "type": "string", + "description": "Sender number.", + "x-example": "<FROM>" + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/vonage": { + "post": { + "summary": "Create Vonage provider", + "operationId": "messagingCreateVonageProvider", + "tags": [ + "messaging" + ], + "description": "Create a new Vonage provider.", + "responses": { + "201": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "createVonageProvider", + "group": "providers", + "weight": 331, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-vonage-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-vonage-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "from": { + "type": "string", + "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "x-example": "+12065550100" + }, + "apiKey": { + "type": "string", + "description": "Vonage API key.", + "x-example": "<API_KEY>" + }, + "apiSecret": { + "type": "string", + "description": "Vonage API secret.", + "x-example": "<API_SECRET>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/providers\/vonage\/{providerId}": { + "patch": { + "summary": "Update Vonage provider", + "operationId": "messagingUpdateVonageProvider", + "tags": [ + "messaging" + ], + "description": "Update a Vonage provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "updateVonageProvider", + "group": "providers", + "weight": 344, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-vonage-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-vonage-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "x-example": false + }, + "apiKey": { + "type": "string", + "description": "Vonage API key.", + "x-example": "<API_KEY>" + }, + "apiSecret": { + "type": "string", + "description": "Vonage API secret.", + "x-example": "<API_SECRET>" + }, + "from": { + "type": "string", + "description": "Sender number.", + "x-example": "<FROM>" + } + } + } + } + } + } + } + }, + "\/messaging\/providers\/{providerId}": { + "get": { + "summary": "Get provider", + "operationId": "messagingGetProvider", + "tags": [ + "messaging" + ], + "description": "Get a provider by its unique ID.\n", + "responses": { + "200": { + "description": "Provider", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/provider" + } + } + } + } + }, + "x-appwrite": { + "method": "getProvider", + "group": "providers", + "weight": 336, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/get-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/get-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete provider", + "operationId": "messagingDeleteProvider", + "tags": [ + "messaging" + ], + "description": "Delete a provider by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteProvider", + "group": "providers", + "weight": 347, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/delete-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/delete-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + } + ] + } + }, + "\/messaging\/providers\/{providerId}\/logs": { + "get": { + "summary": "List provider logs", + "operationId": "messagingListProviderLogs", + "tags": [ + "messaging" + ], + "description": "Get the provider activity logs listed by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/logList" + } + } + } + } + }, + "x-appwrite": { + "method": "listProviderLogs", + "group": "providers", + "weight": 335, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-provider-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-provider-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<PROVIDER_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/messaging\/subscribers\/{subscriberId}\/logs": { + "get": { + "summary": "List subscriber logs", + "operationId": "messagingListSubscriberLogs", + "tags": [ + "messaging" + ], + "description": "Get the subscriber activity logs listed by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/logList" + } + } + } + } + }, + "x-appwrite": { + "method": "listSubscriberLogs", + "group": "subscribers", + "weight": 356, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-subscriber-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-subscriber-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "subscriberId", + "description": "Subscriber ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SUBSCRIBER_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/messaging\/topics": { + "get": { + "summary": "List topics", + "operationId": "messagingListTopics", + "tags": [ + "messaging" + ], + "description": "Get a list of all topics from the current Appwrite project.", + "responses": { + "200": { + "description": "Topic list", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/topicList" + } + } + } + } + }, + "x-appwrite": { + "method": "listTopics", + "group": "topics", + "weight": 349, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-topics.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-topics.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, description, emailTotal, smsTotal, pushTotal", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create topic", + "operationId": "messagingCreateTopic", + "tags": [ + "messaging" + ], + "description": "Create a new topic.", + "responses": { + "201": { + "description": "Topic", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/topic" + } + } + } + } + }, + "x-appwrite": { + "method": "createTopic", + "group": "topics", + "weight": 348, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-topic.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-topic.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "topicId": { + "type": "string", + "description": "Topic ID. Choose a custom Topic ID or a new Topic ID.", + "x-example": "<TOPIC_ID>" + }, + "name": { + "type": "string", + "description": "Topic Name.", + "x-example": "<NAME>" + }, + "subscribe": { + "type": "array", + "description": "An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https:\/\/appwrite.io\/docs\/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.", + "x-example": "[\"any\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "topicId", + "name" + ] + } + } + } + } + } + }, + "\/messaging\/topics\/{topicId}": { + "get": { + "summary": "Get topic", + "operationId": "messagingGetTopic", + "tags": [ + "messaging" + ], + "description": "Get a topic by its unique ID.\n", + "responses": { + "200": { + "description": "Topic", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/topic" + } + } + } + } + }, + "x-appwrite": { + "method": "getTopic", + "group": "topics", + "weight": 351, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/get-topic.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/get-topic.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOPIC_ID>" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update topic", + "operationId": "messagingUpdateTopic", + "tags": [ + "messaging" + ], + "description": "Update a topic by its unique ID.\n", + "responses": { + "200": { + "description": "Topic", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/topic" + } + } + } + } + }, + "x-appwrite": { + "method": "updateTopic", + "group": "topics", + "weight": 352, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-topic.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-topic.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOPIC_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Topic Name.", + "x-example": "<NAME>" + }, + "subscribe": { + "type": "array", + "description": "An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https:\/\/appwrite.io\/docs\/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.", + "x-example": "[\"any\"]", + "items": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete topic", + "operationId": "messagingDeleteTopic", + "tags": [ + "messaging" + ], + "description": "Delete a topic by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteTopic", + "group": "topics", + "weight": 353, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/delete-topic.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/delete-topic.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOPIC_ID>" + }, + "in": "path" + } + ] + } + }, + "\/messaging\/topics\/{topicId}\/logs": { + "get": { + "summary": "List topic logs", + "operationId": "messagingListTopicLogs", + "tags": [ + "messaging" + ], + "description": "Get the topic activity logs listed by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/logList" + } + } + } + } + }, + "x-appwrite": { + "method": "listTopicLogs", + "group": "topics", + "weight": 350, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-topic-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-topic-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOPIC_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/messaging\/topics\/{topicId}\/subscribers": { + "get": { + "summary": "List subscribers", + "operationId": "messagingListSubscribers", + "tags": [ + "messaging" + ], + "description": "Get a list of all subscribers from the current Appwrite project.", + "responses": { + "200": { + "description": "Subscriber list", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/subscriberList" + } + } + } + } + }, + "x-appwrite": { + "method": "listSubscribers", + "group": "subscribers", + "weight": 355, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-subscribers.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-subscribers.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID subscribed to.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOPIC_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, provider, type, enabled", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create subscriber", + "operationId": "messagingCreateSubscriber", + "tags": [ + "messaging" + ], + "description": "Create a new subscriber.", + "responses": { + "201": { + "description": "Subscriber", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/subscriber" + } + } + } + } + }, + "x-appwrite": { + "method": "createSubscriber", + "group": "subscribers", + "weight": 354, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-subscriber.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-subscriber.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.write", + "platforms": [ + "server", + "client", + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "JWT": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [], + "Session": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID to subscribe to.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOPIC_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "subscriberId": { + "type": "string", + "description": "Subscriber ID. Choose a custom Subscriber ID or a new Subscriber ID.", + "x-example": "<SUBSCRIBER_ID>" + }, + "targetId": { + "type": "string", + "description": "Target ID. The target ID to link to the specified Topic ID.", + "x-example": "<TARGET_ID>" + } + }, + "required": [ + "subscriberId", + "targetId" + ] + } + } + } + } + } + }, + "\/messaging\/topics\/{topicId}\/subscribers\/{subscriberId}": { + "get": { + "summary": "Get subscriber", + "operationId": "messagingGetSubscriber", + "tags": [ + "messaging" + ], + "description": "Get a subscriber by its unique ID.\n", + "responses": { + "200": { + "description": "Subscriber", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/subscriber" + } + } + } + } + }, + "x-appwrite": { + "method": "getSubscriber", + "group": "subscribers", + "weight": 357, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/get-subscriber.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/get-subscriber.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID subscribed to.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOPIC_ID>" + }, + "in": "path" + }, + { + "name": "subscriberId", + "description": "Subscriber ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SUBSCRIBER_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete subscriber", + "operationId": "messagingDeleteSubscriber", + "tags": [ + "messaging" + ], + "description": "Delete a subscriber by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSubscriber", + "group": "subscribers", + "weight": 358, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/delete-subscriber.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/delete-subscriber.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.write", + "platforms": [ + "server", + "client", + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "JWT": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [], + "Session": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID subscribed to.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOPIC_ID>" + }, + "in": "path" + }, + { + "name": "subscriberId", + "description": "Subscriber ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SUBSCRIBER_ID>" + }, + "in": "path" + } + ] + } + }, + "\/sites": { + "get": { + "summary": "List sites", + "operationId": "sitesList", + "tags": [ + "sites" + ], + "description": "Get a list of all the project's sites. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Sites List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/siteList" + } + } + } + } + }, + "x-appwrite": { + "method": "list", + "group": "sites", + "weight": 407, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the project's sites. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, enabled, framework, deploymentId, buildCommand, installCommand, outputDirectory, installationId", + "required": false, + "schema": { + "type": "string", + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create site", + "operationId": "sitesCreate", + "tags": [ + "sites" + ], + "description": "Create a new site.", + "responses": { + "201": { + "description": "Site", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/site" + } + } + } + } + }, + "x-appwrite": { + "method": "create", + "group": "sites", + "weight": 405, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new site.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "siteId": { + "type": "string", + "description": "Site ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<SITE_ID>" + }, + "name": { + "type": "string", + "description": "Site name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "framework": { + "type": "string", + "description": "Sites framework.", + "x-example": "analog", + "enum": [ + "analog", + "angular", + "nextjs", + "react", + "nuxt", + "vue", + "sveltekit", + "astro", + "remix", + "lynx", + "flutter", + "react-native", + "vite", + "other" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "enabled": { + "type": "boolean", + "description": "Is site enabled? When set to 'disabled', users cannot access the site but Server SDKs with and API key can still access the site. No data is lost when this is toggled.", + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.", + "x-example": false + }, + "timeout": { + "type": "integer", + "description": "Maximum request time in seconds.", + "x-example": 1 + }, + "installCommand": { + "type": "string", + "description": "Install Command.", + "x-example": "<INSTALL_COMMAND>" + }, + "buildCommand": { + "type": "string", + "description": "Build Command.", + "x-example": "<BUILD_COMMAND>" + }, + "outputDirectory": { + "type": "string", + "description": "Output Directory for site.", + "x-example": "<OUTPUT_DIRECTORY>" + }, + "buildRuntime": { + "type": "string", + "description": "Runtime to use during build step.", + "x-example": "node-14.5", + "enum": [ + "node-14.5", + "node-16.0", + "node-18.0", + "node-19.0", + "node-20.0", + "node-21.0", + "node-22", + "php-8.0", + "php-8.1", + "php-8.2", + "php-8.3", + "ruby-3.0", + "ruby-3.1", + "ruby-3.2", + "ruby-3.3", + "python-3.8", + "python-3.9", + "python-3.10", + "python-3.11", + "python-3.12", + "python-ml-3.11", + "python-ml-3.12", + "deno-1.21", + "deno-1.24", + "deno-1.35", + "deno-1.40", + "deno-1.46", + "deno-2.0", + "dart-2.15", + "dart-2.16", + "dart-2.17", + "dart-2.18", + "dart-2.19", + "dart-3.0", + "dart-3.1", + "dart-3.3", + "dart-3.5", + "dart-3.8", + "dotnet-6.0", + "dotnet-7.0", + "dotnet-8.0", + "java-8.0", + "java-11.0", + "java-17.0", + "java-18.0", + "java-21.0", + "java-22", + "swift-5.5", + "swift-5.8", + "swift-5.9", + "swift-5.10", + "kotlin-1.6", + "kotlin-1.8", + "kotlin-1.9", + "kotlin-2.0", + "cpp-17", + "cpp-20", + "bun-1.0", + "bun-1.1", + "go-1.23", + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29", + "flutter-3.32" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "adapter": { + "type": "string", + "description": "Framework adapter defining rendering strategy. Allowed values are: static, ssr", + "x-example": "static", + "enum": [ + "static", + "ssr" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "installationId": { + "type": "string", + "description": "Appwrite Installation ID for VCS (Version Control System) deployment.", + "x-example": "<INSTALLATION_ID>" + }, + "fallbackFile": { + "type": "string", + "description": "Fallback file for single page application sites.", + "x-example": "<FALLBACK_FILE>" + }, + "providerRepositoryId": { + "type": "string", + "description": "Repository ID of the repo linked to the site.", + "x-example": "<PROVIDER_REPOSITORY_ID>" + }, + "providerBranch": { + "type": "string", + "description": "Production branch for the repo linked to the site.", + "x-example": "<PROVIDER_BRANCH>" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is the VCS (Version Control System) connection in silent mode for the repo linked to the site? In silent mode, comments will not be made on commits and pull requests.", + "x-example": false + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to site code in the linked repo.", + "x-example": "<PROVIDER_ROOT_DIRECTORY>" + }, + "specification": { + "type": "string", + "description": "Framework specification for the site and builds.", + "x-example": null + } + }, + "required": [ + "siteId", + "name", + "framework", + "buildRuntime" + ] + } + } + } + } + } + }, + "\/sites\/frameworks": { + "get": { + "summary": "List frameworks", + "operationId": "sitesListFrameworks", + "tags": [ + "sites" + ], + "description": "Get a list of all frameworks that are currently available on the server instance.", + "responses": { + "200": { + "description": "Frameworks List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/frameworkList" + } + } + } + } + }, + "x-appwrite": { + "method": "listFrameworks", + "group": "frameworks", + "weight": 410, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-frameworks.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all frameworks that are currently available on the server instance.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/sites\/specifications": { + "get": { + "summary": "List specifications", + "operationId": "sitesListSpecifications", + "tags": [ + "sites" + ], + "description": "List allowed site specifications for this instance.", + "responses": { + "200": { + "description": "Specifications List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/specificationList" + } + } + } + } + }, + "x-appwrite": { + "method": "listSpecifications", + "group": "frameworks", + "weight": 433, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-specifications.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList allowed site specifications for this instance.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/sites\/{siteId}": { + "get": { + "summary": "Get site", + "operationId": "sitesGet", + "tags": [ + "sites" + ], + "description": "Get a site by its unique ID.", + "responses": { + "200": { + "description": "Site", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/site" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": "sites", + "weight": 406, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a site by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update site", + "operationId": "sitesUpdate", + "tags": [ + "sites" + ], + "description": "Update site by its unique ID.", + "responses": { + "200": { + "description": "Site", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/site" + } + } + } + } + }, + "x-appwrite": { + "method": "update", + "group": "sites", + "weight": 408, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/update.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate site by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Site name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "framework": { + "type": "string", + "description": "Sites framework.", + "x-example": "analog", + "enum": [ + "analog", + "angular", + "nextjs", + "react", + "nuxt", + "vue", + "sveltekit", + "astro", + "remix", + "lynx", + "flutter", + "react-native", + "vite", + "other" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "enabled": { + "type": "boolean", + "description": "Is site enabled? When set to 'disabled', users cannot access the site but Server SDKs with and API key can still access the site. No data is lost when this is toggled.", + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.", + "x-example": false + }, + "timeout": { + "type": "integer", + "description": "Maximum request time in seconds.", + "x-example": 1 + }, + "installCommand": { + "type": "string", + "description": "Install Command.", + "x-example": "<INSTALL_COMMAND>" + }, + "buildCommand": { + "type": "string", + "description": "Build Command.", + "x-example": "<BUILD_COMMAND>" + }, + "outputDirectory": { + "type": "string", + "description": "Output Directory for site.", + "x-example": "<OUTPUT_DIRECTORY>" + }, + "buildRuntime": { + "type": "string", + "description": "Runtime to use during build step.", + "x-example": "node-14.5", + "enum": [ + "node-14.5", + "node-16.0", + "node-18.0", + "node-19.0", + "node-20.0", + "node-21.0", + "node-22", + "php-8.0", + "php-8.1", + "php-8.2", + "php-8.3", + "ruby-3.0", + "ruby-3.1", + "ruby-3.2", + "ruby-3.3", + "python-3.8", + "python-3.9", + "python-3.10", + "python-3.11", + "python-3.12", + "python-ml-3.11", + "python-ml-3.12", + "deno-1.21", + "deno-1.24", + "deno-1.35", + "deno-1.40", + "deno-1.46", + "deno-2.0", + "dart-2.15", + "dart-2.16", + "dart-2.17", + "dart-2.18", + "dart-2.19", + "dart-3.0", + "dart-3.1", + "dart-3.3", + "dart-3.5", + "dart-3.8", + "dotnet-6.0", + "dotnet-7.0", + "dotnet-8.0", + "java-8.0", + "java-11.0", + "java-17.0", + "java-18.0", + "java-21.0", + "java-22", + "swift-5.5", + "swift-5.8", + "swift-5.9", + "swift-5.10", + "kotlin-1.6", + "kotlin-1.8", + "kotlin-1.9", + "kotlin-2.0", + "cpp-17", + "cpp-20", + "bun-1.0", + "bun-1.1", + "go-1.23", + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29", + "flutter-3.32" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "adapter": { + "type": "string", + "description": "Framework adapter defining rendering strategy. Allowed values are: static, ssr", + "x-example": "static", + "enum": [ + "static", + "ssr" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "fallbackFile": { + "type": "string", + "description": "Fallback file for single page application sites.", + "x-example": "<FALLBACK_FILE>" + }, + "installationId": { + "type": "string", + "description": "Appwrite Installation ID for VCS (Version Control System) deployment.", + "x-example": "<INSTALLATION_ID>" + }, + "providerRepositoryId": { + "type": "string", + "description": "Repository ID of the repo linked to the site.", + "x-example": "<PROVIDER_REPOSITORY_ID>" + }, + "providerBranch": { + "type": "string", + "description": "Production branch for the repo linked to the site.", + "x-example": "<PROVIDER_BRANCH>" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is the VCS (Version Control System) connection in silent mode for the repo linked to the site? In silent mode, comments will not be made on commits and pull requests.", + "x-example": false + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to site code in the linked repo.", + "x-example": "<PROVIDER_ROOT_DIRECTORY>" + }, + "specification": { + "type": "string", + "description": "Framework specification for the site and builds.", + "x-example": null + } + }, + "required": [ + "name", + "framework" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete site", + "operationId": "sitesDelete", + "tags": [ + "sites" + ], + "description": "Delete a site by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "sites", + "weight": 409, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a site by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ] + } + }, + "\/sites\/{siteId}\/deployment": { + "patch": { + "summary": "Update site's deployment", + "operationId": "sitesUpdateSiteDeployment", + "tags": [ + "sites" + ], + "description": "Update the site active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your site.", + "responses": { + "200": { + "description": "Site", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/site" + } + } + } + } + }, + "x-appwrite": { + "method": "updateSiteDeployment", + "group": "sites", + "weight": 416, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/update-site-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate the site active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your site.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "deploymentId": { + "type": "string", + "description": "Deployment ID.", + "x-example": "<DEPLOYMENT_ID>" + } + }, + "required": [ + "deploymentId" + ] + } + } + } + } + } + }, + "\/sites\/{siteId}\/deployments": { + "get": { + "summary": "List deployments", + "operationId": "sitesListDeployments", + "tags": [ + "sites" + ], + "description": "Get a list of all the site's code deployments. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Deployments List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deploymentList" + } + } + } + } + }, + "x-appwrite": { + "method": "listDeployments", + "group": "deployments", + "weight": 415, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-deployments.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the site's code deployments. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create deployment", + "operationId": "sitesCreateDeployment", + "tags": [ + "sites" + ], + "description": "Create a new site code deployment. Use this endpoint to upload a new version of your site code. To activate your newly uploaded code, you'll need to update the function's deployment to use your new deployment ID.", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createDeployment", + "group": "deployments", + "weight": 411, + "cookies": false, + "type": "upload", + "deprecated": false, + "demo": "sites\/create-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new site code deployment. Use this endpoint to upload a new version of your site code. To activate your newly uploaded code, you'll need to update the function's deployment to use your new deployment ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": true, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "multipart\/form-data": { + "schema": { + "type": "object", + "properties": { + "installCommand": { + "type": "string", + "description": "Install Commands.", + "x-example": "<INSTALL_COMMAND>" + }, + "buildCommand": { + "type": "string", + "description": "Build Commands.", + "x-example": "<BUILD_COMMAND>" + }, + "outputDirectory": { + "type": "string", + "description": "Output Directory.", + "x-example": "<OUTPUT_DIRECTORY>" + }, + "code": { + "type": "string", + "description": "Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.", + "x-example": null + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "x-example": false + } + }, + "required": [ + "code", + "activate" + ] + } + } + } + } + } + }, + "\/sites\/{siteId}\/deployments\/duplicate": { + "post": { + "summary": "Create duplicate deployment", + "operationId": "sitesCreateDuplicateDeployment", + "tags": [ + "sites" + ], + "description": "Create a new build for an existing site deployment. This endpoint allows you to rebuild a deployment with the updated site configuration, including its commands and output directory if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createDuplicateDeployment", + "group": "deployments", + "weight": 419, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create-duplicate-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new build for an existing site deployment. This endpoint allows you to rebuild a deployment with the updated site configuration, including its commands and output directory if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "deploymentId": { + "type": "string", + "description": "Deployment ID.", + "x-example": "<DEPLOYMENT_ID>" + } + }, + "required": [ + "deploymentId" + ] + } + } + } + } + } + }, + "\/sites\/{siteId}\/deployments\/template": { + "post": { + "summary": "Create template deployment", + "operationId": "sitesCreateTemplateDeployment", + "tags": [ + "sites" + ], + "description": "Create a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/sites#listTemplates) to find the template details.", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createTemplateDeployment", + "group": "deployments", + "weight": 412, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create-template-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/sites#listTemplates) to find the template details.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "repository": { + "type": "string", + "description": "Repository name of the template.", + "x-example": "<REPOSITORY>" + }, + "owner": { + "type": "string", + "description": "The name of the owner of the template.", + "x-example": "<OWNER>" + }, + "rootDirectory": { + "type": "string", + "description": "Path to site code in the template repo.", + "x-example": "<ROOT_DIRECTORY>" + }, + "version": { + "type": "string", + "description": "Version (tag) for the repo linked to the site template.", + "x-example": "<VERSION>" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "x-example": false + } + }, + "required": [ + "repository", + "owner", + "rootDirectory", + "version" + ] + } + } + } + } + } + }, + "\/sites\/{siteId}\/deployments\/vcs": { + "post": { + "summary": "Create VCS deployment", + "operationId": "sitesCreateVcsDeployment", + "tags": [ + "sites" + ], + "description": "Create a deployment when a site is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", + "responses": { + "202": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "createVcsDeployment", + "group": "deployments", + "weight": 413, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create-vcs-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment when a site is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Type of reference passed. Allowed values are: branch, commit", + "x-example": "branch", + "enum": [ + "branch", + "commit", + "tag" + ], + "x-enum-name": "VCSDeploymentType", + "x-enum-keys": [] + }, + "reference": { + "type": "string", + "description": "VCS reference to create deployment from. Depending on type this can be: branch name, commit hash", + "x-example": "<REFERENCE>" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "x-example": false + } + }, + "required": [ + "type", + "reference" + ] + } + } + } + } + } + }, + "\/sites\/{siteId}\/deployments\/{deploymentId}": { + "get": { + "summary": "Get deployment", + "operationId": "sitesGetDeployment", + "tags": [ + "sites" + ], + "description": "Get a site deployment by its unique ID.", + "responses": { + "200": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "getDeployment", + "group": "deployments", + "weight": 414, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a site deployment by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DEPLOYMENT_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete deployment", + "operationId": "sitesDeleteDeployment", + "tags": [ + "sites" + ], + "description": "Delete a site deployment by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDeployment", + "group": "deployments", + "weight": 417, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/delete-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a site deployment by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DEPLOYMENT_ID>" + }, + "in": "path" + } + ] + } + }, + "\/sites\/{siteId}\/deployments\/{deploymentId}\/download": { + "get": { + "summary": "Get deployment download", + "operationId": "sitesGetDeploymentDownload", + "tags": [ + "sites" + ], + "description": "Get a site deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "responses": { + "200": { + "description": "File" + } + }, + "x-appwrite": { + "method": "getDeploymentDownload", + "group": "deployments", + "weight": 418, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "sites\/get-deployment-download.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a site deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DEPLOYMENT_ID>" + }, + "in": "path" + }, + { + "name": "type", + "description": "Deployment file to download. Can be: \"source\", \"output\".", + "required": false, + "schema": { + "type": "string", + "x-example": "source", + "enum": [ + "source", + "output" + ], + "x-enum-name": "DeploymentDownloadType", + "x-enum-keys": [], + "default": "source" + }, + "in": "query" + } + ] + } + }, + "\/sites\/{siteId}\/deployments\/{deploymentId}\/status": { + "patch": { + "summary": "Update deployment status", + "operationId": "sitesUpdateDeploymentStatus", + "tags": [ + "sites" + ], + "description": "Cancel an ongoing site deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", + "responses": { + "200": { + "description": "Deployment", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/deployment" + } + } + } + } + }, + "x-appwrite": { + "method": "updateDeploymentStatus", + "group": "deployments", + "weight": 420, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/update-deployment-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCancel an ongoing site deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DEPLOYMENT_ID>" + }, + "in": "path" + } + ] + } + }, + "\/sites\/{siteId}\/logs": { + "get": { + "summary": "List logs", + "operationId": "sitesListLogs", + "tags": [ + "sites" + ], + "description": "Get a list of all site logs. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Executions List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/executionList" + } + } + } + } + }, + "x-appwrite": { + "method": "listLogs", + "group": "logs", + "weight": 422, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all site logs. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "log.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: trigger, status, responseStatusCode, duration, requestMethod, requestPath, deploymentId", + "required": false, + "schema": { + "type": "string", + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/sites\/{siteId}\/logs\/{logId}": { + "get": { + "summary": "Get log", + "operationId": "sitesGetLog", + "tags": [ + "sites" + ], + "description": "Get a site request log by its unique ID.", + "responses": { + "200": { + "description": "Execution", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/execution" + } + } + } + } + }, + "x-appwrite": { + "method": "getLog", + "group": "logs", + "weight": 421, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get-log.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a site request log by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "log.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "logId", + "description": "Log ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<LOG_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete log", + "operationId": "sitesDeleteLog", + "tags": [ + "sites" + ], + "description": "Delete a site log by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteLog", + "group": "logs", + "weight": 423, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/delete-log.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a site log by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "log.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "logId", + "description": "Log ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<LOG_ID>" + }, + "in": "path" + } + ] + } + }, + "\/sites\/{siteId}\/variables": { + "get": { + "summary": "List variables", + "operationId": "sitesListVariables", + "tags": [ + "sites" + ], + "description": "Get a list of all variables of a specific site.", + "responses": { + "200": { + "description": "Variables List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variableList" + } + } + } + } + }, + "x-appwrite": { + "method": "listVariables", + "group": "variables", + "weight": 426, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-variables.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all variables of a specific site.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ] + }, + "post": { + "summary": "Create variable", + "operationId": "sitesCreateVariable", + "tags": [ + "sites" + ], + "description": "Create a new site variable. These variables can be accessed during build and runtime (server-side rendering) as environment variables.", + "responses": { + "201": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "createVariable", + "group": "variables", + "weight": 424, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new site variable. These variables can be accessed during build and runtime (server-side rendering) as environment variables.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "x-example": "<KEY>" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "x-example": "<VALUE>" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only sites can read them during build and runtime.", + "x-example": false + } + }, + "required": [ + "key", + "value" + ] + } + } + } + } + } + }, + "\/sites\/{siteId}\/variables\/{variableId}": { + "get": { + "summary": "Get variable", + "operationId": "sitesGetVariable", + "tags": [ + "sites" + ], + "description": "Get a variable by its unique ID.", + "responses": { + "200": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "getVariable", + "group": "variables", + "weight": 425, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<VARIABLE_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update variable", + "operationId": "sitesUpdateVariable", + "tags": [ + "sites" + ], + "description": "Update variable by its unique ID.", + "responses": { + "200": { + "description": "Variable", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/variable" + } + } + } + } + }, + "x-appwrite": { + "method": "updateVariable", + "group": "variables", + "weight": 427, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/update-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<VARIABLE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "x-example": "<KEY>" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "x-example": "<VALUE>" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only sites can read them during build and runtime.", + "x-example": false + } + }, + "required": [ + "key" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete variable", + "operationId": "sitesDeleteVariable", + "tags": [ + "sites" + ], + "description": "Delete a variable by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteVariable", + "group": "variables", + "weight": 428, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/delete-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SITE_ID>" + }, + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<VARIABLE_ID>" + }, + "in": "path" + } + ] + } + }, + "\/storage\/buckets": { + "get": { + "summary": "List buckets", + "operationId": "storageListBuckets", + "tags": [ + "storage" + ], + "description": "Get a list of all the storage buckets. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Buckets List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/bucketList" + } + } + } + } + }, + "x-appwrite": { + "method": "listBuckets", + "group": "buckets", + "weight": 209, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/list-buckets.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/list-buckets.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create bucket", + "operationId": "storageCreateBucket", + "tags": [ + "storage" + ], + "description": "Create a new storage bucket.", + "responses": { + "201": { + "description": "Bucket", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/bucket" + } + } + } + } + }, + "x-appwrite": { + "method": "createBucket", + "group": "buckets", + "weight": 208, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/create-bucket.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/create-bucket.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "bucketId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<BUCKET_ID>" + }, + "name": { + "type": "string", + "description": "Bucket name", + "x-example": "<NAME>" + }, + "permissions": { + "type": "array", + "description": "An array of permission strings. By default, no user is granted with any permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "fileSecurity": { + "type": "boolean", + "description": "Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Is bucket enabled? When set to 'disabled', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.", + "x-example": false + }, + "maximumFileSize": { + "type": "integer", + "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", + "x-example": 1 + }, + "allowedFileExtensions": { + "type": "array", + "description": "Allowed file extensions. Maximum of 100 extensions are allowed, each 64 characters long.", + "x-example": null, + "items": { + "type": "string" + } + }, + "compression": { + "type": "string", + "description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", + "x-example": "none", + "enum": [ + "none", + "gzip", + "zstd" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "encryption": { + "type": "boolean", + "description": "Is encryption enabled? For file size above 20MB encryption is skipped even if it's enabled", + "x-example": false + }, + "antivirus": { + "type": "boolean", + "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", + "x-example": false + } + }, + "required": [ + "bucketId", + "name" + ] + } + } + } + } + } + }, + "\/storage\/buckets\/{bucketId}": { + "get": { + "summary": "Get bucket", + "operationId": "storageGetBucket", + "tags": [ + "storage" + ], + "description": "Get a storage bucket by its unique ID. This endpoint response returns a JSON object with the storage bucket metadata.", + "responses": { + "200": { + "description": "Bucket", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/bucket" + } + } + } + } + }, + "x-appwrite": { + "method": "getBucket", + "group": "buckets", + "weight": 210, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/get-bucket.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-bucket.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Bucket unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update bucket", + "operationId": "storageUpdateBucket", + "tags": [ + "storage" + ], + "description": "Update a storage bucket by its unique ID.", + "responses": { + "200": { + "description": "Bucket", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/bucket" + } + } + } + } + }, + "x-appwrite": { + "method": "updateBucket", + "group": "buckets", + "weight": 211, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/update-bucket.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/update-bucket.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Bucket unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Bucket name", + "x-example": "<NAME>" + }, + "permissions": { + "type": "array", + "description": "An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "fileSecurity": { + "type": "boolean", + "description": "Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Is bucket enabled? When set to 'disabled', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.", + "x-example": false + }, + "maximumFileSize": { + "type": "integer", + "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", + "x-example": 1 + }, + "allowedFileExtensions": { + "type": "array", + "description": "Allowed file extensions. Maximum of 100 extensions are allowed, each 64 characters long.", + "x-example": null, + "items": { + "type": "string" + } + }, + "compression": { + "type": "string", + "description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", + "x-example": "none", + "enum": [ + "none", + "gzip", + "zstd" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "encryption": { + "type": "boolean", + "description": "Is encryption enabled? For file size above 20MB encryption is skipped even if it's enabled", + "x-example": false + }, + "antivirus": { + "type": "boolean", + "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", + "x-example": false + } + }, + "required": [ + "name" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete bucket", + "operationId": "storageDeleteBucket", + "tags": [ + "storage" + ], + "description": "Delete a storage bucket by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteBucket", + "group": "buckets", + "weight": 212, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/delete-bucket.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/delete-bucket.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Bucket unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files": { + "get": { + "summary": "List files", + "operationId": "storageListFiles", + "tags": [ + "storage" + ], + "description": "Get a list of all the user files. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Files List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/fileList" + } + } + } + } + }, + "x-appwrite": { + "method": "listFiles", + "group": "files", + "weight": 214, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/list-files.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/list-files.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, signature, mimeType, sizeOriginal, chunksTotal, chunksUploaded", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create file", + "operationId": "storageCreateFile", + "tags": [ + "storage" + ], + "description": "Create a new file. Before using this route, you should create a new bucket resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/storage#storageCreateBucket) API or directly from your Appwrite console.\n\nLarger files should be uploaded using multiple requests with the [content-range](https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Headers\/Content-Range) header to send a partial request with a maximum supported chunk of `5MB`. The `content-range` header values should always be in bytes.\n\nWhen the first request is sent, the server will return the **File** object, and the subsequent part request must include the file's **id** in `x-appwrite-id` header to allow the server to know that the partial upload is for the existing file and not for a new one.\n\nIf you're creating a new file using one of the Appwrite SDKs, all the chunking logic will be managed by the SDK internally.\n", + "responses": { + "201": { + "description": "File", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/file" + } + } + } + } + }, + "x-appwrite": { + "method": "createFile", + "group": "files", + "weight": 213, + "cookies": false, + "type": "upload", + "deprecated": false, + "demo": "storage\/create-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/create-file.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId},chunkId:{chunkId}", + "scope": "files.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "multipart\/form-data": { + "schema": { + "type": "object", + "properties": { + "fileId": { + "type": "string", + "description": "File ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<FILE_ID>", + "x-upload-id": true + }, + "file": { + "type": "string", + "description": "Binary file. Appwrite SDKs provide helpers to handle file input. [Learn about file input](https:\/\/appwrite.io\/docs\/products\/storage\/upload-download#input-file).", + "x-example": null + }, + "permissions": { + "type": "array", + "description": "An array of permission strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "fileId", + "file" + ] + } + } + } + } + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}": { + "get": { + "summary": "Get file", + "operationId": "storageGetFile", + "tags": [ + "storage" + ], + "description": "Get a file by its unique ID. This endpoint response returns a JSON object with the file metadata.", + "responses": { + "200": { + "description": "File", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/file" + } + } + } + } + }, + "x-appwrite": { + "method": "getFile", + "group": "files", + "weight": 215, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/get-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FILE_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update file", + "operationId": "storageUpdateFile", + "tags": [ + "storage" + ], + "description": "Update a file by its unique ID. Only users with write permissions have access to update this resource.", + "responses": { + "200": { + "description": "File", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/file" + } + } + } + } + }, + "x-appwrite": { + "method": "updateFile", + "group": "files", + "weight": 220, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/update-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/update-file.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "files.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FILE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the file", + "x-example": "<NAME>" + }, + "permissions": { + "type": "array", + "description": "An array of permission string. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete file", + "operationId": "storageDeleteFile", + "tags": [ + "storage" + ], + "description": "Delete a file by its unique ID. Only users with write permissions have access to delete this resource.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteFile", + "group": "files", + "weight": 221, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/delete-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/delete-file.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "files.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FILE_ID>" + }, + "in": "path" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/download": { + "get": { + "summary": "Get file for download", + "operationId": "storageGetFileDownload", + "tags": [ + "storage" + ], + "description": "Get a file content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "responses": { + "200": { + "description": "File" + } + }, + "x-appwrite": { + "method": "getFileDownload", + "group": "files", + "weight": 217, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "storage\/get-file-download.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file-download.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FILE_ID>" + }, + "in": "path" + }, + { + "name": "token", + "description": "File token for accessing this file.", + "required": false, + "schema": { + "type": "string", + "x-example": "<TOKEN>", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/preview": { + "get": { + "summary": "Get file preview", + "operationId": "storageGetFilePreview", + "tags": [ + "storage" + ], + "description": "Get a file preview image. Currently, this method supports preview for image files (jpg, png, and gif), other supported formats, like pdf, docs, slides, and spreadsheets, will return the file icon image. You can also pass query string arguments for cutting and resizing your preview image. Preview is supported only for image files smaller than 10MB.", + "responses": { + "200": { + "description": "Image" + } + }, + "x-appwrite": { + "method": "getFilePreview", + "group": "files", + "weight": 216, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "storage\/get-file-preview.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file-preview.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File ID", + "required": true, + "schema": { + "type": "string", + "x-example": "<FILE_ID>" + }, + "in": "path" + }, + { + "name": "width", + "description": "Resize preview image width, Pass an integer between 0 to 4000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0 + }, + "in": "query" + }, + { + "name": "height", + "description": "Resize preview image height, Pass an integer between 0 to 4000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0 + }, + "in": "query" + }, + { + "name": "gravity", + "description": "Image crop gravity. Can be one of center,top-left,top,top-right,left,right,bottom-left,bottom,bottom-right", + "required": false, + "schema": { + "type": "string", + "x-example": "center", + "enum": [ + "center", + "top-left", + "top", + "top-right", + "left", + "right", + "bottom-left", + "bottom", + "bottom-right" + ], + "x-enum-name": "ImageGravity", + "x-enum-keys": [], + "default": "center" + }, + "in": "query" + }, + { + "name": "quality", + "description": "Preview image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1 + }, + "in": "query" + }, + { + "name": "borderWidth", + "description": "Preview image border in pixels. Pass an integer between 0 to 100. Defaults to 0.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0 + }, + "in": "query" + }, + { + "name": "borderColor", + "description": "Preview image border color. Use a valid HEX color, no # is needed for prefix.", + "required": false, + "schema": { + "type": "string", + "default": "" + }, + "in": "query" + }, + { + "name": "borderRadius", + "description": "Preview image border radius in pixels. Pass an integer between 0 to 4000.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0 + }, + "in": "query" + }, + { + "name": "opacity", + "description": "Preview image opacity. Only works with images having an alpha channel (like png). Pass a number between 0 to 1.", + "required": false, + "schema": { + "type": "number", + "format": "float", + "x-example": 0, + "default": 1 + }, + "in": "query" + }, + { + "name": "rotation", + "description": "Preview image rotation in degrees. Pass an integer between -360 and 360.", + "required": false, + "schema": { + "type": "integer", + "format": "int32", + "x-example": -360, + "default": 0 + }, + "in": "query" + }, + { + "name": "background", + "description": "Preview image background color. Only works with transparent images (png). Use a valid HEX color, no # is needed for prefix.", + "required": false, + "schema": { + "type": "string", + "default": "" + }, + "in": "query" + }, + { + "name": "output", + "description": "Output format type (jpeg, jpg, png, gif and webp).", + "required": false, + "schema": { + "type": "string", + "x-example": "jpg", + "enum": [ + "jpg", + "jpeg", + "png", + "webp", + "heic", + "avif", + "gif" + ], + "x-enum-name": "ImageFormat", + "x-enum-keys": [], + "default": "" + }, + "in": "query" + }, + { + "name": "token", + "description": "File token for accessing this file.", + "required": false, + "schema": { + "type": "string", + "x-example": "<TOKEN>", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/view": { + "get": { + "summary": "Get file for view", + "operationId": "storageGetFileView", + "tags": [ + "storage" + ], + "description": "Get a file content by its unique ID. This endpoint is similar to the download method but returns with no 'Content-Disposition: attachment' header.", + "responses": { + "200": { + "description": "File" + } + }, + "x-appwrite": { + "method": "getFileView", + "group": "files", + "weight": 218, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "storage\/get-file-view.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file-view.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FILE_ID>" + }, + "in": "path" + }, + { + "name": "token", + "description": "File token for accessing this file.", + "required": false, + "schema": { + "type": "string", + "x-example": "<TOKEN>", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/teams": { + "get": { + "summary": "List teams", + "operationId": "teamsList", + "tags": [ + "teams" + ], + "description": "Get a list of all the teams in which the current user is a member. You can use the parameters to filter your results.", + "responses": { + "200": { + "description": "Teams List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/teamList" + } + } + } + } + }, + "x-appwrite": { + "method": "list", + "group": "teams", + "weight": 225, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/list-teams.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, total, billingPlan", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create team", + "operationId": "teamsCreate", + "tags": [ + "teams" + ], + "description": "Create a new team. The user who creates the team will automatically be assigned as the owner of the team. Only the users with the owner role can invite new members, add new owners and delete or update the team.", + "responses": { + "201": { + "description": "Team", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/team" + } + } + } + } + }, + "x-appwrite": { + "method": "create", + "group": "teams", + "weight": 224, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/create-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "teamId": { + "type": "string", + "description": "Team ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<TEAM_ID>" + }, + "name": { + "type": "string", + "description": "Team name. Max length: 128 chars.", + "x-example": "<NAME>" + }, + "roles": { + "type": "array", + "description": "Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.", + "x-example": null, + "items": { + "type": "string" + } + } + }, + "required": [ + "teamId", + "name" + ] + } + } + } + } + } + }, + "\/teams\/{teamId}": { + "get": { + "summary": "Get team", + "operationId": "teamsGet", + "tags": [ + "teams" + ], + "description": "Get a team by its ID. All team members have read access for this resource.", + "responses": { + "200": { + "description": "Team", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/team" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": "teams", + "weight": 226, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update name", + "operationId": "teamsUpdateName", + "tags": [ + "teams" + ], + "description": "Update the team's name by its unique ID.", + "responses": { + "200": { + "description": "Team", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/team" + } + } + } + } + }, + "x-appwrite": { + "method": "updateName", + "group": "teams", + "weight": 228, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-name.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-name.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "New team name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "name" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete team", + "operationId": "teamsDelete", + "tags": [ + "teams" + ], + "description": "Delete a team using its ID. Only team members with the owner role can delete the team.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "teams", + "weight": 230, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/delete-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + } + ] + } + }, + "\/teams\/{teamId}\/memberships": { + "get": { + "summary": "List team memberships", + "operationId": "teamsListMemberships", + "tags": [ + "teams" + ], + "description": "Use this endpoint to list a team's members using the team's ID. All team members have read access to this endpoint. Hide sensitive attributes from the response by toggling membership privacy in the Console.", + "responses": { + "200": { + "description": "Memberships List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/membershipList" + } + } + } + } + }, + "x-appwrite": { + "method": "listMemberships", + "group": "memberships", + "weight": 232, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/list-memberships.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/list-team-members.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create team membership", + "operationId": "teamsCreateMembership", + "tags": [ + "teams" + ], + "description": "Invite a new member to join your team. Provide an ID for existing users, or invite unregistered users using an email or phone number. If initiated from a Client SDK, Appwrite will send an email or sms with a link to join the team to the invited user, and an account will be created for them if one doesn't exist. If initiated from a Server SDK, the new member will be added automatically to the team.\n\nYou only need to provide one of a user ID, email, or phone number. Appwrite will prioritize accepting the user ID > email > phone number if you provide more than one of these parameters.\n\nUse the `url` parameter to redirect the user from the invitation email to your app. After the user is redirected, use the [Update Team Membership Status](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/teams#updateMembershipStatus) endpoint to allow the user to accept the invitation to the team. \n\nPlease note that to avoid a [Redirect Attack](https:\/\/github.com\/OWASP\/CheatSheetSeries\/blob\/master\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) Appwrite will accept the only redirect URLs under the domains you have added as a platform on the Appwrite Console.\n", + "responses": { + "201": { + "description": "Membership", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/membership" + } + } + } + } + }, + "x-appwrite": { + "method": "createMembership", + "group": "memberships", + "weight": 231, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/create-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/create-team-membership.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "Email of the new team member.", + "x-example": "email@example.com" + }, + "userId": { + "type": "string", + "description": "ID of the user to be added to a team.", + "x-example": "<USER_ID>" + }, + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "x-example": "+12065550100" + }, + "roles": { + "type": "array", + "description": "Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.", + "x-example": null, + "items": { + "type": "string" + } + }, + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "x-example": "https:\/\/example.com" + }, + "name": { + "type": "string", + "description": "Name of the new team member. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "roles" + ] + } + } + } + } + } + }, + "\/teams\/{teamId}\/memberships\/{membershipId}": { + "get": { + "summary": "Get team membership", + "operationId": "teamsGetMembership", + "tags": [ + "teams" + ], + "description": "Get a team member by the membership unique id. All team members have read access for this resource. Hide sensitive attributes from the response by toggling membership privacy in the Console.", + "responses": { + "200": { + "description": "Membership", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/membership" + } + } + } + } + }, + "x-appwrite": { + "method": "getMembership", + "group": "memberships", + "weight": 233, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/get-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team-member.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MEMBERSHIP_ID>" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update membership", + "operationId": "teamsUpdateMembership", + "tags": [ + "teams" + ], + "description": "Modify the roles of a team member. Only team members with the owner role have access to this endpoint. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions).\n", + "responses": { + "200": { + "description": "Membership", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/membership" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMembership", + "group": "memberships", + "weight": 234, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-membership.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MEMBERSHIP_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "roles": { + "type": "array", + "description": "An array of strings. Use this param to set the user's roles in the team. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.", + "x-example": null, + "items": { + "type": "string" + } + } + }, + "required": [ + "roles" + ] + } + } + } + } + }, + "delete": { + "summary": "Delete team membership", + "operationId": "teamsDeleteMembership", + "tags": [ + "teams" + ], + "description": "This endpoint allows a user to leave a team or for a team owner to delete the membership of any other team member. You can also use this endpoint to delete a user membership even if it is not accepted.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteMembership", + "group": "memberships", + "weight": 236, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/delete-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/delete-team-membership.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MEMBERSHIP_ID>" + }, + "in": "path" + } + ] + } + }, + "\/teams\/{teamId}\/memberships\/{membershipId}\/status": { + "patch": { + "summary": "Update team membership status", + "operationId": "teamsUpdateMembershipStatus", + "tags": [ + "teams" + ], + "description": "Use this endpoint to allow a user to accept an invitation to join a team after being redirected back to your app from the invitation email received by the user.\n\nIf the request is successful, a session for the user is automatically created.\n", + "responses": { + "200": { + "description": "Membership", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/membership" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMembershipStatus", + "group": "memberships", + "weight": 235, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-membership-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-membership-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<MEMBERSHIP_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Secret key.", + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + } + } + } + }, + "\/teams\/{teamId}\/prefs": { + "get": { + "summary": "Get team preferences", + "operationId": "teamsGetPrefs", + "tags": [ + "teams" + ], + "description": "Get the team's shared preferences by its unique ID. If a preference doesn't need to be shared by all team members, prefer storing them in [user preferences](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#getPrefs).", + "responses": { + "200": { + "description": "Preferences", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/preferences" + } + } + } + } + }, + "x-appwrite": { + "method": "getPrefs", + "group": "teams", + "weight": 227, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/get-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update preferences", + "operationId": "teamsUpdatePrefs", + "tags": [ + "teams" + ], + "description": "Update the team's preferences by its unique ID. The object you pass is stored as is and replaces any previous value. The maximum allowed prefs size is 64kB and throws an error if exceeded.", + "responses": { + "200": { + "description": "Preferences", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/preferences" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePrefs", + "group": "teams", + "weight": 229, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TEAM_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "prefs": { + "type": "object", + "description": "Prefs key-value JSON object.", + "x-example": "{}" + } + }, + "required": [ + "prefs" + ] + } + } + } + } + } + }, + "\/tokens\/buckets\/{bucketId}\/files\/{fileId}": { + "get": { + "summary": "List tokens", + "operationId": "tokensList", + "tags": [ + "tokens" + ], + "description": "List all the tokens created for a specific file or bucket. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Resource Tokens List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/resourceTokenList" + } + } + } + } + }, + "x-appwrite": { + "method": "list", + "group": "files", + "weight": 441, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList all the tokens created for a specific file or bucket. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "tokens.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FILE_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: expire", + "required": false, + "schema": { + "type": "string", + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create file token", + "operationId": "tokensCreateFileToken", + "tags": [ + "tokens" + ], + "description": "Create a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", + "responses": { + "201": { + "description": "ResourceToken", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/resourceToken" + } + } + } + } + }, + "x-appwrite": { + "method": "createFileToken", + "group": "files", + "weight": 439, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/create-file-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "tokens.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "schema": { + "type": "string", + "x-example": "<BUCKET_ID>" + }, + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<FILE_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "expire": { + "type": "string", + "description": "Token expiry date", + "x-example": null, + "x-nullable": true + } + } + } + } + } + } + } + }, + "\/tokens\/{tokenId}": { + "get": { + "summary": "Get token", + "operationId": "tokensGet", + "tags": [ + "tokens" + ], + "description": "Get a token by its unique ID.", + "responses": { + "200": { + "description": "ResourceToken", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/resourceToken" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": "tokens", + "weight": 440, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a token by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "tokens.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOKEN_ID>" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update token", + "operationId": "tokensUpdate", + "tags": [ + "tokens" + ], + "description": "Update a token by its unique ID. Use this endpoint to update a token's expiry date.", + "responses": { + "200": { + "description": "ResourceToken", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/resourceToken" + } + } + } + } + }, + "x-appwrite": { + "method": "update", + "group": "tokens", + "weight": 442, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/update.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate a token by its unique ID. Use this endpoint to update a token's expiry date.", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "tokens.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token unique ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOKEN_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "expire": { + "type": "string", + "description": "File token expiry date", + "x-example": null, + "x-nullable": true + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete token", + "operationId": "tokensDelete", + "tags": [ + "tokens" + ], + "description": "Delete a token by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "tokens", + "weight": 443, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a token by its unique ID.", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "tokens.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TOKEN_ID>" + }, + "in": "path" + } + ] + } + }, + "\/users": { + "get": { + "summary": "List users", + "operationId": "usersList", + "tags": [ + "users" + ], + "description": "Get a list of all the project's users. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Users List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/userList" + } + } + } + } + }, + "x-appwrite": { + "method": "list", + "group": "users", + "weight": 247, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-users.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, email, phone, status, passwordUpdate, registration, emailVerification, phoneVerification, labels", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create user", + "operationId": "usersCreate", + "tags": [ + "users" + ], + "description": "Create a new user.", + "responses": { + "201": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "create", + "group": "users", + "weight": 238, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "x-example": "+12065550100" + }, + "password": { + "type": "string", + "description": "Plain text user password. Must be at least 8 chars.", + "x-example": null + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "userId" + ] + } + } + } + } + } + }, + "\/users\/argon2": { + "post": { + "summary": "Create user with Argon2 password", + "operationId": "usersCreateArgon2User", + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [Argon2](https:\/\/en.wikipedia.org\/wiki\/Argon2) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "createArgon2User", + "group": "users", + "weight": 241, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-argon2user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-argon2-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using Argon2.", + "x-example": "password" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + } + } + } + }, + "\/users\/bcrypt": { + "post": { + "summary": "Create user with bcrypt password", + "operationId": "usersCreateBcryptUser", + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [Bcrypt](https:\/\/en.wikipedia.org\/wiki\/Bcrypt) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "createBcryptUser", + "group": "users", + "weight": 239, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-bcrypt-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-bcrypt-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using Bcrypt.", + "x-example": "password" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + } + } + } + }, + "\/users\/identities": { + "get": { + "summary": "List identities", + "operationId": "usersListIdentities", + "tags": [ + "users" + ], + "description": "Get identities for all users.", + "responses": { + "200": { + "description": "Identities List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/identityList" + } + } + } + } + }, + "x-appwrite": { + "method": "listIdentities", + "group": "identities", + "weight": 255, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-identities.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-identities.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, provider, providerUid, providerEmail, providerAccessTokenExpiry", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/users\/identities\/{identityId}": { + "delete": { + "summary": "Delete identity", + "operationId": "usersDeleteIdentity", + "tags": [ + "users" + ], + "description": "Delete an identity by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteIdentity", + "group": "identities", + "weight": 278, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-identity.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-identity.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "identityId", + "description": "Identity ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<IDENTITY_ID>" + }, + "in": "path" + } + ] + } + }, + "\/users\/md5": { + "post": { + "summary": "Create user with MD5 password", + "operationId": "usersCreateMD5User", + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [MD5](https:\/\/en.wikipedia.org\/wiki\/MD5) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "createMD5User", + "group": "users", + "weight": 240, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-m-d5user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-md5-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using MD5.", + "x-example": "password" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + } + } + } + }, + "\/users\/phpass": { + "post": { + "summary": "Create user with PHPass password", + "operationId": "usersCreatePHPassUser", + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [PHPass](https:\/\/www.openwall.com\/phpass\/) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "createPHPassUser", + "group": "users", + "weight": 243, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-p-h-pass-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-phpass-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or pass the string `ID.unique()`to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using PHPass.", + "x-example": "password" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + } + } + } + }, + "\/users\/scrypt": { + "post": { + "summary": "Create user with Scrypt password", + "operationId": "usersCreateScryptUser", + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [Scrypt](https:\/\/github.com\/Tarsnap\/scrypt) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "createScryptUser", + "group": "users", + "weight": 244, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-scrypt-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-scrypt-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using Scrypt.", + "x-example": "password" + }, + "passwordSalt": { + "type": "string", + "description": "Optional salt used to hash password.", + "x-example": "<PASSWORD_SALT>" + }, + "passwordCpu": { + "type": "integer", + "description": "Optional CPU cost used to hash password.", + "x-example": null + }, + "passwordMemory": { + "type": "integer", + "description": "Optional memory cost used to hash password.", + "x-example": null + }, + "passwordParallel": { + "type": "integer", + "description": "Optional parallelization cost used to hash password.", + "x-example": null + }, + "passwordLength": { + "type": "integer", + "description": "Optional hash length used to hash password.", + "x-example": null + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password", + "passwordSalt", + "passwordCpu", + "passwordMemory", + "passwordParallel", + "passwordLength" + ] + } + } + } + } + } + }, + "\/users\/scrypt-modified": { + "post": { + "summary": "Create user with Scrypt modified password", + "operationId": "usersCreateScryptModifiedUser", + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [Scrypt Modified](https:\/\/gist.github.com\/Meldiron\/eecf84a0225eccb5a378d45bb27462cc) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "createScryptModifiedUser", + "group": "users", + "weight": 245, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-scrypt-modified-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-scrypt-modified-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using Scrypt Modified.", + "x-example": "password" + }, + "passwordSalt": { + "type": "string", + "description": "Salt used to hash password.", + "x-example": "<PASSWORD_SALT>" + }, + "passwordSaltSeparator": { + "type": "string", + "description": "Salt separator used to hash password.", + "x-example": "<PASSWORD_SALT_SEPARATOR>" + }, + "passwordSignerKey": { + "type": "string", + "description": "Signer key used to hash password.", + "x-example": "<PASSWORD_SIGNER_KEY>" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password", + "passwordSalt", + "passwordSaltSeparator", + "passwordSignerKey" + ] + } + } + } + } + } + }, + "\/users\/sha": { + "post": { + "summary": "Create user with SHA password", + "operationId": "usersCreateSHAUser", + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [SHA](https:\/\/en.wikipedia.org\/wiki\/Secure_Hash_Algorithm) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "createSHAUser", + "group": "users", + "weight": 242, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-s-h-a-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-sha-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using SHA.", + "x-example": "password" + }, + "passwordVersion": { + "type": "string", + "description": "Optional SHA version used to hash password. Allowed values are: 'sha1', 'sha224', 'sha256', 'sha384', 'sha512\/224', 'sha512\/256', 'sha512', 'sha3-224', 'sha3-256', 'sha3-384', 'sha3-512'", + "x-example": "sha1", + "enum": [ + "sha1", + "sha224", + "sha256", + "sha384", + "sha512\/224", + "sha512\/256", + "sha512", + "sha3-224", + "sha3-256", + "sha3-384", + "sha3-512" + ], + "x-enum-name": "PasswordHash", + "x-enum-keys": [] + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + } + } + } + }, + "\/users\/{userId}": { + "get": { + "summary": "Get user", + "operationId": "usersGet", + "tags": [ + "users" + ], + "description": "Get a user by its unique ID.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "get", + "group": "users", + "weight": 248, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete user", + "operationId": "usersDelete", + "tags": [ + "users" + ], + "description": "Delete a user by its unique ID, thereby releasing it's ID. Since ID is released and can be reused, all user-related resources like documents or storage files should be deleted before user deletion. If you want to keep ID reserved, use the [updateStatus](https:\/\/appwrite.io\/docs\/server\/users#usersUpdateStatus) endpoint instead.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "users", + "weight": 276, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/email": { + "patch": { + "summary": "Update email", + "operationId": "usersUpdateEmail", + "tags": [ + "users" + ], + "description": "Update the user email by its unique ID.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateEmail", + "group": "users", + "weight": 261, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-email.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "x-example": "email@example.com" + } + }, + "required": [ + "email" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/jwts": { + "post": { + "summary": "Create user JWT", + "operationId": "usersCreateJWT", + "tags": [ + "users" + ], + "description": "Use this endpoint to create a JSON Web Token for user by its unique ID. You can use the resulting JWT to authenticate on behalf of the user. The JWT secret will become invalid if the session it uses gets deleted.", + "responses": { + "201": { + "description": "JWT", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/jwt" + } + } + } + } + }, + "x-appwrite": { + "method": "createJWT", + "group": "sessions", + "weight": 279, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-j-w-t.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-user-jwt.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "description": "Session ID. Use the string 'recent' to use the most recent session. Defaults to the most recent session.", + "x-example": "<SESSION_ID>" + }, + "duration": { + "type": "integer", + "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", + "x-example": 0 + } + } + } + } + } + } + } + }, + "\/users\/{userId}\/labels": { + "put": { + "summary": "Update user labels", + "operationId": "usersUpdateLabels", + "tags": [ + "users" + ], + "description": "Update the user labels by its unique ID. \n\nLabels can be used to grant access to resources. While teams are a way for user's to share access to a resource, labels can be defined by the developer to grant access without an invitation. See the [Permissions docs](https:\/\/appwrite.io\/docs\/permissions) for more info.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateLabels", + "group": "users", + "weight": 257, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-labels.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-labels.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "labels": { + "type": "array", + "description": "Array of user labels. Replaces the previous labels. Maximum of 1000 labels are allowed, each up to 36 alphanumeric characters long.", + "x-example": null, + "items": { + "type": "string" + } + } + }, + "required": [ + "labels" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/logs": { + "get": { + "summary": "List user logs", + "operationId": "usersListLogs", + "tags": [ + "users" + ], + "description": "Get the user activity logs list by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/logList" + } + } + } + } + }, + "x-appwrite": { + "method": "listLogs", + "group": "logs", + "weight": 253, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-user-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + } + }, + "\/users\/{userId}\/memberships": { + "get": { + "summary": "List user memberships", + "operationId": "usersListMemberships", + "tags": [ + "users" + ], + "description": "Get the user membership list by its unique ID.", + "responses": { + "200": { + "description": "Memberships List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/membershipList" + } + } + } + } + }, + "x-appwrite": { + "method": "listMemberships", + "group": "memberships", + "weight": 252, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-memberships.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-user-memberships.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "schema": { + "type": "string", + "x-example": "<SEARCH>", + "default": "" + }, + "in": "query" + } + ] + } + }, + "\/users\/{userId}\/mfa": { + "patch": { + "summary": "Update MFA", + "operationId": "usersUpdateMfa", + "tags": [ + "users" + ], + "description": "Enable or disable MFA on a user account.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMfa", + "group": "users", + "weight": 266, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-mfa.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-mfa.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "mfa": { + "type": "boolean", + "description": "Enable or disable MFA.", + "x-example": false + } + }, + "required": [ + "mfa" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/mfa\/authenticators\/{type}": { + "delete": { + "summary": "Delete authenticator", + "operationId": "usersDeleteMfaAuthenticator", + "tags": [ + "users" + ], + "description": "Delete an authenticator app.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteMfaAuthenticator", + "group": "mfa", + "weight": 271, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + }, + { + "name": "type", + "description": "Type of authenticator.", + "required": true, + "schema": { + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [] + }, + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/mfa\/factors": { + "get": { + "summary": "List factors", + "operationId": "usersListMfaFactors", + "tags": [ + "users" + ], + "description": "List the factors available on the account to be used as a MFA challange.", + "responses": { + "200": { + "description": "MFAFactors", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaFactors" + } + } + } + } + }, + "x-appwrite": { + "method": "listMfaFactors", + "group": "mfa", + "weight": 267, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-mfa-factors.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-mfa-factors.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/mfa\/recovery-codes": { + "get": { + "summary": "Get MFA recovery codes", + "operationId": "usersGetMfaRecoveryCodes", + "tags": [ + "users" + ], + "description": "Get recovery codes that can be used as backup for MFA flow by User ID. Before getting codes, they must be generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaRecoveryCodes" + } + } + } + } + }, + "x-appwrite": { + "method": "getMfaRecoveryCodes", + "group": "mfa", + "weight": 268, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/get-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + }, + "put": { + "summary": "Update MFA recovery codes (regenerate)", + "operationId": "usersUpdateMfaRecoveryCodes", + "tags": [ + "users" + ], + "description": "Regenerate recovery codes that can be used as backup for MFA flow by User ID. Before regenerating codes, they must be first generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaRecoveryCodes" + } + } + } + } + }, + "x-appwrite": { + "method": "updateMfaRecoveryCodes", + "group": "mfa", + "weight": 270, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Create MFA recovery codes", + "operationId": "usersCreateMfaRecoveryCodes", + "tags": [ + "users" + ], + "description": "Generate recovery codes used as backup for MFA flow for User ID. Recovery codes can be used as a MFA verification type in [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method by client SDK.", + "responses": { + "201": { + "description": "MFA Recovery Codes", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/mfaRecoveryCodes" + } + } + } + } + }, + "x-appwrite": { + "method": "createMfaRecoveryCodes", + "group": "mfa", + "weight": 269, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/name": { + "patch": { + "summary": "Update name", + "operationId": "usersUpdateName", + "tags": [ + "users" + ], + "description": "Update the user name by its unique ID.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateName", + "group": "users", + "weight": 259, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-name.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-name.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "x-example": "<NAME>" + } + }, + "required": [ + "name" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/password": { + "patch": { + "summary": "Update password", + "operationId": "usersUpdatePassword", + "tags": [ + "users" + ], + "description": "Update the user password by its unique ID.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePassword", + "group": "users", + "weight": 260, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-password.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-password.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "password": { + "type": "string", + "description": "New user password. Must be at least 8 chars.", + "x-example": null + } + }, + "required": [ + "password" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/phone": { + "patch": { + "summary": "Update phone", + "operationId": "usersUpdatePhone", + "tags": [ + "users" + ], + "description": "Update the user phone by its unique ID.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePhone", + "group": "users", + "weight": 262, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-phone.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-phone.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "number": { + "type": "string", + "description": "User phone number.", + "x-example": "+12065550100" + } + }, + "required": [ + "number" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/prefs": { + "get": { + "summary": "Get user preferences", + "operationId": "usersGetPrefs", + "tags": [ + "users" + ], + "description": "Get the user preferences by its unique ID.", + "responses": { + "200": { + "description": "Preferences", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/preferences" + } + } + } + } + }, + "x-appwrite": { + "method": "getPrefs", + "group": "users", + "weight": 249, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/get-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-user-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update user preferences", + "operationId": "usersUpdatePrefs", + "tags": [ + "users" + ], + "description": "Update the user preferences by its unique ID. The object you pass is stored as is, and replaces any previous value. The maximum allowed prefs size is 64kB and throws error if exceeded.", + "responses": { + "200": { + "description": "Preferences", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/preferences" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePrefs", + "group": "users", + "weight": 264, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "prefs": { + "type": "object", + "description": "Prefs key-value JSON object.", + "x-example": "{}" + } + }, + "required": [ + "prefs" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/sessions": { + "get": { + "summary": "List user sessions", + "operationId": "usersListSessions", + "tags": [ + "users" + ], + "description": "Get the user sessions list by its unique ID.", + "responses": { + "200": { + "description": "Sessions List", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/sessionList" + } + } + } + } + }, + "x-appwrite": { + "method": "listSessions", + "group": "sessions", + "weight": 251, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-user-sessions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + }, + "post": { + "summary": "Create session", + "operationId": "usersCreateSession", + "tags": [ + "users" + ], + "description": "Creates a session for a user. Returns an immediately usable session object.\n\nIf you want to generate a token for a custom authentication flow, use the [POST \/users\/{userId}\/tokens](https:\/\/appwrite.io\/docs\/server\/users#createToken) endpoint.", + "responses": { + "201": { + "description": "Session", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/session" + } + } + } + } + }, + "x-appwrite": { + "method": "createSession", + "group": "sessions", + "weight": 272, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-session.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete user sessions", + "operationId": "usersDeleteSessions", + "tags": [ + "users" + ], + "description": "Delete all user's sessions by using the user's unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSessions", + "group": "sessions", + "weight": 275, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-user-sessions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/sessions\/{sessionId}": { + "delete": { + "summary": "Delete user session", + "operationId": "usersDeleteSession", + "tags": [ + "users" + ], + "description": "Delete a user sessions by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSession", + "group": "sessions", + "weight": 274, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-user-session.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + }, + { + "name": "sessionId", + "description": "Session ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<SESSION_ID>" + }, + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/status": { + "patch": { + "summary": "Update user status", + "operationId": "usersUpdateStatus", + "tags": [ + "users" + ], + "description": "Update the user status by its unique ID. Use this endpoint as an alternative to deleting a user if you want to keep user's ID reserved.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateStatus", + "group": "users", + "weight": 256, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "status": { + "type": "boolean", + "description": "User Status. To activate the user pass `true` and to block the user pass `false`.", + "x-example": false + } + }, + "required": [ + "status" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/targets": { + "get": { + "summary": "List user targets", + "operationId": "usersListTargets", + "tags": [ + "users" + ], + "description": "List the messaging targets that are associated with a user.", + "responses": { + "200": { + "description": "Target list", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/targetList" + } + } + } + } + }, + "x-appwrite": { + "method": "listTargets", + "group": "targets", + "weight": 254, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-targets.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-user-targets.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.read", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, providerId, identifier, providerType", + "required": false, + "schema": { + "type": "array", + "items": { + "type": "string" + }, + "default": [] + }, + "in": "query" + } + ] + }, + "post": { + "summary": "Create user target", + "operationId": "usersCreateTarget", + "tags": [ + "users" + ], + "description": "Create a messaging target.", + "responses": { + "201": { + "description": "Target", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/target" + } + } + } + } + }, + "x-appwrite": { + "method": "createTarget", + "group": "targets", + "weight": 246, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "targetId": { + "type": "string", + "description": "Target ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "x-example": "<TARGET_ID>" + }, + "providerType": { + "type": "string", + "description": "The target provider type. Can be one of the following: `email`, `sms` or `push`.", + "x-example": "email", + "enum": [ + "email", + "sms", + "push" + ], + "x-enum-name": "MessagingProviderType", + "x-enum-keys": [] + }, + "identifier": { + "type": "string", + "description": "The target identifier (token, email, phone etc.)", + "x-example": "<IDENTIFIER>" + }, + "providerId": { + "type": "string", + "description": "Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Target name. Max length: 128 chars. For example: My Awesome App Galaxy S23.", + "x-example": "<NAME>" + } + }, + "required": [ + "targetId", + "providerType", + "identifier" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/targets\/{targetId}": { + "get": { + "summary": "Get user target", + "operationId": "usersGetTarget", + "tags": [ + "users" + ], + "description": "Get a user's push notification target by ID.", + "responses": { + "200": { + "description": "Target", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/target" + } + } + } + } + }, + "x-appwrite": { + "method": "getTarget", + "group": "targets", + "weight": 250, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/get-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-user-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.read", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + }, + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TARGET_ID>" + }, + "in": "path" + } + ] + }, + "patch": { + "summary": "Update user target", + "operationId": "usersUpdateTarget", + "tags": [ + "users" + ], + "description": "Update a messaging target.", + "responses": { + "200": { + "description": "Target", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/target" + } + } + } + } + }, + "x-appwrite": { + "method": "updateTarget", + "group": "targets", + "weight": 265, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + }, + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TARGET_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "description": "The target identifier (token, email, phone etc.)", + "x-example": "<IDENTIFIER>" + }, + "providerId": { + "type": "string", + "description": "Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Target name. Max length: 128 chars. For example: My Awesome App Galaxy S23.", + "x-example": "<NAME>" + } + } + } + } + } + } + }, + "delete": { + "summary": "Delete user target", + "operationId": "usersDeleteTarget", + "tags": [ + "users" + ], + "description": "Delete a messaging target.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteTarget", + "group": "targets", + "weight": 277, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + }, + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<TARGET_ID>" + }, + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/tokens": { + "post": { + "summary": "Create token", + "operationId": "usersCreateToken", + "tags": [ + "users" + ], + "description": "Returns a token with a secret key for creating a session. Use the user ID and secret and submit a request to the [PUT \/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process.\n", + "responses": { + "201": { + "description": "Token", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/token" + } + } + } + } + }, + "x-appwrite": { + "method": "createToken", + "group": "sessions", + "weight": 273, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-token.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "length": { + "type": "integer", + "description": "Token length in characters. The default length is 6 characters", + "x-example": 4 + }, + "expire": { + "type": "integer", + "description": "Token expiration period in seconds. The default expiration is 15 minutes.", + "x-example": 60 + } + } + } + } + } + } + } + }, + "\/users\/{userId}\/verification": { + "patch": { + "summary": "Update email verification", + "operationId": "usersUpdateEmailVerification", + "tags": [ + "users" + ], + "description": "Update the user email verification status by its unique ID.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updateEmailVerification", + "group": "users", + "weight": 263, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-email-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-email-verification.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "emailVerification": { + "type": "boolean", + "description": "User email verification status.", + "x-example": false + } + }, + "required": [ + "emailVerification" + ] + } + } + } + } + } + }, + "\/users\/{userId}\/verification\/phone": { + "patch": { + "summary": "Update phone verification", + "operationId": "usersUpdatePhoneVerification", + "tags": [ + "users" + ], + "description": "Update the user phone verification status by its unique ID.", + "responses": { + "200": { + "description": "User", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/user" + } + } + } + } + }, + "x-appwrite": { + "method": "updatePhoneVerification", + "group": "users", + "weight": 258, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-phone-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-phone-verification.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<USER_ID>" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "phoneVerification": { + "type": "boolean", + "description": "User phone verification status.", + "x-example": false + } + }, + "required": [ + "phoneVerification" + ] + } + } + } + } + } + } + }, + "tags": [ + { + "name": "account", + "description": "The Account service allows you to authenticate and manage a user account." + }, + { + "name": "avatars", + "description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars." + }, + { + "name": "databases", + "description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents" + }, + { + "name": "locale", + "description": "The Locale service allows you to customize your app based on your users' location." + }, + { + "name": "health", + "description": "The Health service allows you to both validate and monitor your Appwrite server's health." + }, + { + "name": "projects", + "description": "The Project service allows you to manage all the projects in your Appwrite server." + }, + { + "name": "project", + "description": "The Project service allows you to manage all the projects in your Appwrite server." + }, + { + "name": "storage", + "description": "The Storage service allows you to manage your project files." + }, + { + "name": "teams", + "description": "The Teams service allows you to group users of your project and to enable them to share read and write access to your project resources" + }, + { + "name": "users", + "description": "The Users service allows you to manage your project users." + }, + { + "name": "sites", + "description": "The Sites Service allows you view, create and manage your web applications." + }, + { + "name": "functions", + "description": "The Functions Service allows you view, create and manage your Cloud Functions." + }, + { + "name": "proxy", + "description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration." + }, + { + "name": "graphql", + "description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL." + }, + { + "name": "console", + "description": "The Console service allows you to interact with console relevant informations." + }, + { + "name": "migrations", + "description": "The Migrations service allows you to migrate third-party data to your Appwrite project." + }, + { + "name": "messaging", + "description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.)." + } + ], + "components": { + "schemas": { + "any": { + "description": "Any", + "type": "object", + "additionalProperties": true + }, + "error": { + "description": "Error", + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Error message.", + "x-example": "Not found" + }, + "code": { + "type": "string", + "description": "Error code.", + "x-example": "404" + }, + "type": { + "type": "string", + "description": "Error type. You can learn more about all the error types at https:\/\/appwrite.io\/docs\/error-codes#errorTypes", + "x-example": "not_found" + }, + "version": { + "type": "string", + "description": "Server version number.", + "x-example": "1.0" + } + }, + "required": [ + "message", + "code", + "type", + "version" + ] + }, + "documentList": { + "description": "Documents List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of documents documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "documents": { + "type": "array", + "description": "List of documents.", + "items": { + "$ref": "#\/components\/schemas\/document" + }, + "x-example": "" + } + }, + "required": [ + "total", + "documents" + ] + }, + "collectionList": { + "description": "Collections List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of collections documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "collections": { + "type": "array", + "description": "List of collections.", + "items": { + "$ref": "#\/components\/schemas\/collection" + }, + "x-example": "" + } + }, + "required": [ + "total", + "collections" + ] + }, + "databaseList": { + "description": "Databases List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of databases documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "databases": { + "type": "array", + "description": "List of databases.", + "items": { + "$ref": "#\/components\/schemas\/database" + }, + "x-example": "" + } + }, + "required": [ + "total", + "databases" + ] + }, + "indexList": { + "description": "Indexes List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of indexes documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "indexes": { + "type": "array", + "description": "List of indexes.", + "items": { + "$ref": "#\/components\/schemas\/index" + }, + "x-example": "" + } + }, + "required": [ + "total", + "indexes" + ] + }, + "userList": { + "description": "Users List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of users documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "users": { + "type": "array", + "description": "List of users.", + "items": { + "$ref": "#\/components\/schemas\/user" + }, + "x-example": "" + } + }, + "required": [ + "total", + "users" + ] + }, + "sessionList": { + "description": "Sessions List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of sessions documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "sessions": { + "type": "array", + "description": "List of sessions.", + "items": { + "$ref": "#\/components\/schemas\/session" + }, + "x-example": "" + } + }, + "required": [ + "total", + "sessions" + ] + }, + "identityList": { + "description": "Identities List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of identities documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "identities": { + "type": "array", + "description": "List of identities.", + "items": { + "$ref": "#\/components\/schemas\/identity" + }, + "x-example": "" + } + }, + "required": [ + "total", + "identities" + ] + }, + "logList": { + "description": "Logs List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of logs documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "logs": { + "type": "array", + "description": "List of logs.", + "items": { + "$ref": "#\/components\/schemas\/log" + }, + "x-example": "" + } + }, + "required": [ + "total", + "logs" + ] + }, + "fileList": { + "description": "Files List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of files documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "files": { + "type": "array", + "description": "List of files.", + "items": { + "$ref": "#\/components\/schemas\/file" + }, + "x-example": "" + } + }, + "required": [ + "total", + "files" + ] + }, + "bucketList": { + "description": "Buckets List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of buckets documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "buckets": { + "type": "array", + "description": "List of buckets.", + "items": { + "$ref": "#\/components\/schemas\/bucket" + }, + "x-example": "" + } + }, + "required": [ + "total", + "buckets" + ] + }, + "resourceTokenList": { + "description": "Resource Tokens List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of tokens documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "tokens": { + "type": "array", + "description": "List of tokens.", + "items": { + "$ref": "#\/components\/schemas\/resourceToken" + }, + "x-example": "" + } + }, + "required": [ + "total", + "tokens" + ] + }, + "teamList": { + "description": "Teams List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of teams documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "teams": { + "type": "array", + "description": "List of teams.", + "items": { + "$ref": "#\/components\/schemas\/team" + }, + "x-example": "" + } + }, + "required": [ + "total", + "teams" + ] + }, + "membershipList": { + "description": "Memberships List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of memberships documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "memberships": { + "type": "array", + "description": "List of memberships.", + "items": { + "$ref": "#\/components\/schemas\/membership" + }, + "x-example": "" + } + }, + "required": [ + "total", + "memberships" + ] + }, + "siteList": { + "description": "Sites List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of sites documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "sites": { + "type": "array", + "description": "List of sites.", + "items": { + "$ref": "#\/components\/schemas\/site" + }, + "x-example": "" + } + }, + "required": [ + "total", + "sites" + ] + }, + "functionList": { + "description": "Functions List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of functions documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "functions": { + "type": "array", + "description": "List of functions.", + "items": { + "$ref": "#\/components\/schemas\/function" + }, + "x-example": "" + } + }, + "required": [ + "total", + "functions" + ] + }, + "frameworkList": { + "description": "Frameworks List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of frameworks documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "frameworks": { + "type": "array", + "description": "List of frameworks.", + "items": { + "$ref": "#\/components\/schemas\/framework" + }, + "x-example": "" + } + }, + "required": [ + "total", + "frameworks" + ] + }, + "runtimeList": { + "description": "Runtimes List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of runtimes documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "runtimes": { + "type": "array", + "description": "List of runtimes.", + "items": { + "$ref": "#\/components\/schemas\/runtime" + }, + "x-example": "" + } + }, + "required": [ + "total", + "runtimes" + ] + }, + "deploymentList": { + "description": "Deployments List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of deployments documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "deployments": { + "type": "array", + "description": "List of deployments.", + "items": { + "$ref": "#\/components\/schemas\/deployment" + }, + "x-example": "" + } + }, + "required": [ + "total", + "deployments" + ] + }, + "executionList": { + "description": "Executions List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of executions documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "executions": { + "type": "array", + "description": "List of executions.", + "items": { + "$ref": "#\/components\/schemas\/execution" + }, + "x-example": "" + } + }, + "required": [ + "total", + "executions" + ] + }, + "countryList": { + "description": "Countries List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of countries documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "countries": { + "type": "array", + "description": "List of countries.", + "items": { + "$ref": "#\/components\/schemas\/country" + }, + "x-example": "" + } + }, + "required": [ + "total", + "countries" + ] + }, + "continentList": { + "description": "Continents List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of continents documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "continents": { + "type": "array", + "description": "List of continents.", + "items": { + "$ref": "#\/components\/schemas\/continent" + }, + "x-example": "" + } + }, + "required": [ + "total", + "continents" + ] + }, + "languageList": { + "description": "Languages List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of languages documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "languages": { + "type": "array", + "description": "List of languages.", + "items": { + "$ref": "#\/components\/schemas\/language" + }, + "x-example": "" + } + }, + "required": [ + "total", + "languages" + ] + }, + "currencyList": { + "description": "Currencies List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of currencies documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "currencies": { + "type": "array", + "description": "List of currencies.", + "items": { + "$ref": "#\/components\/schemas\/currency" + }, + "x-example": "" + } + }, + "required": [ + "total", + "currencies" + ] + }, + "phoneList": { + "description": "Phones List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of phones documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "phones": { + "type": "array", + "description": "List of phones.", + "items": { + "$ref": "#\/components\/schemas\/phone" + }, + "x-example": "" + } + }, + "required": [ + "total", + "phones" + ] + }, + "variableList": { + "description": "Variables List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of variables documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "variables": { + "type": "array", + "description": "List of variables.", + "items": { + "$ref": "#\/components\/schemas\/variable" + }, + "x-example": "" + } + }, + "required": [ + "total", + "variables" + ] + }, + "localeCodeList": { + "description": "Locale codes list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of localeCodes documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "localeCodes": { + "type": "array", + "description": "List of localeCodes.", + "items": { + "$ref": "#\/components\/schemas\/localeCode" + }, + "x-example": "" + } + }, + "required": [ + "total", + "localeCodes" + ] + }, + "providerList": { + "description": "Provider list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of providers documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "providers": { + "type": "array", + "description": "List of providers.", + "items": { + "$ref": "#\/components\/schemas\/provider" + }, + "x-example": "" + } + }, + "required": [ + "total", + "providers" + ] + }, + "messageList": { + "description": "Message list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of messages documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "messages": { + "type": "array", + "description": "List of messages.", + "items": { + "$ref": "#\/components\/schemas\/message" + }, + "x-example": "" + } + }, + "required": [ + "total", + "messages" + ] + }, + "topicList": { + "description": "Topic list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of topics documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "topics": { + "type": "array", + "description": "List of topics.", + "items": { + "$ref": "#\/components\/schemas\/topic" + }, + "x-example": "" + } + }, + "required": [ + "total", + "topics" + ] + }, + "subscriberList": { + "description": "Subscriber list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of subscribers documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "subscribers": { + "type": "array", + "description": "List of subscribers.", + "items": { + "$ref": "#\/components\/schemas\/subscriber" + }, + "x-example": "" + } + }, + "required": [ + "total", + "subscribers" + ] + }, + "targetList": { + "description": "Target list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of targets documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "targets": { + "type": "array", + "description": "List of targets.", + "items": { + "$ref": "#\/components\/schemas\/target" + }, + "x-example": "" + } + }, + "required": [ + "total", + "targets" + ] + }, + "specificationList": { + "description": "Specifications List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of specifications documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "specifications": { + "type": "array", + "description": "List of specifications.", + "items": { + "$ref": "#\/components\/schemas\/specification" + }, + "x-example": "" + } + }, + "required": [ + "total", + "specifications" + ] + }, + "database": { + "description": "Database", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Database ID.", + "x-example": "5e5ea5c16897e" + }, + "name": { + "type": "string", + "description": "Database name.", + "x-example": "My Database" + }, + "$createdAt": { + "type": "string", + "description": "Database creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Database update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "enabled": { + "type": "boolean", + "description": "If database is enabled. Can be 'enabled' or 'disabled'. When disabled, the database is inaccessible to users, but remains accessible to Server SDKs using API keys.", + "x-example": false + } + }, + "required": [ + "$id", + "name", + "$createdAt", + "$updatedAt", + "enabled" + ] + }, + "collection": { + "description": "Collection", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Collection ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Collection creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Collection update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Collection permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + }, + "databaseId": { + "type": "string", + "description": "Database ID.", + "x-example": "5e5ea5c16897e" + }, + "name": { + "type": "string", + "description": "Collection name.", + "x-example": "My Collection" + }, + "enabled": { + "type": "boolean", + "description": "Collection enabled. Can be 'enabled' or 'disabled'. When disabled, the collection is inaccessible to users, but remains accessible to Server SDKs using API keys.", + "x-example": false + }, + "documentSecurity": { + "type": "boolean", + "description": "Whether document-level permissions are enabled. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": true + }, + "attributes": { + "type": "array", + "description": "Collection attributes.", + "items": { + "anyOf": [ + { + "$ref": "#\/components\/schemas\/attributeBoolean" + }, + { + "$ref": "#\/components\/schemas\/attributeInteger" + }, + { + "$ref": "#\/components\/schemas\/attributeFloat" + }, + { + "$ref": "#\/components\/schemas\/attributeEmail" + }, + { + "$ref": "#\/components\/schemas\/attributeEnum" + }, + { + "$ref": "#\/components\/schemas\/attributeUrl" + }, + { + "$ref": "#\/components\/schemas\/attributeIp" + }, + { + "$ref": "#\/components\/schemas\/attributeDatetime" + }, + { + "$ref": "#\/components\/schemas\/attributeRelationship" + }, + { + "$ref": "#\/components\/schemas\/attributeString" + } + ] + }, + "x-example": {} + }, + "indexes": { + "type": "array", + "description": "Collection indexes.", + "items": { + "$ref": "#\/components\/schemas\/index" + }, + "x-example": {} + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "$permissions", + "databaseId", + "name", + "enabled", + "documentSecurity", + "attributes", + "indexes" + ] + }, + "attributeList": { + "description": "Attributes List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of attributes in the given collection.", + "x-example": 5, + "format": "int32" + }, + "attributes": { + "type": "array", + "description": "List of attributes.", + "items": { + "anyOf": [ + { + "$ref": "#\/components\/schemas\/attributeBoolean" + }, + { + "$ref": "#\/components\/schemas\/attributeInteger" + }, + { + "$ref": "#\/components\/schemas\/attributeFloat" + }, + { + "$ref": "#\/components\/schemas\/attributeEmail" + }, + { + "$ref": "#\/components\/schemas\/attributeEnum" + }, + { + "$ref": "#\/components\/schemas\/attributeUrl" + }, + { + "$ref": "#\/components\/schemas\/attributeIp" + }, + { + "$ref": "#\/components\/schemas\/attributeDatetime" + }, + { + "$ref": "#\/components\/schemas\/attributeRelationship" + }, + { + "$ref": "#\/components\/schemas\/attributeString" + } + ] + }, + "x-example": "" + } + }, + "required": [ + "total", + "attributes" + ] + }, + "attributeString": { + "description": "AttributeString", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "fullName" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "size": { + "type": "integer", + "description": "Attribute size.", + "x-example": 128, + "format": "int32" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "default", + "nullable": true + }, + "encrypt": { + "type": "boolean", + "description": "Defines whether this attribute is encrypted or not.", + "x-example": false, + "nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "size" + ] + }, + "attributeInteger": { + "description": "AttributeInteger", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "count" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "integer" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "min": { + "type": "integer", + "description": "Minimum value to enforce for new documents.", + "x-example": 1, + "format": "int32", + "nullable": true + }, + "max": { + "type": "integer", + "description": "Maximum value to enforce for new documents.", + "x-example": 10, + "format": "int32", + "nullable": true + }, + "default": { + "type": "integer", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": 10, + "format": "int32", + "nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt" + ] + }, + "attributeFloat": { + "description": "AttributeFloat", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "percentageCompleted" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "double" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "min": { + "type": "number", + "description": "Minimum value to enforce for new documents.", + "x-example": 1.5, + "format": "double", + "nullable": true + }, + "max": { + "type": "number", + "description": "Maximum value to enforce for new documents.", + "x-example": 10.5, + "format": "double", + "nullable": true + }, + "default": { + "type": "number", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": 2.5, + "format": "double", + "nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt" + ] + }, + "attributeBoolean": { + "description": "AttributeBoolean", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "isEnabled" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "boolean" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "default": { + "type": "boolean", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": false, + "nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt" + ] + }, + "attributeEmail": { + "description": "AttributeEmail", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "userEmail" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "format": { + "type": "string", + "description": "String format.", + "x-example": "email" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "default@example.com", + "nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "format" + ] + }, + "attributeEnum": { + "description": "AttributeEnum", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "status" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "elements": { + "type": "array", + "description": "Array of elements in enumerated type.", + "items": { + "type": "string" + }, + "x-example": "element" + }, + "format": { + "type": "string", + "description": "String format.", + "x-example": "enum" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "element", + "nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "elements", + "format" + ] + }, + "attributeIp": { + "description": "AttributeIP", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "ipAddress" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "format": { + "type": "string", + "description": "String format.", + "x-example": "ip" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "192.0.2.0", + "nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "format" + ] + }, + "attributeUrl": { + "description": "AttributeURL", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "githubUrl" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "format": { + "type": "string", + "description": "String format.", + "x-example": "url" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "http:\/\/example.com", + "nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "format" + ] + }, + "attributeDatetime": { + "description": "AttributeDatetime", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "birthDay" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "datetime" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "format": { + "type": "string", + "description": "ISO 8601 format.", + "x-example": "datetime" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Only null is optional", + "x-example": "2020-10-15T06:38:00.000+00:00", + "nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "format" + ] + }, + "attributeRelationship": { + "description": "AttributeRelationship", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "fullName" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "relatedCollection": { + "type": "string", + "description": "The ID of the related collection.", + "x-example": "collection" + }, + "relationType": { + "type": "string", + "description": "The type of the relationship.", + "x-example": "oneToOne|oneToMany|manyToOne|manyToMany" + }, + "twoWay": { + "type": "boolean", + "description": "Is the relationship two-way?", + "x-example": false + }, + "twoWayKey": { + "type": "string", + "description": "The key of the two-way relationship.", + "x-example": "string" + }, + "onDelete": { + "type": "string", + "description": "How deleting the parent document will propagate to child documents.", + "x-example": "restrict|cascade|setNull" + }, + "side": { + "type": "string", + "description": "Whether this is the parent or child side of the relationship", + "x-example": "parent|child" + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "relatedCollection", + "relationType", + "twoWay", + "twoWayKey", + "onDelete", + "side" + ] + }, + "index": { + "description": "Index", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Index Key.", + "x-example": "index1" + }, + "type": { + "type": "string", + "description": "Index type.", + "x-example": "primary" + }, + "status": { + "type": "string", + "description": "Index status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an index.", + "x-example": "string" + }, + "attributes": { + "type": "array", + "description": "Index attributes.", + "items": { + "type": "string" + }, + "x-example": [] + }, + "lengths": { + "type": "array", + "description": "Index attributes length.", + "items": { + "type": "integer", + "format": "int32" + }, + "x-example": [] + }, + "orders": { + "type": "array", + "description": "Index orders.", + "items": { + "type": "string" + }, + "x-example": [], + "nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Index creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Index update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "key", + "type", + "status", + "error", + "attributes", + "lengths", + "$createdAt", + "$updatedAt" + ] + }, + "document": { + "description": "Document", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Document ID.", + "x-example": "5e5ea5c16897e" + }, + "$sequence": { + "type": "integer", + "description": "Document automatically incrementing ID.", + "x-example": 1, + "format": "int32" + }, + "$collectionId": { + "type": "string", + "description": "Collection ID.", + "x-example": "5e5ea5c15117e" + }, + "$databaseId": { + "type": "string", + "description": "Database ID.", + "x-example": "5e5ea5c15117e" + }, + "$createdAt": { + "type": "string", + "description": "Document creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Document update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Document permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + } + }, + "additionalProperties": true, + "required": [ + "$id", + "$sequence", + "$collectionId", + "$databaseId", + "$createdAt", + "$updatedAt", + "$permissions" + ] + }, + "log": { + "description": "Log", + "type": "object", + "properties": { + "event": { + "type": "string", + "description": "Event name.", + "x-example": "account.sessions.create" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "610fc2f985ee0" + }, + "userEmail": { + "type": "string", + "description": "User Email.", + "x-example": "john@appwrite.io" + }, + "userName": { + "type": "string", + "description": "User Name.", + "x-example": "John Doe" + }, + "mode": { + "type": "string", + "description": "API mode when event triggered.", + "x-example": "admin" + }, + "ip": { + "type": "string", + "description": "IP session in use when the session was created.", + "x-example": "127.0.0.1" + }, + "time": { + "type": "string", + "description": "Log creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "osCode": { + "type": "string", + "description": "Operating system code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/os.json).", + "x-example": "Mac" + }, + "osName": { + "type": "string", + "description": "Operating system name.", + "x-example": "Mac" + }, + "osVersion": { + "type": "string", + "description": "Operating system version.", + "x-example": "Mac" + }, + "clientType": { + "type": "string", + "description": "Client type.", + "x-example": "browser" + }, + "clientCode": { + "type": "string", + "description": "Client code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/clients.json).", + "x-example": "CM" + }, + "clientName": { + "type": "string", + "description": "Client name.", + "x-example": "Chrome Mobile iOS" + }, + "clientVersion": { + "type": "string", + "description": "Client version.", + "x-example": "84.0" + }, + "clientEngine": { + "type": "string", + "description": "Client engine name.", + "x-example": "WebKit" + }, + "clientEngineVersion": { + "type": "string", + "description": "Client engine name.", + "x-example": "605.1.15" + }, + "deviceName": { + "type": "string", + "description": "Device name.", + "x-example": "smartphone" + }, + "deviceBrand": { + "type": "string", + "description": "Device brand name.", + "x-example": "Google" + }, + "deviceModel": { + "type": "string", + "description": "Device model name.", + "x-example": "Nexus 5" + }, + "countryCode": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + }, + "countryName": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + } + }, + "required": [ + "event", + "userId", + "userEmail", + "userName", + "mode", + "ip", + "time", + "osCode", + "osName", + "osVersion", + "clientType", + "clientCode", + "clientName", + "clientVersion", + "clientEngine", + "clientEngineVersion", + "deviceName", + "deviceBrand", + "deviceModel", + "countryCode", + "countryName" + ] + }, + "user": { + "description": "User", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "User creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "User update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "User name.", + "x-example": "John Doe" + }, + "password": { + "type": "string", + "description": "Hashed user password.", + "x-example": "$argon2id$v=19$m=2048,t=4,p=3$aUZjLnliVWRINmFNTWMudg$5S+x+7uA31xFnrHFT47yFwcJeaP0w92L\/4LdgrVRXxE", + "nullable": true + }, + "hash": { + "type": "string", + "description": "Password hashing algorithm.", + "x-example": "argon2", + "nullable": true + }, + "hashOptions": { + "type": "object", + "description": "Password hashing algorithm configuration.", + "x-example": {}, + "items": { + "oneOf": [ + { + "$ref": "#\/components\/schemas\/algoArgon2" + }, + { + "$ref": "#\/components\/schemas\/algoScrypt" + }, + { + "$ref": "#\/components\/schemas\/algoScryptModified" + }, + { + "$ref": "#\/components\/schemas\/algoBcrypt" + }, + { + "$ref": "#\/components\/schemas\/algoPhpass" + }, + { + "$ref": "#\/components\/schemas\/algoSha" + }, + { + "$ref": "#\/components\/schemas\/algoMd5" + } + ] + }, + "nullable": true + }, + "registration": { + "type": "string", + "description": "User registration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "boolean", + "description": "User status. Pass `true` for enabled and `false` for disabled.", + "x-example": true + }, + "labels": { + "type": "array", + "description": "Labels for the user.", + "items": { + "type": "string" + }, + "x-example": [ + "vip" + ] + }, + "passwordUpdate": { + "type": "string", + "description": "Password update time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "email": { + "type": "string", + "description": "User email address.", + "x-example": "john@appwrite.io" + }, + "phone": { + "type": "string", + "description": "User phone number in E.164 format.", + "x-example": "+4930901820" + }, + "emailVerification": { + "type": "boolean", + "description": "Email verification status.", + "x-example": true + }, + "phoneVerification": { + "type": "boolean", + "description": "Phone verification status.", + "x-example": true + }, + "mfa": { + "type": "boolean", + "description": "Multi factor authentication status.", + "x-example": true + }, + "prefs": { + "type": "object", + "description": "User preferences as a key-value object", + "x-example": { + "theme": "pink", + "timezone": "UTC" + }, + "items": { + "$ref": "#\/components\/schemas\/preferences" + } + }, + "targets": { + "type": "array", + "description": "A user-owned message receiver. A single user may have multiple e.g. emails, phones, and a browser. Each target is registered with a single provider.", + "items": { + "$ref": "#\/components\/schemas\/target" + }, + "x-example": [] + }, + "accessedAt": { + "type": "string", + "description": "Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "registration", + "status", + "labels", + "passwordUpdate", + "email", + "phone", + "emailVerification", + "phoneVerification", + "mfa", + "prefs", + "targets", + "accessedAt" + ] + }, + "algoMd5": { + "description": "AlgoMD5", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "md5" + } + }, + "required": [ + "type" + ] + }, + "algoSha": { + "description": "AlgoSHA", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "sha" + } + }, + "required": [ + "type" + ] + }, + "algoPhpass": { + "description": "AlgoPHPass", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "phpass" + } + }, + "required": [ + "type" + ] + }, + "algoBcrypt": { + "description": "AlgoBcrypt", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "bcrypt" + } + }, + "required": [ + "type" + ] + }, + "algoScrypt": { + "description": "AlgoScrypt", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "scrypt" + }, + "costCpu": { + "type": "integer", + "description": "CPU complexity of computed hash.", + "x-example": 8, + "format": "int32" + }, + "costMemory": { + "type": "integer", + "description": "Memory complexity of computed hash.", + "x-example": 14, + "format": "int32" + }, + "costParallel": { + "type": "integer", + "description": "Parallelization of computed hash.", + "x-example": 1, + "format": "int32" + }, + "length": { + "type": "integer", + "description": "Length used to compute hash.", + "x-example": 64, + "format": "int32" + } + }, + "required": [ + "type", + "costCpu", + "costMemory", + "costParallel", + "length" + ] + }, + "algoScryptModified": { + "description": "AlgoScryptModified", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "scryptMod" + }, + "salt": { + "type": "string", + "description": "Salt used to compute hash.", + "x-example": "UxLMreBr6tYyjQ==" + }, + "saltSeparator": { + "type": "string", + "description": "Separator used to compute hash.", + "x-example": "Bw==" + }, + "signerKey": { + "type": "string", + "description": "Key used to compute hash.", + "x-example": "XyEKE9RcTDeLEsL\/RjwPDBv\/RqDl8fb3gpYEOQaPihbxf1ZAtSOHCjuAAa7Q3oHpCYhXSN9tizHgVOwn6krflQ==" + } + }, + "required": [ + "type", + "salt", + "saltSeparator", + "signerKey" + ] + }, + "algoArgon2": { + "description": "AlgoArgon2", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "argon2" + }, + "memoryCost": { + "type": "integer", + "description": "Memory used to compute hash.", + "x-example": 65536, + "format": "int32" + }, + "timeCost": { + "type": "integer", + "description": "Amount of time consumed to compute hash", + "x-example": 4, + "format": "int32" + }, + "threads": { + "type": "integer", + "description": "Number of threads used to compute hash.", + "x-example": 3, + "format": "int32" + } + }, + "required": [ + "type", + "memoryCost", + "timeCost", + "threads" + ] + }, + "preferences": { + "description": "Preferences", + "type": "object", + "additionalProperties": true + }, + "session": { + "description": "Session", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Session ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Session creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Session update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5bb8c16897e" + }, + "expire": { + "type": "string", + "description": "Session expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "provider": { + "type": "string", + "description": "Session Provider.", + "x-example": "email" + }, + "providerUid": { + "type": "string", + "description": "Session Provider User ID.", + "x-example": "user@example.com" + }, + "providerAccessToken": { + "type": "string", + "description": "Session Provider Access Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + }, + "providerAccessTokenExpiry": { + "type": "string", + "description": "The date of when the access token expires in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "providerRefreshToken": { + "type": "string", + "description": "Session Provider Refresh Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + }, + "ip": { + "type": "string", + "description": "IP in use when the session was created.", + "x-example": "127.0.0.1" + }, + "osCode": { + "type": "string", + "description": "Operating system code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/os.json).", + "x-example": "Mac" + }, + "osName": { + "type": "string", + "description": "Operating system name.", + "x-example": "Mac" + }, + "osVersion": { + "type": "string", + "description": "Operating system version.", + "x-example": "Mac" + }, + "clientType": { + "type": "string", + "description": "Client type.", + "x-example": "browser" + }, + "clientCode": { + "type": "string", + "description": "Client code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/clients.json).", + "x-example": "CM" + }, + "clientName": { + "type": "string", + "description": "Client name.", + "x-example": "Chrome Mobile iOS" + }, + "clientVersion": { + "type": "string", + "description": "Client version.", + "x-example": "84.0" + }, + "clientEngine": { + "type": "string", + "description": "Client engine name.", + "x-example": "WebKit" + }, + "clientEngineVersion": { + "type": "string", + "description": "Client engine name.", + "x-example": "605.1.15" + }, + "deviceName": { + "type": "string", + "description": "Device name.", + "x-example": "smartphone" + }, + "deviceBrand": { + "type": "string", + "description": "Device brand name.", + "x-example": "Google" + }, + "deviceModel": { + "type": "string", + "description": "Device model name.", + "x-example": "Nexus 5" + }, + "countryCode": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + }, + "countryName": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + }, + "current": { + "type": "boolean", + "description": "Returns true if this the current user session.", + "x-example": true + }, + "factors": { + "type": "array", + "description": "Returns a list of active session factors.", + "items": { + "type": "string" + }, + "x-example": [ + "email" + ] + }, + "secret": { + "type": "string", + "description": "Secret used to authenticate the user. Only included if the request was made with an API key", + "x-example": "5e5bb8c16897e" + }, + "mfaUpdatedAt": { + "type": "string", + "description": "Most recent date in ISO 8601 format when the session successfully passed MFA challenge.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "userId", + "expire", + "provider", + "providerUid", + "providerAccessToken", + "providerAccessTokenExpiry", + "providerRefreshToken", + "ip", + "osCode", + "osName", + "osVersion", + "clientType", + "clientCode", + "clientName", + "clientVersion", + "clientEngine", + "clientEngineVersion", + "deviceName", + "deviceBrand", + "deviceModel", + "countryCode", + "countryName", + "current", + "factors", + "secret", + "mfaUpdatedAt" + ] + }, + "identity": { + "description": "Identity", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Identity ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Identity creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Identity update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5bb8c16897e" + }, + "provider": { + "type": "string", + "description": "Identity Provider.", + "x-example": "email" + }, + "providerUid": { + "type": "string", + "description": "ID of the User in the Identity Provider.", + "x-example": "5e5bb8c16897e" + }, + "providerEmail": { + "type": "string", + "description": "Email of the User in the Identity Provider.", + "x-example": "user@example.com" + }, + "providerAccessToken": { + "type": "string", + "description": "Identity Provider Access Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + }, + "providerAccessTokenExpiry": { + "type": "string", + "description": "The date of when the access token expires in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "providerRefreshToken": { + "type": "string", + "description": "Identity Provider Refresh Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "userId", + "provider", + "providerUid", + "providerEmail", + "providerAccessToken", + "providerAccessTokenExpiry", + "providerRefreshToken" + ] + }, + "token": { + "description": "Token", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Token ID.", + "x-example": "bb8ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Token creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c168bb8" + }, + "secret": { + "type": "string", + "description": "Token secret key. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.", + "x-example": "" + }, + "expire": { + "type": "string", + "description": "Token expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "phrase": { + "type": "string", + "description": "Security phrase of a token. Empty if security phrase was not requested when creating a token. It includes randomly generated phrase which is also sent in the external resource such as email.", + "x-example": "Golden Fox" + } + }, + "required": [ + "$id", + "$createdAt", + "userId", + "secret", + "expire", + "phrase" + ] + }, + "jwt": { + "description": "JWT", + "type": "object", + "properties": { + "jwt": { + "type": "string", + "description": "JWT encoded string.", + "x-example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + } + }, + "required": [ + "jwt" + ] + }, + "locale": { + "description": "Locale", + "type": "object", + "properties": { + "ip": { + "type": "string", + "description": "User IP address.", + "x-example": "127.0.0.1" + }, + "countryCode": { + "type": "string", + "description": "Country code in [ISO 3166-1](http:\/\/en.wikipedia.org\/wiki\/ISO_3166-1) two-character format", + "x-example": "US" + }, + "country": { + "type": "string", + "description": "Country name. This field support localization.", + "x-example": "United States" + }, + "continentCode": { + "type": "string", + "description": "Continent code. A two character continent code \"AF\" for Africa, \"AN\" for Antarctica, \"AS\" for Asia, \"EU\" for Europe, \"NA\" for North America, \"OC\" for Oceania, and \"SA\" for South America.", + "x-example": "NA" + }, + "continent": { + "type": "string", + "description": "Continent name. This field support localization.", + "x-example": "North America" + }, + "eu": { + "type": "boolean", + "description": "True if country is part of the European Union.", + "x-example": false + }, + "currency": { + "type": "string", + "description": "Currency code in [ISO 4217-1](http:\/\/en.wikipedia.org\/wiki\/ISO_4217) three-character format", + "x-example": "USD" + } + }, + "required": [ + "ip", + "countryCode", + "country", + "continentCode", + "continent", + "eu", + "currency" + ] + }, + "localeCode": { + "description": "LocaleCode", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Locale codes in [ISO 639-1](https:\/\/en.wikipedia.org\/wiki\/List_of_ISO_639-1_codes)", + "x-example": "en-us" + }, + "name": { + "type": "string", + "description": "Locale name", + "x-example": "US" + } + }, + "required": [ + "code", + "name" + ] + }, + "file": { + "description": "File", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "File ID.", + "x-example": "5e5ea5c16897e" + }, + "bucketId": { + "type": "string", + "description": "Bucket ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "File creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "File update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "File permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + }, + "name": { + "type": "string", + "description": "File name.", + "x-example": "Pink.png" + }, + "signature": { + "type": "string", + "description": "File MD5 signature.", + "x-example": "5d529fd02b544198ae075bd57c1762bb" + }, + "mimeType": { + "type": "string", + "description": "File mime type.", + "x-example": "image\/png" + }, + "sizeOriginal": { + "type": "integer", + "description": "File original size in bytes.", + "x-example": 17890, + "format": "int32" + }, + "chunksTotal": { + "type": "integer", + "description": "Total number of chunks available", + "x-example": 17890, + "format": "int32" + }, + "chunksUploaded": { + "type": "integer", + "description": "Total number of chunks uploaded", + "x-example": 17890, + "format": "int32" + } + }, + "required": [ + "$id", + "bucketId", + "$createdAt", + "$updatedAt", + "$permissions", + "name", + "signature", + "mimeType", + "sizeOriginal", + "chunksTotal", + "chunksUploaded" + ] + }, + "bucket": { + "description": "Bucket", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Bucket ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Bucket creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Bucket update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Bucket permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + }, + "fileSecurity": { + "type": "boolean", + "description": "Whether file-level security is enabled. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": true + }, + "name": { + "type": "string", + "description": "Bucket name.", + "x-example": "Documents" + }, + "enabled": { + "type": "boolean", + "description": "Bucket enabled.", + "x-example": false + }, + "maximumFileSize": { + "type": "integer", + "description": "Maximum file size supported.", + "x-example": 100, + "format": "int32" + }, + "allowedFileExtensions": { + "type": "array", + "description": "Allowed file extensions.", + "items": { + "type": "string" + }, + "x-example": [ + "jpg", + "png" + ] + }, + "compression": { + "type": "string", + "description": "Compression algorithm choosen for compression. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).", + "x-example": "gzip" + }, + "encryption": { + "type": "boolean", + "description": "Bucket is encrypted.", + "x-example": false + }, + "antivirus": { + "type": "boolean", + "description": "Virus scanning is enabled.", + "x-example": false + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "$permissions", + "fileSecurity", + "name", + "enabled", + "maximumFileSize", + "allowedFileExtensions", + "compression", + "encryption", + "antivirus" + ] + }, + "resourceToken": { + "description": "ResourceToken", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Token ID.", + "x-example": "bb8ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Token creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "resourceId": { + "type": "string", + "description": "Resource ID.", + "x-example": "5e5ea5c168bb8:5e5ea5c168bb8" + }, + "resourceType": { + "type": "string", + "description": "Resource type.", + "x-example": "files" + }, + "expire": { + "type": "string", + "description": "Token expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "secret": { + "type": "string", + "description": "JWT encoded string.", + "x-example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + }, + "accessedAt": { + "type": "string", + "description": "Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "resourceId", + "resourceType", + "expire", + "secret", + "accessedAt" + ] + }, + "team": { + "description": "Team", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Team ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Team creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Team update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Team name.", + "x-example": "VIP" + }, + "total": { + "type": "integer", + "description": "Total number of team members.", + "x-example": 7, + "format": "int32" + }, + "prefs": { + "type": "object", + "description": "Team preferences as a key-value object", + "x-example": { + "theme": "pink", + "timezone": "UTC" + }, + "items": { + "$ref": "#\/components\/schemas\/preferences" + } + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "total", + "prefs" + ] + }, + "membership": { + "description": "Membership", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Membership ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Membership creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Membership update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c16897e" + }, + "userName": { + "type": "string", + "description": "User name. Hide this attribute by toggling membership privacy in the Console.", + "x-example": "John Doe" + }, + "userEmail": { + "type": "string", + "description": "User email address. Hide this attribute by toggling membership privacy in the Console.", + "x-example": "john@appwrite.io" + }, + "teamId": { + "type": "string", + "description": "Team ID.", + "x-example": "5e5ea5c16897e" + }, + "teamName": { + "type": "string", + "description": "Team name.", + "x-example": "VIP" + }, + "invited": { + "type": "string", + "description": "Date, the user has been invited to join the team in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "joined": { + "type": "string", + "description": "Date, the user has accepted the invitation to join the team in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "confirm": { + "type": "boolean", + "description": "User confirmation status, true if the user has joined the team or false otherwise.", + "x-example": false + }, + "mfa": { + "type": "boolean", + "description": "Multi factor authentication status, true if the user has MFA enabled or false otherwise. Hide this attribute by toggling membership privacy in the Console.", + "x-example": false + }, + "roles": { + "type": "array", + "description": "User list of roles", + "items": { + "type": "string" + }, + "x-example": [ + "owner" + ] + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "userId", + "userName", + "userEmail", + "teamId", + "teamName", + "invited", + "joined", + "confirm", + "mfa", + "roles" + ] + }, + "site": { + "description": "Site", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Site ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Site creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Site update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Site name.", + "x-example": "My Site" + }, + "enabled": { + "type": "boolean", + "description": "Site enabled.", + "x-example": false + }, + "live": { + "type": "boolean", + "description": "Is the site deployed with the latest configuration? This is set to false if you've changed an environment variables, entrypoint, commands, or other settings that needs redeploy to be applied. When the value is false, redeploy the site to update it with the latest configuration.", + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.", + "x-example": false + }, + "framework": { + "type": "string", + "description": "Site framework.", + "x-example": "react" + }, + "deploymentId": { + "type": "string", + "description": "Site's active deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "deploymentCreatedAt": { + "type": "string", + "description": "Active deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "deploymentScreenshotLight": { + "type": "string", + "description": "Screenshot of active deployment with light theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "deploymentScreenshotDark": { + "type": "string", + "description": "Screenshot of active deployment with dark theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentId": { + "type": "string", + "description": "Site's latest deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentCreatedAt": { + "type": "string", + "description": "Latest deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentStatus": { + "type": "string", + "description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, + "vars": { + "type": "array", + "description": "Site variables.", + "items": { + "$ref": "#\/components\/schemas\/variable" + }, + "x-example": [] + }, + "timeout": { + "type": "integer", + "description": "Site request timeout in seconds.", + "x-example": 300, + "format": "int32" + }, + "installCommand": { + "type": "string", + "description": "The install command used to install the site dependencies.", + "x-example": "npm install" + }, + "buildCommand": { + "type": "string", + "description": "The build command used to build the site.", + "x-example": "npm run build" + }, + "outputDirectory": { + "type": "string", + "description": "The directory where the site build output is located.", + "x-example": "build" + }, + "installationId": { + "type": "string", + "description": "Site VCS (Version Control System) installation id.", + "x-example": "6m40at4ejk5h2u9s1hboo" + }, + "providerRepositoryId": { + "type": "string", + "description": "VCS (Version Control System) Repository ID", + "x-example": "appwrite" + }, + "providerBranch": { + "type": "string", + "description": "VCS (Version Control System) branch name", + "x-example": "main" + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to site in VCS (Version Control System) repository", + "x-example": "sites\/helloWorld" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is VCS (Version Control System) connection is in silent mode? When in silence mode, no comments will be posted on the repository pull or merge requests", + "x-example": false + }, + "specification": { + "type": "string", + "description": "Machine specification for builds and executions.", + "x-example": "s-1vcpu-512mb" + }, + "buildRuntime": { + "type": "string", + "description": "Site build runtime.", + "x-example": "node-22" + }, + "adapter": { + "type": "string", + "description": "Site framework adapter.", + "x-example": "static" + }, + "fallbackFile": { + "type": "string", + "description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.", + "x-example": "index.html" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "enabled", + "live", + "logging", + "framework", + "deploymentId", + "deploymentCreatedAt", + "deploymentScreenshotLight", + "deploymentScreenshotDark", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", + "vars", + "timeout", + "installCommand", + "buildCommand", + "outputDirectory", + "installationId", + "providerRepositoryId", + "providerBranch", + "providerRootDirectory", + "providerSilentMode", + "specification", + "buildRuntime", + "adapter", + "fallbackFile" + ] + }, + "function": { + "description": "Function", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Function ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Function creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Function update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "execute": { + "type": "array", + "description": "Execution permissions.", + "items": { + "type": "string" + }, + "x-example": "users" + }, + "name": { + "type": "string", + "description": "Function name.", + "x-example": "My Function" + }, + "enabled": { + "type": "boolean", + "description": "Function enabled.", + "x-example": false + }, + "live": { + "type": "boolean", + "description": "Is the function deployed with the latest configuration? This is set to false if you've changed an environment variables, entrypoint, commands, or other settings that needs redeploy to be applied. When the value is false, redeploy the function to update it with the latest configuration.", + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", + "x-example": false + }, + "runtime": { + "type": "string", + "description": "Function execution and build runtime.", + "x-example": "python-3.8" + }, + "deploymentId": { + "type": "string", + "description": "Function's active deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "deploymentCreatedAt": { + "type": "string", + "description": "Active deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentId": { + "type": "string", + "description": "Function's latest deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentCreatedAt": { + "type": "string", + "description": "Latest deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentStatus": { + "type": "string", + "description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, + "scopes": { + "type": "array", + "description": "Allowed permission scopes.", + "items": { + "type": "string" + }, + "x-example": "users.read" + }, + "vars": { + "type": "array", + "description": "Function variables.", + "items": { + "$ref": "#\/components\/schemas\/variable" + }, + "x-example": [] + }, + "events": { + "type": "array", + "description": "Function trigger events.", + "items": { + "type": "string" + }, + "x-example": "account.create" + }, + "schedule": { + "type": "string", + "description": "Function execution schedule in CRON format.", + "x-example": "5 4 * * *" + }, + "timeout": { + "type": "integer", + "description": "Function execution timeout in seconds.", + "x-example": 300, + "format": "int32" + }, + "entrypoint": { + "type": "string", + "description": "The entrypoint file used to execute the deployment.", + "x-example": "index.js" + }, + "commands": { + "type": "string", + "description": "The build command used to build the deployment.", + "x-example": "npm install" + }, + "version": { + "type": "string", + "description": "Version of Open Runtimes used for the function.", + "x-example": "v2" + }, + "installationId": { + "type": "string", + "description": "Function VCS (Version Control System) installation id.", + "x-example": "6m40at4ejk5h2u9s1hboo" + }, + "providerRepositoryId": { + "type": "string", + "description": "VCS (Version Control System) Repository ID", + "x-example": "appwrite" + }, + "providerBranch": { + "type": "string", + "description": "VCS (Version Control System) branch name", + "x-example": "main" + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to function in VCS (Version Control System) repository", + "x-example": "functions\/helloWorld" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is VCS (Version Control System) connection is in silent mode? When in silence mode, no comments will be posted on the repository pull or merge requests", + "x-example": false + }, + "specification": { + "type": "string", + "description": "Machine specification for builds and executions.", + "x-example": "s-1vcpu-512mb" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "execute", + "name", + "enabled", + "live", + "logging", + "runtime", + "deploymentId", + "deploymentCreatedAt", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", + "scopes", + "vars", + "events", + "schedule", + "timeout", + "entrypoint", + "commands", + "version", + "installationId", + "providerRepositoryId", + "providerBranch", + "providerRootDirectory", + "providerSilentMode", + "specification" + ] + }, + "runtime": { + "description": "Runtime", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Runtime ID.", + "x-example": "python-3.8" + }, + "key": { + "type": "string", + "description": "Parent runtime key.", + "x-example": "python" + }, + "name": { + "type": "string", + "description": "Runtime Name.", + "x-example": "Python" + }, + "version": { + "type": "string", + "description": "Runtime version.", + "x-example": "3.8" + }, + "base": { + "type": "string", + "description": "Base Docker image used to build the runtime.", + "x-example": "python:3.8-alpine" + }, + "image": { + "type": "string", + "description": "Image name of Docker Hub.", + "x-example": "appwrite\\\/runtime-for-python:3.8" + }, + "logo": { + "type": "string", + "description": "Name of the logo image.", + "x-example": "python.png" + }, + "supports": { + "type": "array", + "description": "List of supported architectures.", + "items": { + "type": "string" + }, + "x-example": "amd64" + } + }, + "required": [ + "$id", + "key", + "name", + "version", + "base", + "image", + "logo", + "supports" + ] + }, + "framework": { + "description": "Framework", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Framework key.", + "x-example": "sveltekit" + }, + "name": { + "type": "string", + "description": "Framework Name.", + "x-example": "SvelteKit" + }, + "buildRuntime": { + "type": "string", + "description": "Default runtime version.", + "x-example": "node-22" + }, + "runtimes": { + "type": "array", + "description": "List of supported runtime versions.", + "items": { + "type": "string" + }, + "x-example": [ + "static-1", + "node-22" + ] + }, + "adapters": { + "type": "array", + "description": "List of supported adapters.", + "items": { + "$ref": "#\/components\/schemas\/frameworkAdapter" + }, + "x-example": [ + { + "key": "static", + "buildRuntime": "node-22", + "buildCommand": "npm run build", + "installCommand": "npm install", + "outputDirectory": ".\/dist" + } + ] + } + }, + "required": [ + "key", + "name", + "buildRuntime", + "runtimes", + "adapters" + ] + }, + "frameworkAdapter": { + "description": "Framework Adapter", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Adapter key.", + "x-example": "static" + }, + "installCommand": { + "type": "string", + "description": "Default command to download dependencies.", + "x-example": "npm install" + }, + "buildCommand": { + "type": "string", + "description": "Default command to build site into output directory.", + "x-example": "npm run build" + }, + "outputDirectory": { + "type": "string", + "description": "Default output directory of build.", + "x-example": ".\/dist" + }, + "fallbackFile": { + "type": "string", + "description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.", + "x-example": "index.html" + } + }, + "required": [ + "key", + "installCommand", + "buildCommand", + "outputDirectory", + "fallbackFile" + ] + }, + "deployment": { + "description": "Deployment", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Deployment update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "type": { + "type": "string", + "description": "Type of deployment.", + "x-example": "vcs" + }, + "resourceId": { + "type": "string", + "description": "Resource ID.", + "x-example": "5e5ea6g16897e" + }, + "resourceType": { + "type": "string", + "description": "Resource type.", + "x-example": "functions" + }, + "entrypoint": { + "type": "string", + "description": "The entrypoint file to use to execute the deployment code.", + "x-example": "index.js" + }, + "sourceSize": { + "type": "integer", + "description": "The code size in bytes.", + "x-example": 128, + "format": "int32" + }, + "buildSize": { + "type": "integer", + "description": "The build output size in bytes.", + "x-example": 128, + "format": "int32" + }, + "totalSize": { + "type": "integer", + "description": "The total size in bytes (source and build output).", + "x-example": 128, + "format": "int32" + }, + "buildId": { + "type": "string", + "description": "The current build ID.", + "x-example": "5e5ea5c16897e" + }, + "activate": { + "type": "boolean", + "description": "Whether the deployment should be automatically activated.", + "x-example": true + }, + "screenshotLight": { + "type": "string", + "description": "Screenshot with light theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "screenshotDark": { + "type": "string", + "description": "Screenshot with dark theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "status": { + "type": "string", + "description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, + "buildLogs": { + "type": "string", + "description": "The build logs.", + "x-example": "Compiling source files..." + }, + "buildDuration": { + "type": "integer", + "description": "The current build time in seconds.", + "x-example": 128, + "format": "int32" + }, + "providerRepositoryName": { + "type": "string", + "description": "The name of the vcs provider repository", + "x-example": "database" + }, + "providerRepositoryOwner": { + "type": "string", + "description": "The name of the vcs provider repository owner", + "x-example": "utopia" + }, + "providerRepositoryUrl": { + "type": "string", + "description": "The url of the vcs provider repository", + "x-example": "https:\/\/github.com\/vermakhushboo\/g4-node-function" + }, + "providerBranch": { + "type": "string", + "description": "The branch of the vcs repository", + "x-example": "0.7.x" + }, + "providerCommitHash": { + "type": "string", + "description": "The commit hash of the vcs commit", + "x-example": "7c3f25d" + }, + "providerCommitAuthorUrl": { + "type": "string", + "description": "The url of vcs commit author", + "x-example": "https:\/\/github.com\/vermakhushboo" + }, + "providerCommitAuthor": { + "type": "string", + "description": "The name of vcs commit author", + "x-example": "Khushboo Verma" + }, + "providerCommitMessage": { + "type": "string", + "description": "The commit message", + "x-example": "Update index.js" + }, + "providerCommitUrl": { + "type": "string", + "description": "The url of the vcs commit", + "x-example": "https:\/\/github.com\/vermakhushboo\/g4-node-function\/commit\/60c0416257a9cbcdd96b2d370c38d8f8d150ccfb" + }, + "providerBranchUrl": { + "type": "string", + "description": "The branch of the vcs repository", + "x-example": "https:\/\/github.com\/vermakhushboo\/appwrite\/tree\/0.7.x" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "type", + "resourceId", + "resourceType", + "entrypoint", + "sourceSize", + "buildSize", + "totalSize", + "buildId", + "activate", + "screenshotLight", + "screenshotDark", + "status", + "buildLogs", + "buildDuration", + "providerRepositoryName", + "providerRepositoryOwner", + "providerRepositoryUrl", + "providerBranch", + "providerCommitHash", + "providerCommitAuthorUrl", + "providerCommitAuthor", + "providerCommitMessage", + "providerCommitUrl", + "providerBranchUrl" + ] + }, + "execution": { + "description": "Execution", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Execution ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Execution creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Execution upate date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Execution roles.", + "items": { + "type": "string" + }, + "x-example": [ + "any" + ] + }, + "functionId": { + "type": "string", + "description": "Function ID.", + "x-example": "5e5ea6g16897e" + }, + "trigger": { + "type": "string", + "description": "The trigger that caused the function to execute. Possible values can be: `http`, `schedule`, or `event`.", + "x-example": "http" + }, + "status": { + "type": "string", + "description": "The status of the function execution. Possible values can be: `waiting`, `processing`, `completed`, or `failed`.", + "x-example": "processing" + }, + "requestMethod": { + "type": "string", + "description": "HTTP request method type.", + "x-example": "GET" + }, + "requestPath": { + "type": "string", + "description": "HTTP request path and query.", + "x-example": "\/articles?id=5" + }, + "requestHeaders": { + "type": "array", + "description": "HTTP response headers as a key-value object. This will return only whitelisted headers. All headers are returned if execution is created as synchronous.", + "items": { + "$ref": "#\/components\/schemas\/headers" + }, + "x-example": [ + { + "Content-Type": "application\/json" + } + ] + }, + "responseStatusCode": { + "type": "integer", + "description": "HTTP response status code.", + "x-example": 200, + "format": "int32" + }, + "responseBody": { + "type": "string", + "description": "HTTP response body. This will return empty unless execution is created as synchronous.", + "x-example": "" + }, + "responseHeaders": { + "type": "array", + "description": "HTTP response headers as a key-value object. This will return only whitelisted headers. All headers are returned if execution is created as synchronous.", + "items": { + "$ref": "#\/components\/schemas\/headers" + }, + "x-example": [ + { + "Content-Type": "application\/json" + } + ] + }, + "logs": { + "type": "string", + "description": "Function logs. Includes the last 4,000 characters. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.", + "x-example": "" + }, + "errors": { + "type": "string", + "description": "Function errors. Includes the last 4,000 characters. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.", + "x-example": "" + }, + "duration": { + "type": "number", + "description": "Resource(function\/site) execution duration in seconds.", + "x-example": 0.4, + "format": "double" + }, + "scheduledAt": { + "type": "string", + "description": "The scheduled time for execution. If left empty, execution will be queued immediately.", + "x-example": "2020-10-15T06:38:00.000+00:00", + "nullable": true + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "$permissions", + "functionId", + "trigger", + "status", + "requestMethod", + "requestPath", + "requestHeaders", + "responseStatusCode", + "responseBody", + "responseHeaders", + "logs", + "errors", + "duration" + ] + }, + "variable": { + "description": "Variable", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Variable ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Variable creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Variable creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "key": { + "type": "string", + "description": "Variable key.", + "x-example": "API_KEY" + }, + "value": { + "type": "string", + "description": "Variable value.", + "x-example": "myPa$$word1" + }, + "secret": { + "type": "boolean", + "description": "Variable secret flag. Secret variables can only be updated or deleted, but never read.", + "x-example": false + }, + "resourceType": { + "type": "string", + "description": "Service to which the variable belongs. Possible values are \"project\", \"function\"", + "x-example": "function" + }, + "resourceId": { + "type": "string", + "description": "ID of resource to which the variable belongs. If resourceType is \"project\", it is empty. If resourceType is \"function\", it is ID of the function.", + "x-example": "myAwesomeFunction" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "key", + "value", + "secret", + "resourceType", + "resourceId" + ] + }, + "country": { + "description": "Country", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + }, + "code": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + } + }, + "required": [ + "name", + "code" + ] + }, + "continent": { + "description": "Continent", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Continent name.", + "x-example": "Europe" + }, + "code": { + "type": "string", + "description": "Continent two letter code.", + "x-example": "EU" + } + }, + "required": [ + "name", + "code" + ] + }, + "language": { + "description": "Language", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Language name.", + "x-example": "Italian" + }, + "code": { + "type": "string", + "description": "Language two-character ISO 639-1 codes.", + "x-example": "it" + }, + "nativeName": { + "type": "string", + "description": "Language native name.", + "x-example": "Italiano" + } + }, + "required": [ + "name", + "code", + "nativeName" + ] + }, + "currency": { + "description": "Currency", + "type": "object", + "properties": { + "symbol": { + "type": "string", + "description": "Currency symbol.", + "x-example": "$" + }, + "name": { + "type": "string", + "description": "Currency name.", + "x-example": "US dollar" + }, + "symbolNative": { + "type": "string", + "description": "Currency native symbol.", + "x-example": "$" + }, + "decimalDigits": { + "type": "integer", + "description": "Number of decimal digits.", + "x-example": 2, + "format": "int32" + }, + "rounding": { + "type": "number", + "description": "Currency digit rounding.", + "x-example": 0, + "format": "double" + }, + "code": { + "type": "string", + "description": "Currency code in [ISO 4217-1](http:\/\/en.wikipedia.org\/wiki\/ISO_4217) three-character format.", + "x-example": "USD" + }, + "namePlural": { + "type": "string", + "description": "Currency plural name", + "x-example": "US dollars" + } + }, + "required": [ + "symbol", + "name", + "symbolNative", + "decimalDigits", + "rounding", + "code", + "namePlural" + ] + }, + "phone": { + "description": "Phone", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Phone code.", + "x-example": "+1" + }, + "countryCode": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + }, + "countryName": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + } + }, + "required": [ + "code", + "countryCode", + "countryName" + ] + }, + "healthAntivirus": { + "description": "Health Antivirus", + "type": "object", + "properties": { + "version": { + "type": "string", + "description": "Antivirus version.", + "x-example": "1.0.0" + }, + "status": { + "type": "string", + "description": "Antivirus status. Possible values can are: `disabled`, `offline`, `online`", + "x-example": "online" + } + }, + "required": [ + "version", + "status" + ] + }, + "healthQueue": { + "description": "Health Queue", + "type": "object", + "properties": { + "size": { + "type": "integer", + "description": "Amount of actions in the queue.", + "x-example": 8, + "format": "int32" + } + }, + "required": [ + "size" + ] + }, + "healthStatus": { + "description": "Health Status", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the service.", + "x-example": "database" + }, + "ping": { + "type": "integer", + "description": "Duration in milliseconds how long the health check took.", + "x-example": 128, + "format": "int32" + }, + "status": { + "type": "string", + "description": "Service status. Possible values can are: `pass`, `fail`", + "x-example": "pass" + } + }, + "required": [ + "name", + "ping", + "status" + ] + }, + "healthCertificate": { + "description": "Health Certificate", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Certificate name", + "x-example": "\/CN=www.google.com" + }, + "subjectSN": { + "type": "string", + "description": "Subject SN", + "x-example": "" + }, + "issuerOrganisation": { + "type": "string", + "description": "Issuer organisation", + "x-example": "" + }, + "validFrom": { + "type": "string", + "description": "Valid from", + "x-example": "1704200998" + }, + "validTo": { + "type": "string", + "description": "Valid to", + "x-example": "1711458597" + }, + "signatureTypeSN": { + "type": "string", + "description": "Signature type SN", + "x-example": "RSA-SHA256" + } + }, + "required": [ + "name", + "subjectSN", + "issuerOrganisation", + "validFrom", + "validTo", + "signatureTypeSN" + ] + }, + "healthTime": { + "description": "Health Time", + "type": "object", + "properties": { + "remoteTime": { + "type": "integer", + "description": "Current unix timestamp on trustful remote server.", + "x-example": 1639490751, + "format": "int32" + }, + "localTime": { + "type": "integer", + "description": "Current unix timestamp of local server where Appwrite runs.", + "x-example": 1639490844, + "format": "int32" + }, + "diff": { + "type": "integer", + "description": "Difference of unix remote and local timestamps in milliseconds.", + "x-example": 93, + "format": "int32" + } + }, + "required": [ + "remoteTime", + "localTime", + "diff" + ] + }, + "headers": { + "description": "Headers", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Header name.", + "x-example": "Content-Type" + }, + "value": { + "type": "string", + "description": "Header value.", + "x-example": "application\/json" + } + }, + "required": [ + "name", + "value" + ] + }, + "specification": { + "description": "Specification", + "type": "object", + "properties": { + "memory": { + "type": "integer", + "description": "Memory size in MB.", + "x-example": 512, + "format": "int32" + }, + "cpus": { + "type": "number", + "description": "Number of CPUs.", + "x-example": 1, + "format": "double" + }, + "enabled": { + "type": "boolean", + "description": "Is size enabled.", + "x-example": true + }, + "slug": { + "type": "string", + "description": "Size slug.", + "x-example": "s-1vcpu-512mb" + } + }, + "required": [ + "memory", + "cpus", + "enabled", + "slug" + ] + }, + "mfaChallenge": { + "description": "MFA Challenge", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Token ID.", + "x-example": "bb8ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Token creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c168bb8" + }, + "expire": { + "type": "string", + "description": "Token expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "userId", + "expire" + ] + }, + "mfaRecoveryCodes": { + "description": "MFA Recovery Codes", + "type": "object", + "properties": { + "recoveryCodes": { + "type": "array", + "description": "Recovery codes.", + "items": { + "type": "string" + }, + "x-example": [ + "a3kf0-s0cl2", + "s0co1-as98s" + ] + } + }, + "required": [ + "recoveryCodes" + ] + }, + "mfaType": { + "description": "MFAType", + "type": "object", + "properties": { + "secret": { + "type": "string", + "description": "Secret token used for TOTP factor.", + "x-example": true + }, + "uri": { + "type": "string", + "description": "URI for authenticator apps.", + "x-example": true + } + }, + "required": [ + "secret", + "uri" + ] + }, + "mfaFactors": { + "description": "MFAFactors", + "type": "object", + "properties": { + "totp": { + "type": "boolean", + "description": "Can TOTP be used for MFA challenge for this account.", + "x-example": true + }, + "phone": { + "type": "boolean", + "description": "Can phone (SMS) be used for MFA challenge for this account.", + "x-example": true + }, + "email": { + "type": "boolean", + "description": "Can email be used for MFA challenge for this account.", + "x-example": true + }, + "recoveryCode": { + "type": "boolean", + "description": "Can recovery code be used for MFA challenge for this account.", + "x-example": true + } + }, + "required": [ + "totp", + "phone", + "email", + "recoveryCode" + ] + }, + "provider": { + "description": "Provider", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Provider ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Provider creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Provider update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "The name for the provider instance.", + "x-example": "Mailgun" + }, + "provider": { + "type": "string", + "description": "The name of the provider service.", + "x-example": "mailgun" + }, + "enabled": { + "type": "boolean", + "description": "Is provider enabled?", + "x-example": true + }, + "type": { + "type": "string", + "description": "Type of provider.", + "x-example": "sms" + }, + "credentials": { + "type": "object", + "description": "Provider credentials.", + "x-example": { + "key": "123456789" + } + }, + "options": { + "type": "object", + "description": "Provider options.", + "x-example": { + "from": "sender-email@mydomain" + }, + "nullable": true + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "provider", + "enabled", + "type", + "credentials" + ] + }, + "message": { + "description": "Message", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Message ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Message creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Message update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "providerType": { + "type": "string", + "description": "Message provider type.", + "x-example": "email" + }, + "topics": { + "type": "array", + "description": "Topic IDs set as recipients.", + "items": { + "type": "string" + }, + "x-example": [ + "5e5ea5c16897e" + ] + }, + "users": { + "type": "array", + "description": "User IDs set as recipients.", + "items": { + "type": "string" + }, + "x-example": [ + "5e5ea5c16897e" + ] + }, + "targets": { + "type": "array", + "description": "Target IDs set as recipients.", + "items": { + "type": "string" + }, + "x-example": [ + "5e5ea5c16897e" + ] + }, + "scheduledAt": { + "type": "string", + "description": "The scheduled time for message.", + "x-example": "2020-10-15T06:38:00.000+00:00", + "nullable": true + }, + "deliveredAt": { + "type": "string", + "description": "The time when the message was delivered.", + "x-example": "2020-10-15T06:38:00.000+00:00", + "nullable": true + }, + "deliveryErrors": { + "type": "array", + "description": "Delivery errors if any.", + "items": { + "type": "string" + }, + "x-example": [ + "Failed to send message to target 5e5ea5c16897e: Credentials not valid." + ], + "nullable": true + }, + "deliveredTotal": { + "type": "integer", + "description": "Number of recipients the message was delivered to.", + "x-example": 1, + "format": "int32" + }, + "data": { + "type": "object", + "description": "Data of the message.", + "x-example": { + "subject": "Welcome to Appwrite", + "content": "Hi there, welcome to Appwrite family." + } + }, + "status": { + "type": "string", + "description": "Status of delivery.", + "x-example": "Message status can be one of the following: draft, processing, scheduled, sent, or failed." + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "providerType", + "topics", + "users", + "targets", + "deliveredTotal", + "data", + "status" + ] + }, + "topic": { + "description": "Topic", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Topic ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Topic creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Topic update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "The name of the topic.", + "x-example": "events" + }, + "emailTotal": { + "type": "integer", + "description": "Total count of email subscribers subscribed to the topic.", + "x-example": 100, + "format": "int32" + }, + "smsTotal": { + "type": "integer", + "description": "Total count of SMS subscribers subscribed to the topic.", + "x-example": 100, + "format": "int32" + }, + "pushTotal": { + "type": "integer", + "description": "Total count of push subscribers subscribed to the topic.", + "x-example": 100, + "format": "int32" + }, + "subscribe": { + "type": "array", + "description": "Subscribe permissions.", + "items": { + "type": "string" + }, + "x-example": "users" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "emailTotal", + "smsTotal", + "pushTotal", + "subscribe" + ] + }, + "subscriber": { + "description": "Subscriber", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Subscriber ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Subscriber creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Subscriber update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "targetId": { + "type": "string", + "description": "Target ID.", + "x-example": "259125845563242502" + }, + "target": { + "type": "object", + "description": "Target.", + "x-example": { + "$id": "259125845563242502", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "providerType": "email", + "providerId": "259125845563242502", + "name": "ageon-app-email", + "identifier": "random-mail@email.org", + "userId": "5e5ea5c16897e" + }, + "items": { + "$ref": "#\/components\/schemas\/target" + } + }, + "userId": { + "type": "string", + "description": "Topic ID.", + "x-example": "5e5ea5c16897e" + }, + "userName": { + "type": "string", + "description": "User Name.", + "x-example": "Aegon Targaryen" + }, + "topicId": { + "type": "string", + "description": "Topic ID.", + "x-example": "259125845563242502" + }, + "providerType": { + "type": "string", + "description": "The target provider type. Can be one of the following: `email`, `sms` or `push`.", + "x-example": "email" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "targetId", + "target", + "userId", + "userName", + "topicId", + "providerType" + ] + }, + "target": { + "description": "Target", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Target ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Target creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Target update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Target Name.", + "x-example": "Apple iPhone 12" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "259125845563242502" + }, + "providerId": { + "type": "string", + "description": "Provider ID.", + "x-example": "259125845563242502", + "nullable": true + }, + "providerType": { + "type": "string", + "description": "The target provider type. Can be one of the following: `email`, `sms` or `push`.", + "x-example": "email" + }, + "identifier": { + "type": "string", + "description": "The target identifier.", + "x-example": "token" + }, + "expired": { + "type": "boolean", + "description": "Is the target expired.", + "x-example": false + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "userId", + "providerType", + "identifier", + "expired" + ] + } + }, + "securitySchemes": { + "Project": { + "type": "apiKey", + "name": "X-Appwrite-Project", + "description": "Your project ID", + "in": "header", + "x-appwrite": { + "demo": "<YOUR_PROJECT_ID>" + } + }, + "Key": { + "type": "apiKey", + "name": "X-Appwrite-Key", + "description": "Your secret API key", + "in": "header", + "x-appwrite": { + "demo": "<YOUR_API_KEY>" + } + }, + "JWT": { + "type": "apiKey", + "name": "X-Appwrite-JWT", + "description": "Your secret JSON Web Token", + "in": "header" + }, + "Locale": { + "type": "apiKey", + "name": "X-Appwrite-Locale", + "description": "", + "in": "header", + "x-appwrite": { + "demo": "en" + } + }, + "Session": { + "type": "apiKey", + "name": "X-Appwrite-Session", + "description": "The user session to authenticate with", + "in": "header" + }, + "ForwardedUserAgent": { + "type": "apiKey", + "name": "X-Forwarded-User-Agent", + "description": "The user agent string of the client that made the request", + "in": "header" + } + } + }, + "externalDocs": { + "description": "Full API docs, specs and tutorials", + "url": "https:\/\/appwrite.io\/docs" + } +} \ No newline at end of file diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index bbb78c6c66..fd2752e337 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -4890,7 +4890,7 @@ "x-appwrite": { "method": "deleteDocument", "group": "documents", - "weight": 117, + "weight": 119, "cookies": false, "type": "", "deprecated": false, @@ -4951,6 +4951,234 @@ ] } }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/decrement": { + "patch": { + "summary": "Decrement document attribute", + "operationId": "databasesDecrementDocumentAttribute", + "tags": [ + "databases" + ], + "description": "Decrement a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "decrementDocumentAttribute", + "group": "documents", + "weight": 116, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/decrement-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/decrement-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DOCUMENT_ID>" + }, + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to decrement the attribute by. The value must be a number.", + "x-example": null + }, + "min": { + "type": "mixed", + "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", + "x-example": null + } + } + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/increment": { + "patch": { + "summary": "Increment document attribute", + "operationId": "databasesIncrementDocumentAttribute", + "tags": [ + "databases" + ], + "description": "Increment a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "incrementDocumentAttribute", + "group": "documents", + "weight": 115, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/increment-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/increment-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DOCUMENT_ID>" + }, + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to increment the attribute by. The value must be a number.", + "x-example": null + }, + "max": { + "type": "mixed", + "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", + "x-example": null + } + } + } + } + } + } + } + }, "\/functions\/{functionId}\/executions": { "get": { "summary": "List executions", @@ -4974,7 +5202,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 392, + "weight": 394, "cookies": false, "type": "", "deprecated": false, @@ -5049,7 +5277,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 390, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -5164,7 +5392,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 391, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -5238,7 +5466,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 306, + "weight": 308, "cookies": false, "type": "graphql", "deprecated": false, @@ -5290,7 +5518,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 305, + "weight": 307, "cookies": false, "type": "graphql", "deprecated": false, @@ -5342,7 +5570,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 122, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -5394,7 +5622,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 123, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -5446,7 +5674,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 127, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -5498,7 +5726,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 124, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -5550,7 +5778,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 125, + "weight": 127, "cookies": false, "type": "", "deprecated": false, @@ -5602,7 +5830,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 126, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -5654,7 +5882,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 128, + "weight": 130, "cookies": false, "type": "", "deprecated": false, @@ -5706,7 +5934,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 129, + "weight": 131, "cookies": false, "type": "", "deprecated": false, @@ -5758,7 +5986,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 352, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -5841,7 +6069,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 356, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -5916,7 +6144,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 212, + "weight": 214, "cookies": false, "type": "", "deprecated": false, @@ -6002,7 +6230,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 211, + "weight": 213, "cookies": false, "type": "upload", "deprecated": false, @@ -6100,7 +6328,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 213, + "weight": 215, "cookies": false, "type": "", "deprecated": false, @@ -6172,7 +6400,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 218, + "weight": 220, "cookies": false, "type": "", "deprecated": false, @@ -6261,7 +6489,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 219, + "weight": 221, "cookies": false, "type": "", "deprecated": false, @@ -6328,7 +6556,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 215, + "weight": 217, "cookies": false, "type": "location", "deprecated": false, @@ -6406,7 +6634,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 214, + "weight": 216, "cookies": false, "type": "location", "deprecated": false, @@ -6595,7 +6823,8 @@ "png", "webp", "heic", - "avif" + "avif", + "gif" ], "x-enum-name": "ImageFormat", "x-enum-keys": [], @@ -6633,7 +6862,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 216, + "weight": 218, "cookies": false, "type": "location", "deprecated": false, @@ -6718,7 +6947,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 223, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -6794,7 +7023,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 222, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -6879,7 +7108,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 224, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -6941,7 +7170,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 226, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -7015,7 +7244,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 228, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -7079,7 +7308,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 230, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -7165,7 +7394,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 229, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -7276,7 +7505,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 231, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -7348,7 +7577,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 232, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -7435,7 +7664,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 234, + "weight": 236, "cookies": false, "type": "", "deprecated": false, @@ -7509,7 +7738,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 233, + "weight": 235, "cookies": false, "type": "", "deprecated": false, @@ -7607,7 +7836,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 225, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -7668,7 +7897,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 227, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -8182,6 +8411,12 @@ "description": "Document ID.", "x-example": "5e5ea5c16897e" }, + "$sequence": { + "type": "integer", + "description": "Document automatically incrementing ID.", + "x-example": 1, + "format": "int32" + }, "$collectionId": { "type": "string", "description": "Collection ID.", @@ -8216,6 +8451,7 @@ "additionalProperties": true, "required": [ "$id", + "$sequence", "$collectionId", "$databaseId", "$createdAt", diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 187281716f..4372df4eb3 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -4359,7 +4359,7 @@ "x-appwrite": { "method": "chat", "group": "console", - "weight": 308, + "weight": 310, "cookies": false, "type": "", "deprecated": false, @@ -4419,7 +4419,7 @@ "x-appwrite": { "method": "getResource", "group": null, - "weight": 432, + "weight": 434, "cookies": false, "type": "", "deprecated": false, @@ -4494,7 +4494,7 @@ "x-appwrite": { "method": "variables", "group": "console", - "weight": 307, + "weight": 309, "cookies": false, "type": "", "deprecated": false, @@ -4694,7 +4694,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 119, + "weight": 121, "cookies": false, "type": "", "deprecated": false, @@ -8167,7 +8167,7 @@ "x-appwrite": { "method": "upsertDocuments", "group": "documents", - "weight": 116, + "weight": 118, "cookies": false, "type": "", "deprecated": false, @@ -8258,7 +8258,7 @@ "x-appwrite": { "method": "updateDocuments", "group": "documents", - "weight": 115, + "weight": 117, "cookies": false, "type": "", "deprecated": false, @@ -8351,7 +8351,7 @@ "x-appwrite": { "method": "deleteDocuments", "group": "documents", - "weight": 118, + "weight": 120, "cookies": false, "type": "", "deprecated": false, @@ -8744,7 +8744,7 @@ "x-appwrite": { "method": "deleteDocument", "group": "documents", - "weight": 117, + "weight": 119, "cookies": false, "type": "", "deprecated": false, @@ -8898,6 +8898,234 @@ ] } }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/decrement": { + "patch": { + "summary": "Decrement document attribute", + "operationId": "databasesDecrementDocumentAttribute", + "tags": [ + "databases" + ], + "description": "Decrement a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "decrementDocumentAttribute", + "group": "documents", + "weight": 116, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/decrement-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/decrement-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DOCUMENT_ID>" + }, + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to decrement the attribute by. The value must be a number.", + "x-example": null + }, + "min": { + "type": "mixed", + "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", + "x-example": null + } + } + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/increment": { + "patch": { + "summary": "Increment document attribute", + "operationId": "databasesIncrementDocumentAttribute", + "tags": [ + "databases" + ], + "description": "Increment a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "incrementDocumentAttribute", + "group": "documents", + "weight": 115, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/increment-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/increment-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DOCUMENT_ID>" + }, + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to increment the attribute by. The value must be a number.", + "x-example": null + }, + "max": { + "type": "mixed", + "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", + "x-example": null + } + } + } + } + } + } + } + }, "\/databases\/{databaseId}\/collections\/{collectionId}\/indexes": { "get": { "summary": "List indexes", @@ -9365,7 +9593,7 @@ "x-appwrite": { "method": "getCollectionUsage", "group": null, - "weight": 121, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -9530,7 +9758,7 @@ "x-appwrite": { "method": "getDatabaseUsage", "group": null, - "weight": 120, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -9612,7 +9840,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 376, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -9685,7 +9913,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 373, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -9767,6 +9995,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -9792,7 +10021,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -9916,7 +10146,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 378, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -9965,7 +10195,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 379, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -10015,7 +10245,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 402, + "weight": 404, "cookies": false, "type": "", "deprecated": false, @@ -10115,7 +10345,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 401, + "weight": 403, "cookies": false, "type": "", "deprecated": false, @@ -10175,7 +10405,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 395, + "weight": 397, "cookies": false, "type": "", "deprecated": false, @@ -10247,7 +10477,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 374, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -10306,7 +10536,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 375, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -10395,6 +10625,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -10420,7 +10651,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -10534,7 +10766,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 377, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -10595,7 +10827,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 382, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -10675,7 +10907,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 383, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -10758,7 +10990,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 380, + "weight": 382, "cookies": false, "type": "upload", "deprecated": false, @@ -10854,7 +11086,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 388, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -10939,7 +11171,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 385, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -11042,7 +11274,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 386, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -11139,7 +11371,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 381, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -11201,7 +11433,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 384, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -11265,7 +11497,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 387, + "weight": 389, "cookies": false, "type": "location", "deprecated": false, @@ -11355,7 +11587,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 389, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -11426,7 +11658,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 392, + "weight": 394, "cookies": false, "type": "", "deprecated": false, @@ -11501,7 +11733,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 390, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -11616,7 +11848,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 391, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -11681,7 +11913,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 393, + "weight": 395, "cookies": false, "type": "", "deprecated": false, @@ -11752,7 +11984,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 394, + "weight": 396, "cookies": false, "type": "", "deprecated": false, @@ -11834,7 +12066,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 398, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -11893,7 +12125,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 396, + "weight": 398, "cookies": false, "type": "", "deprecated": false, @@ -11984,7 +12216,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 397, + "weight": 399, "cookies": false, "type": "", "deprecated": false, @@ -12053,7 +12285,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 399, + "weight": 401, "cookies": false, "type": "", "deprecated": false, @@ -12144,7 +12376,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 400, + "weight": 402, "cookies": false, "type": "", "deprecated": false, @@ -12215,7 +12447,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 306, + "weight": 308, "cookies": false, "type": "graphql", "deprecated": false, @@ -12267,7 +12499,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 305, + "weight": 307, "cookies": false, "type": "graphql", "deprecated": false, @@ -12319,7 +12551,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 130, + "weight": 132, "cookies": false, "type": "", "deprecated": false, @@ -12368,7 +12600,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 151, + "weight": 153, "cookies": false, "type": "", "deprecated": false, @@ -12417,7 +12649,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 133, + "weight": 135, "cookies": false, "type": "", "deprecated": false, @@ -12466,7 +12698,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 138, + "weight": 140, "cookies": false, "type": "", "deprecated": false, @@ -12526,7 +12758,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 132, + "weight": 134, "cookies": false, "type": "", "deprecated": false, @@ -12575,7 +12807,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 134, + "weight": 136, "cookies": false, "type": "", "deprecated": false, @@ -12624,7 +12856,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 140, + "weight": 142, "cookies": false, "type": "", "deprecated": false, @@ -12686,7 +12918,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 139, + "weight": 141, "cookies": false, "type": "", "deprecated": false, @@ -12748,7 +12980,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 141, + "weight": 143, "cookies": false, "type": "", "deprecated": false, @@ -12821,7 +13053,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 142, + "weight": 144, "cookies": false, "type": "", "deprecated": false, @@ -12883,7 +13115,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 152, + "weight": 154, "cookies": false, "type": "", "deprecated": false, @@ -12971,7 +13203,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 146, + "weight": 148, "cookies": false, "type": "", "deprecated": false, @@ -13033,7 +13265,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 137, + "weight": 139, "cookies": false, "type": "", "deprecated": false, @@ -13095,7 +13327,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 143, + "weight": 145, "cookies": false, "type": "", "deprecated": false, @@ -13157,7 +13389,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 144, + "weight": 146, "cookies": false, "type": "", "deprecated": false, @@ -13219,7 +13451,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 145, + "weight": 147, "cookies": false, "type": "", "deprecated": false, @@ -13281,7 +13513,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 147, + "weight": 149, "cookies": false, "type": "", "deprecated": false, @@ -13343,7 +13575,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 148, + "weight": 150, "cookies": false, "type": "", "deprecated": false, @@ -13405,7 +13637,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 136, + "weight": 138, "cookies": false, "type": "", "deprecated": false, @@ -13467,7 +13699,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 150, + "weight": 152, "cookies": false, "type": "", "deprecated": false, @@ -13516,7 +13748,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 149, + "weight": 151, "cookies": false, "type": "", "deprecated": false, @@ -13565,7 +13797,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 135, + "weight": 137, "cookies": false, "type": "", "deprecated": false, @@ -13614,7 +13846,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 122, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -13666,7 +13898,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 123, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -13718,7 +13950,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 127, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -13770,7 +14002,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 124, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -13822,7 +14054,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 125, + "weight": 127, "cookies": false, "type": "", "deprecated": false, @@ -13874,7 +14106,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 126, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -13926,7 +14158,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 128, + "weight": 130, "cookies": false, "type": "", "deprecated": false, @@ -13978,7 +14210,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 129, + "weight": 131, "cookies": false, "type": "", "deprecated": false, @@ -14030,7 +14262,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 360, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -14106,7 +14338,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 357, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -14250,7 +14482,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 364, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -14396,7 +14628,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 359, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -14570,7 +14802,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 366, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -14748,7 +14980,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 358, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -14857,7 +15089,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 365, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -14969,7 +15201,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 363, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -15022,7 +15254,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 367, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -15084,7 +15316,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 361, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -15159,7 +15391,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 362, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -15234,7 +15466,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 332, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -15310,7 +15542,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 331, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -15415,7 +15647,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 344, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -15523,7 +15755,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 330, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -15608,7 +15840,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 343, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -15696,7 +15928,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 322, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -15811,7 +16043,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 335, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -15929,7 +16161,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 325, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -16024,7 +16256,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 338, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -16122,7 +16354,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 323, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -16227,7 +16459,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 336, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -16335,7 +16567,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 324, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -16478,7 +16710,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 337, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -16623,7 +16855,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 326, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -16718,7 +16950,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 339, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -16816,7 +17048,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 327, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -16911,7 +17143,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 340, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -17009,7 +17241,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 328, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -17104,7 +17336,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 341, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -17202,7 +17434,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 329, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -17297,7 +17529,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 342, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -17395,7 +17627,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 334, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -17448,7 +17680,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 345, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -17510,7 +17742,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 333, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -17585,7 +17817,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 354, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -17660,7 +17892,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 347, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -17734,7 +17966,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 346, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -17817,7 +18049,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 349, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -17877,7 +18109,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 350, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -17954,7 +18186,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 351, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -18016,7 +18248,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 348, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -18091,7 +18323,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 353, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -18175,7 +18407,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 352, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -18265,7 +18497,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 355, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -18328,7 +18560,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 356, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -18403,7 +18635,7 @@ "x-appwrite": { "method": "list", "group": null, - "weight": 314, + "weight": 316, "cookies": false, "type": "", "deprecated": false, @@ -18477,7 +18709,7 @@ "x-appwrite": { "method": "createAppwriteMigration", "group": null, - "weight": 309, + "weight": 311, "cookies": false, "type": "", "deprecated": false, @@ -18565,7 +18797,7 @@ "x-appwrite": { "method": "getAppwriteReport", "group": null, - "weight": 316, + "weight": 318, "cookies": false, "type": "", "deprecated": false, @@ -18658,7 +18890,7 @@ "x-appwrite": { "method": "createCsvMigration", "group": null, - "weight": 313, + "weight": 315, "cookies": false, "type": "", "deprecated": false, @@ -18737,7 +18969,7 @@ "x-appwrite": { "method": "createFirebaseMigration", "group": null, - "weight": 310, + "weight": 312, "cookies": false, "type": "", "deprecated": false, @@ -18813,7 +19045,7 @@ "x-appwrite": { "method": "getFirebaseReport", "group": null, - "weight": 317, + "weight": 319, "cookies": false, "type": "", "deprecated": false, @@ -18885,7 +19117,7 @@ "x-appwrite": { "method": "createNHostMigration", "group": null, - "weight": 312, + "weight": 314, "cookies": false, "type": "", "deprecated": false, @@ -18996,7 +19228,7 @@ "x-appwrite": { "method": "getNHostReport", "group": null, - "weight": 319, + "weight": 321, "cookies": false, "type": "", "deprecated": false, @@ -19129,7 +19361,7 @@ "x-appwrite": { "method": "createSupabaseMigration", "group": null, - "weight": 311, + "weight": 313, "cookies": false, "type": "", "deprecated": false, @@ -19234,7 +19466,7 @@ "x-appwrite": { "method": "getSupabaseReport", "group": null, - "weight": 318, + "weight": 320, "cookies": false, "type": "", "deprecated": false, @@ -19358,7 +19590,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 315, + "weight": 317, "cookies": false, "type": "", "deprecated": false, @@ -19416,7 +19648,7 @@ "x-appwrite": { "method": "retry", "group": null, - "weight": 320, + "weight": 322, "cookies": false, "type": "", "deprecated": false, @@ -19467,7 +19699,7 @@ "x-appwrite": { "method": "delete", "group": null, - "weight": 321, + "weight": 323, "cookies": false, "type": "", "deprecated": false, @@ -19527,7 +19759,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 200, + "weight": 202, "cookies": false, "type": "", "deprecated": false, @@ -19615,7 +19847,7 @@ "x-appwrite": { "method": "listVariables", "group": null, - "weight": 202, + "weight": 204, "cookies": false, "type": "", "deprecated": false, @@ -19661,7 +19893,7 @@ "x-appwrite": { "method": "createVariable", "group": null, - "weight": 201, + "weight": 203, "cookies": false, "type": "", "deprecated": false, @@ -19739,7 +19971,7 @@ "x-appwrite": { "method": "getVariable", "group": null, - "weight": 203, + "weight": 205, "cookies": false, "type": "", "deprecated": false, @@ -19797,7 +20029,7 @@ "x-appwrite": { "method": "updateVariable", "group": null, - "weight": 204, + "weight": 206, "cookies": false, "type": "", "deprecated": false, @@ -19877,7 +20109,7 @@ "x-appwrite": { "method": "deleteVariable", "group": null, - "weight": 205, + "weight": 207, "cookies": false, "type": "", "deprecated": false, @@ -19937,7 +20169,7 @@ "x-appwrite": { "method": "list", "group": "projects", - "weight": 155, + "weight": 157, "cookies": false, "type": "", "deprecated": false, @@ -20009,7 +20241,7 @@ "x-appwrite": { "method": "create", "group": "projects", - "weight": 154, + "weight": 156, "cookies": false, "type": "", "deprecated": false, @@ -20143,7 +20375,7 @@ "x-appwrite": { "method": "get", "group": "projects", - "weight": 156, + "weight": 158, "cookies": false, "type": "", "deprecated": false, @@ -20201,7 +20433,7 @@ "x-appwrite": { "method": "update", "group": "projects", - "weight": 157, + "weight": 159, "cookies": false, "type": "", "deprecated": false, @@ -20316,7 +20548,7 @@ "x-appwrite": { "method": "delete", "group": "projects", - "weight": 174, + "weight": 176, "cookies": false, "type": "", "deprecated": false, @@ -20376,7 +20608,7 @@ "x-appwrite": { "method": "updateApiStatus", "group": "projects", - "weight": 161, + "weight": 163, "cookies": false, "type": "", "deprecated": false, @@ -20468,7 +20700,7 @@ "x-appwrite": { "method": "updateApiStatusAll", "group": "projects", - "weight": 162, + "weight": 164, "cookies": false, "type": "", "deprecated": false, @@ -20547,7 +20779,7 @@ "x-appwrite": { "method": "updateAuthDuration", "group": "auth", - "weight": 167, + "weight": 169, "cookies": false, "type": "", "deprecated": false, @@ -20626,7 +20858,7 @@ "x-appwrite": { "method": "updateAuthLimit", "group": "auth", - "weight": 166, + "weight": 168, "cookies": false, "type": "", "deprecated": false, @@ -20705,7 +20937,7 @@ "x-appwrite": { "method": "updateAuthSessionsLimit", "group": "auth", - "weight": 172, + "weight": 174, "cookies": false, "type": "", "deprecated": false, @@ -20784,7 +21016,7 @@ "x-appwrite": { "method": "updateMembershipsPrivacy", "group": "auth", - "weight": 165, + "weight": 167, "cookies": false, "type": "", "deprecated": false, @@ -20875,7 +21107,7 @@ "x-appwrite": { "method": "updateMockNumbers", "group": "auth", - "weight": 173, + "weight": 175, "cookies": false, "type": "", "deprecated": false, @@ -20957,7 +21189,7 @@ "x-appwrite": { "method": "updateAuthPasswordDictionary", "group": "auth", - "weight": 170, + "weight": 172, "cookies": false, "type": "", "deprecated": false, @@ -21036,7 +21268,7 @@ "x-appwrite": { "method": "updateAuthPasswordHistory", "group": "auth", - "weight": 169, + "weight": 171, "cookies": false, "type": "", "deprecated": false, @@ -21115,7 +21347,7 @@ "x-appwrite": { "method": "updatePersonalDataCheck", "group": "auth", - "weight": 171, + "weight": 173, "cookies": false, "type": "", "deprecated": false, @@ -21194,7 +21426,7 @@ "x-appwrite": { "method": "updateSessionAlerts", "group": "auth", - "weight": 164, + "weight": 166, "cookies": false, "type": "", "deprecated": false, @@ -21273,7 +21505,7 @@ "x-appwrite": { "method": "updateAuthStatus", "group": "auth", - "weight": 168, + "weight": 170, "cookies": false, "type": "", "deprecated": false, @@ -21373,7 +21605,7 @@ "x-appwrite": { "method": "listDevKeys", "group": "devKeys", - "weight": 371, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -21441,7 +21673,7 @@ "x-appwrite": { "method": "createDevKey", "group": "devKeys", - "weight": 368, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -21526,7 +21758,7 @@ "x-appwrite": { "method": "getDevKey", "group": "devKeys", - "weight": 370, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -21594,7 +21826,7 @@ "x-appwrite": { "method": "updateDevKey", "group": "devKeys", - "weight": 369, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -21680,7 +21912,7 @@ "x-appwrite": { "method": "deleteDevKey", "group": "devKeys", - "weight": 372, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -21750,7 +21982,7 @@ "x-appwrite": { "method": "createJWT", "group": "auth", - "weight": 186, + "weight": 188, "cookies": false, "type": "", "deprecated": false, @@ -21837,7 +22069,7 @@ "x-appwrite": { "method": "listKeys", "group": "keys", - "weight": 182, + "weight": 184, "cookies": false, "type": "", "deprecated": false, @@ -21895,7 +22127,7 @@ "x-appwrite": { "method": "createKey", "group": "keys", - "weight": 181, + "weight": 183, "cookies": false, "type": "", "deprecated": false, @@ -21988,7 +22220,7 @@ "x-appwrite": { "method": "getKey", "group": "keys", - "weight": 183, + "weight": 185, "cookies": false, "type": "", "deprecated": false, @@ -22056,7 +22288,7 @@ "x-appwrite": { "method": "updateKey", "group": "keys", - "weight": 184, + "weight": 186, "cookies": false, "type": "", "deprecated": false, @@ -22150,7 +22382,7 @@ "x-appwrite": { "method": "deleteKey", "group": "keys", - "weight": 185, + "weight": 187, "cookies": false, "type": "", "deprecated": false, @@ -22220,7 +22452,7 @@ "x-appwrite": { "method": "updateOAuth2", "group": "auth", - "weight": 163, + "weight": 165, "cookies": false, "type": "", "deprecated": false, @@ -22358,7 +22590,7 @@ "x-appwrite": { "method": "listPlatforms", "group": "platforms", - "weight": 188, + "weight": 190, "cookies": false, "type": "", "deprecated": false, @@ -22416,7 +22648,7 @@ "x-appwrite": { "method": "createPlatform", "group": "platforms", - "weight": 187, + "weight": 189, "cookies": false, "type": "", "deprecated": false, @@ -22535,7 +22767,7 @@ "x-appwrite": { "method": "getPlatform", "group": "platforms", - "weight": 189, + "weight": 191, "cookies": false, "type": "", "deprecated": false, @@ -22603,7 +22835,7 @@ "x-appwrite": { "method": "updatePlatform", "group": "platforms", - "weight": 190, + "weight": 192, "cookies": false, "type": "", "deprecated": false, @@ -22698,7 +22930,7 @@ "x-appwrite": { "method": "deletePlatform", "group": "platforms", - "weight": 191, + "weight": 193, "cookies": false, "type": "", "deprecated": false, @@ -22768,7 +23000,7 @@ "x-appwrite": { "method": "updateServiceStatus", "group": "projects", - "weight": 159, + "weight": 161, "cookies": false, "type": "", "deprecated": false, @@ -22869,7 +23101,7 @@ "x-appwrite": { "method": "updateServiceStatusAll", "group": "projects", - "weight": 160, + "weight": 162, "cookies": false, "type": "", "deprecated": false, @@ -22948,7 +23180,7 @@ "x-appwrite": { "method": "updateSmtp", "group": "templates", - "weight": 192, + "weight": 194, "cookies": false, "type": "", "deprecated": false, @@ -23066,7 +23298,7 @@ "x-appwrite": { "method": "createSmtpTest", "group": "templates", - "weight": 193, + "weight": 195, "cookies": false, "type": "", "deprecated": false, @@ -23197,7 +23429,7 @@ "x-appwrite": { "method": "updateTeam", "group": "projects", - "weight": 158, + "weight": 160, "cookies": false, "type": "", "deprecated": false, @@ -23276,7 +23508,7 @@ "x-appwrite": { "method": "getEmailTemplate", "group": "templates", - "weight": 195, + "weight": 197, "cookies": false, "type": "", "deprecated": false, @@ -23500,7 +23732,7 @@ "x-appwrite": { "method": "updateEmailTemplate", "group": "templates", - "weight": 197, + "weight": 199, "cookies": false, "type": "", "deprecated": false, @@ -23764,7 +23996,7 @@ "x-appwrite": { "method": "deleteEmailTemplate", "group": "templates", - "weight": 199, + "weight": 201, "cookies": false, "type": "", "deprecated": false, @@ -23990,7 +24222,7 @@ "x-appwrite": { "method": "getSmsTemplate", "group": "templates", - "weight": 194, + "weight": 196, "cookies": false, "type": "", "deprecated": false, @@ -24211,7 +24443,7 @@ "x-appwrite": { "method": "updateSmsTemplate", "group": "templates", - "weight": 196, + "weight": 198, "cookies": false, "type": "", "deprecated": false, @@ -24451,7 +24683,7 @@ "x-appwrite": { "method": "deleteSmsTemplate", "group": "templates", - "weight": 198, + "weight": 200, "cookies": false, "type": "", "deprecated": false, @@ -24674,7 +24906,7 @@ "x-appwrite": { "method": "listWebhooks", "group": "webhooks", - "weight": 176, + "weight": 178, "cookies": false, "type": "", "deprecated": false, @@ -24732,7 +24964,7 @@ "x-appwrite": { "method": "createWebhook", "group": "webhooks", - "weight": 175, + "weight": 177, "cookies": false, "type": "", "deprecated": false, @@ -24847,7 +25079,7 @@ "x-appwrite": { "method": "getWebhook", "group": "webhooks", - "weight": 177, + "weight": 179, "cookies": false, "type": "", "deprecated": false, @@ -24915,7 +25147,7 @@ "x-appwrite": { "method": "updateWebhook", "group": "webhooks", - "weight": 178, + "weight": 180, "cookies": false, "type": "", "deprecated": false, @@ -25031,7 +25263,7 @@ "x-appwrite": { "method": "deleteWebhook", "group": "webhooks", - "weight": 180, + "weight": 182, "cookies": false, "type": "", "deprecated": false, @@ -25101,7 +25333,7 @@ "x-appwrite": { "method": "updateWebhookSignature", "group": "webhooks", - "weight": 179, + "weight": 181, "cookies": false, "type": "", "deprecated": false, @@ -25171,7 +25403,7 @@ "x-appwrite": { "method": "listRules", "group": null, - "weight": 292, + "weight": 294, "cookies": false, "type": "", "deprecated": false, @@ -25245,7 +25477,7 @@ "x-appwrite": { "method": "createAPIRule", "group": null, - "weight": 433, + "weight": 435, "cookies": false, "type": "", "deprecated": false, @@ -25312,7 +25544,7 @@ "x-appwrite": { "method": "createFunctionRule", "group": null, - "weight": 435, + "weight": 437, "cookies": false, "type": "", "deprecated": false, @@ -25390,7 +25622,7 @@ "x-appwrite": { "method": "createRedirectRule", "group": null, - "weight": 436, + "weight": 438, "cookies": false, "type": "", "deprecated": false, @@ -25503,7 +25735,7 @@ "x-appwrite": { "method": "createSiteRule", "group": null, - "weight": 434, + "weight": 436, "cookies": false, "type": "", "deprecated": false, @@ -25581,7 +25813,7 @@ "x-appwrite": { "method": "getRule", "group": null, - "weight": 293, + "weight": 295, "cookies": false, "type": "", "deprecated": false, @@ -25632,7 +25864,7 @@ "x-appwrite": { "method": "deleteRule", "group": null, - "weight": 294, + "weight": 296, "cookies": false, "type": "", "deprecated": false, @@ -25692,7 +25924,7 @@ "x-appwrite": { "method": "updateRuleVerification", "group": null, - "weight": 295, + "weight": 297, "cookies": false, "type": "", "deprecated": false, @@ -25752,7 +25984,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 405, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -25822,7 +26054,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 403, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -25957,6 +26189,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -25982,7 +26215,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -26069,7 +26303,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 408, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -26118,7 +26352,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 431, + "weight": 433, "cookies": false, "type": "", "deprecated": false, @@ -26168,7 +26402,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 427, + "weight": 429, "cookies": false, "type": "", "deprecated": false, @@ -26268,7 +26502,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 428, + "weight": 430, "cookies": false, "type": "", "deprecated": false, @@ -26328,7 +26562,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 429, + "weight": 431, "cookies": false, "type": "", "deprecated": false, @@ -26400,7 +26634,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 404, + "weight": 406, "cookies": false, "type": "", "deprecated": false, @@ -26459,7 +26693,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 406, + "weight": 408, "cookies": false, "type": "", "deprecated": false, @@ -26601,6 +26835,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -26626,7 +26861,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -26702,7 +26938,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 407, + "weight": 409, "cookies": false, "type": "", "deprecated": false, @@ -26763,7 +26999,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 414, + "weight": 416, "cookies": false, "type": "", "deprecated": false, @@ -26843,7 +27079,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 413, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -26926,7 +27162,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 409, + "weight": 411, "cookies": false, "type": "upload", "deprecated": false, @@ -27027,7 +27263,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 417, + "weight": 419, "cookies": false, "type": "", "deprecated": false, @@ -27107,7 +27343,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 410, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -27210,7 +27446,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 411, + "weight": 413, "cookies": false, "type": "", "deprecated": false, @@ -27308,7 +27544,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 412, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -27370,7 +27606,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 415, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -27434,7 +27670,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 416, + "weight": 418, "cookies": false, "type": "location", "deprecated": false, @@ -27524,7 +27760,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 418, + "weight": 420, "cookies": false, "type": "", "deprecated": false, @@ -27595,7 +27831,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 420, + "weight": 422, "cookies": false, "type": "", "deprecated": false, @@ -27666,7 +27902,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 419, + "weight": 421, "cookies": false, "type": "", "deprecated": false, @@ -27728,7 +27964,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 421, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -27799,7 +28035,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 430, + "weight": 432, "cookies": false, "type": "", "deprecated": false, @@ -27881,7 +28117,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 424, + "weight": 426, "cookies": false, "type": "", "deprecated": false, @@ -27940,7 +28176,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 422, + "weight": 424, "cookies": false, "type": "", "deprecated": false, @@ -28031,7 +28267,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 423, + "weight": 425, "cookies": false, "type": "", "deprecated": false, @@ -28100,7 +28336,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 425, + "weight": 427, "cookies": false, "type": "", "deprecated": false, @@ -28191,7 +28427,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 426, + "weight": 428, "cookies": false, "type": "", "deprecated": false, @@ -28262,7 +28498,7 @@ "x-appwrite": { "method": "listBuckets", "group": "buckets", - "weight": 207, + "weight": 209, "cookies": false, "type": "", "deprecated": false, @@ -28335,7 +28571,7 @@ "x-appwrite": { "method": "createBucket", "group": "buckets", - "weight": 206, + "weight": 208, "cookies": false, "type": "", "deprecated": false, @@ -28462,7 +28698,7 @@ "x-appwrite": { "method": "getBucket", "group": "buckets", - "weight": 208, + "weight": 210, "cookies": false, "type": "", "deprecated": false, @@ -28521,7 +28757,7 @@ "x-appwrite": { "method": "updateBucket", "group": "buckets", - "weight": 209, + "weight": 211, "cookies": false, "type": "", "deprecated": false, @@ -28645,7 +28881,7 @@ "x-appwrite": { "method": "deleteBucket", "group": "buckets", - "weight": 210, + "weight": 212, "cookies": false, "type": "", "deprecated": false, @@ -28706,7 +28942,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 212, + "weight": 214, "cookies": false, "type": "", "deprecated": false, @@ -28792,7 +29028,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 211, + "weight": 213, "cookies": false, "type": "upload", "deprecated": false, @@ -28890,7 +29126,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 213, + "weight": 215, "cookies": false, "type": "", "deprecated": false, @@ -28962,7 +29198,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 218, + "weight": 220, "cookies": false, "type": "", "deprecated": false, @@ -29051,7 +29287,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 219, + "weight": 221, "cookies": false, "type": "", "deprecated": false, @@ -29118,7 +29354,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 215, + "weight": 217, "cookies": false, "type": "location", "deprecated": false, @@ -29196,7 +29432,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 214, + "weight": 216, "cookies": false, "type": "location", "deprecated": false, @@ -29385,7 +29621,8 @@ "png", "webp", "heic", - "avif" + "avif", + "gif" ], "x-enum-name": "ImageFormat", "x-enum-keys": [], @@ -29423,7 +29660,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 216, + "weight": 218, "cookies": false, "type": "location", "deprecated": false, @@ -29508,7 +29745,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 220, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -29580,7 +29817,7 @@ "x-appwrite": { "method": "getBucketUsage", "group": null, - "weight": 221, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -29662,7 +29899,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 223, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -29738,7 +29975,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 222, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -29823,7 +30060,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 224, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -29885,7 +30122,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 226, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -29959,7 +30196,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 228, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -30023,7 +30260,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 235, + "weight": 237, "cookies": false, "type": "", "deprecated": false, @@ -30096,7 +30333,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 230, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -30182,7 +30419,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 229, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -30293,7 +30530,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 231, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -30365,7 +30602,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 232, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -30452,7 +30689,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 234, + "weight": 236, "cookies": false, "type": "", "deprecated": false, @@ -30526,7 +30763,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 233, + "weight": 235, "cookies": false, "type": "", "deprecated": false, @@ -30623,7 +30860,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 225, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -30683,7 +30920,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 227, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -30764,7 +31001,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 439, + "weight": 441, "cookies": false, "type": "", "deprecated": false, @@ -30844,7 +31081,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 437, + "weight": 439, "cookies": false, "type": "", "deprecated": false, @@ -30933,7 +31170,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 438, + "weight": 440, "cookies": false, "type": "", "deprecated": false, @@ -30993,7 +31230,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 440, + "weight": 442, "cookies": false, "type": "", "deprecated": false, @@ -31063,7 +31300,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 441, + "weight": 443, "cookies": false, "type": "", "deprecated": false, @@ -31125,7 +31362,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 245, + "weight": 247, "cookies": false, "type": "", "deprecated": false, @@ -31198,7 +31435,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 236, + "weight": 238, "cookies": false, "type": "", "deprecated": false, @@ -31286,7 +31523,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 239, + "weight": 241, "cookies": false, "type": "", "deprecated": false, @@ -31371,7 +31608,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 237, + "weight": 239, "cookies": false, "type": "", "deprecated": false, @@ -31456,7 +31693,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 253, + "weight": 255, "cookies": false, "type": "", "deprecated": false, @@ -31524,7 +31761,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 276, + "weight": 278, "cookies": false, "type": "", "deprecated": false, @@ -31585,7 +31822,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 238, + "weight": 240, "cookies": false, "type": "", "deprecated": false, @@ -31670,7 +31907,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 241, + "weight": 243, "cookies": false, "type": "", "deprecated": false, @@ -31755,7 +31992,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 242, + "weight": 244, "cookies": false, "type": "", "deprecated": false, @@ -31870,7 +32107,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 243, + "weight": 245, "cookies": false, "type": "", "deprecated": false, @@ -31973,7 +32210,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 240, + "weight": 242, "cookies": false, "type": "", "deprecated": false, @@ -32078,7 +32315,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 278, + "weight": 280, "cookies": false, "type": "", "deprecated": false, @@ -32150,7 +32387,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 246, + "weight": 248, "cookies": false, "type": "", "deprecated": false, @@ -32202,7 +32439,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 274, + "weight": 276, "cookies": false, "type": "", "deprecated": false, @@ -32263,7 +32500,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 259, + "weight": 261, "cookies": false, "type": "", "deprecated": false, @@ -32343,7 +32580,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 277, + "weight": 279, "cookies": false, "type": "", "deprecated": false, @@ -32425,7 +32662,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 255, + "weight": 257, "cookies": false, "type": "", "deprecated": false, @@ -32508,7 +32745,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 251, + "weight": 253, "cookies": false, "type": "", "deprecated": false, @@ -32582,7 +32819,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 250, + "weight": 252, "cookies": false, "type": "", "deprecated": false, @@ -32667,7 +32904,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 264, + "weight": 266, "cookies": false, "type": "", "deprecated": false, @@ -32740,7 +32977,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 269, + "weight": 271, "cookies": false, "type": "", "deprecated": false, @@ -32816,7 +33053,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 265, + "weight": 267, "cookies": false, "type": "", "deprecated": false, @@ -32877,7 +33114,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 266, + "weight": 268, "cookies": false, "type": "", "deprecated": false, @@ -32936,7 +33173,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 268, + "weight": 270, "cookies": false, "type": "", "deprecated": false, @@ -32995,7 +33232,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 267, + "weight": 269, "cookies": false, "type": "", "deprecated": false, @@ -33056,7 +33293,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 257, + "weight": 259, "cookies": false, "type": "", "deprecated": false, @@ -33136,7 +33373,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 258, + "weight": 260, "cookies": false, "type": "", "deprecated": false, @@ -33216,7 +33453,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 260, + "weight": 262, "cookies": false, "type": "", "deprecated": false, @@ -33296,7 +33533,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 247, + "weight": 249, "cookies": false, "type": "", "deprecated": false, @@ -33355,7 +33592,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 262, + "weight": 264, "cookies": false, "type": "", "deprecated": false, @@ -33435,7 +33672,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 249, + "weight": 251, "cookies": false, "type": "", "deprecated": false, @@ -33494,7 +33731,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 270, + "weight": 272, "cookies": false, "type": "", "deprecated": false, @@ -33546,7 +33783,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 273, + "weight": 275, "cookies": false, "type": "", "deprecated": false, @@ -33600,7 +33837,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 272, + "weight": 274, "cookies": false, "type": "", "deprecated": false, @@ -33671,7 +33908,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 254, + "weight": 256, "cookies": false, "type": "", "deprecated": false, @@ -33751,7 +33988,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 252, + "weight": 254, "cookies": false, "type": "", "deprecated": false, @@ -33789,7 +34026,7 @@ }, { "name": "queries", - "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, email, phone, status, passwordUpdate, registration, emailVerification, phoneVerification, labels", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, providerId, identifier, providerType", "required": false, "schema": { "type": "array", @@ -33824,7 +34061,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 244, + "weight": 246, "cookies": false, "type": "", "deprecated": false, @@ -33934,7 +34171,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 248, + "weight": 250, "cookies": false, "type": "", "deprecated": false, @@ -34004,7 +34241,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 263, + "weight": 265, "cookies": false, "type": "", "deprecated": false, @@ -34093,7 +34330,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 275, + "weight": 277, "cookies": false, "type": "", "deprecated": false, @@ -34165,7 +34402,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 271, + "weight": 273, "cookies": false, "type": "", "deprecated": false, @@ -34247,7 +34484,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 261, + "weight": 263, "cookies": false, "type": "", "deprecated": false, @@ -34327,7 +34564,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 256, + "weight": 258, "cookies": false, "type": "", "deprecated": false, @@ -34407,7 +34644,7 @@ "x-appwrite": { "method": "createRepositoryDetection", "group": "repositories", - "weight": 282, + "weight": 284, "cookies": false, "type": "", "deprecated": false, @@ -34503,7 +34740,7 @@ "x-appwrite": { "method": "listRepositories", "group": "repositories", - "weight": 283, + "weight": 285, "cookies": false, "type": "", "deprecated": false, @@ -34588,7 +34825,7 @@ "x-appwrite": { "method": "createRepository", "group": "repositories", - "weight": 284, + "weight": 286, "cookies": false, "type": "", "deprecated": false, @@ -34673,7 +34910,7 @@ "x-appwrite": { "method": "getRepository", "group": "repositories", - "weight": 285, + "weight": 287, "cookies": false, "type": "", "deprecated": false, @@ -34743,7 +34980,7 @@ "x-appwrite": { "method": "listRepositoryBranches", "group": "repositories", - "weight": 286, + "weight": 288, "cookies": false, "type": "", "deprecated": false, @@ -34813,7 +35050,7 @@ "x-appwrite": { "method": "getRepositoryContents", "group": "repositories", - "weight": 281, + "weight": 283, "cookies": false, "type": "", "deprecated": false, @@ -34887,7 +35124,7 @@ "x-appwrite": { "method": "updateExternalDeployments", "group": "repositories", - "weight": 291, + "weight": 293, "cookies": false, "type": "", "deprecated": false, @@ -34976,7 +35213,7 @@ "x-appwrite": { "method": "listInstallations", "group": "installations", - "weight": 288, + "weight": 290, "cookies": false, "type": "", "deprecated": false, @@ -35050,7 +35287,7 @@ "x-appwrite": { "method": "getInstallation", "group": "installations", - "weight": 289, + "weight": 291, "cookies": false, "type": "", "deprecated": false, @@ -35101,7 +35338,7 @@ "x-appwrite": { "method": "deleteInstallation", "group": "installations", - "weight": 290, + "weight": 292, "cookies": false, "type": "", "deprecated": false, @@ -36611,6 +36848,12 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "default", "nullable": true + }, + "encrypt": { + "type": "boolean", + "description": "Defines whether this attribute is encrypted or not.", + "x-example": false, + "nullable": true } }, "required": [ @@ -37362,6 +37605,12 @@ "description": "Document ID.", "x-example": "5e5ea5c16897e" }, + "$sequence": { + "type": "integer", + "description": "Document automatically incrementing ID.", + "x-example": 1, + "format": "int32" + }, "$collectionId": { "type": "string", "description": "Collection ID.", @@ -37396,6 +37645,7 @@ "additionalProperties": true, "required": [ "$id", + "$sequence", "$collectionId", "$databaseId", "$createdAt", diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 1ae9328864..871f5a1e57 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -7650,7 +7650,7 @@ "x-appwrite": { "method": "upsertDocuments", "group": "documents", - "weight": 116, + "weight": 118, "cookies": false, "type": "", "deprecated": false, @@ -7742,7 +7742,7 @@ "x-appwrite": { "method": "updateDocuments", "group": "documents", - "weight": 115, + "weight": 117, "cookies": false, "type": "", "deprecated": false, @@ -7836,7 +7836,7 @@ "x-appwrite": { "method": "deleteDocuments", "group": "documents", - "weight": 118, + "weight": 120, "cookies": false, "type": "", "deprecated": false, @@ -8236,7 +8236,7 @@ "x-appwrite": { "method": "deleteDocument", "group": "documents", - "weight": 117, + "weight": 119, "cookies": false, "type": "", "deprecated": false, @@ -8299,6 +8299,238 @@ ] } }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/decrement": { + "patch": { + "summary": "Decrement document attribute", + "operationId": "databasesDecrementDocumentAttribute", + "tags": [ + "databases" + ], + "description": "Decrement a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "decrementDocumentAttribute", + "group": "documents", + "weight": 116, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/decrement-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/decrement-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DOCUMENT_ID>" + }, + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to decrement the attribute by. The value must be a number.", + "x-example": null + }, + "min": { + "type": "mixed", + "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", + "x-example": null + } + } + } + } + } + } + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/increment": { + "patch": { + "summary": "Increment document attribute", + "operationId": "databasesIncrementDocumentAttribute", + "tags": [ + "databases" + ], + "description": "Increment a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "content": { + "application\/json": { + "schema": { + "$ref": "#\/components\/schemas\/document" + } + } + } + } + }, + "x-appwrite": { + "method": "incrementDocumentAttribute", + "group": "documents", + "weight": 115, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/increment-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/increment-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DATABASE_ID>" + }, + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<COLLECTION_ID>" + }, + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "schema": { + "type": "string", + "x-example": "<DOCUMENT_ID>" + }, + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "schema": { + "type": "string" + }, + "in": "path" + } + ], + "requestBody": { + "content": { + "application\/json": { + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to increment the attribute by. The value must be a number.", + "x-example": null + }, + "max": { + "type": "mixed", + "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", + "x-example": null + } + } + } + } + } + } + } + }, "\/databases\/{databaseId}\/collections\/{collectionId}\/indexes": { "get": { "summary": "List indexes", @@ -8687,7 +8919,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 376, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -8761,7 +8993,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 373, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -8844,6 +9076,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -8869,7 +9102,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -8993,7 +9227,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 378, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -9043,7 +9277,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 379, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -9094,7 +9328,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 374, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -9154,7 +9388,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 375, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -9244,6 +9478,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -9269,7 +9504,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -9383,7 +9619,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 377, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -9445,7 +9681,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 382, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -9526,7 +9762,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 383, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -9610,7 +9846,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 380, + "weight": 382, "cookies": false, "type": "upload", "deprecated": false, @@ -9707,7 +9943,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 388, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -9793,7 +10029,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 385, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -9897,7 +10133,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 386, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -9995,7 +10231,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 381, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -10058,7 +10294,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 384, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -10123,7 +10359,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 387, + "weight": 389, "cookies": false, "type": "location", "deprecated": false, @@ -10214,7 +10450,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 389, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -10286,7 +10522,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 392, + "weight": 394, "cookies": false, "type": "", "deprecated": false, @@ -10363,7 +10599,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 390, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -10480,7 +10716,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 391, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -10547,7 +10783,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 393, + "weight": 395, "cookies": false, "type": "", "deprecated": false, @@ -10619,7 +10855,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 398, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -10679,7 +10915,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 396, + "weight": 398, "cookies": false, "type": "", "deprecated": false, @@ -10771,7 +11007,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 397, + "weight": 399, "cookies": false, "type": "", "deprecated": false, @@ -10841,7 +11077,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 399, + "weight": 401, "cookies": false, "type": "", "deprecated": false, @@ -10933,7 +11169,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 400, + "weight": 402, "cookies": false, "type": "", "deprecated": false, @@ -11005,7 +11241,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 306, + "weight": 308, "cookies": false, "type": "graphql", "deprecated": false, @@ -11059,7 +11295,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 305, + "weight": 307, "cookies": false, "type": "graphql", "deprecated": false, @@ -11113,7 +11349,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 130, + "weight": 132, "cookies": false, "type": "", "deprecated": false, @@ -11163,7 +11399,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 151, + "weight": 153, "cookies": false, "type": "", "deprecated": false, @@ -11213,7 +11449,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 133, + "weight": 135, "cookies": false, "type": "", "deprecated": false, @@ -11263,7 +11499,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 138, + "weight": 140, "cookies": false, "type": "", "deprecated": false, @@ -11324,7 +11560,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 132, + "weight": 134, "cookies": false, "type": "", "deprecated": false, @@ -11374,7 +11610,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 134, + "weight": 136, "cookies": false, "type": "", "deprecated": false, @@ -11424,7 +11660,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 140, + "weight": 142, "cookies": false, "type": "", "deprecated": false, @@ -11487,7 +11723,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 139, + "weight": 141, "cookies": false, "type": "", "deprecated": false, @@ -11550,7 +11786,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 141, + "weight": 143, "cookies": false, "type": "", "deprecated": false, @@ -11624,7 +11860,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 142, + "weight": 144, "cookies": false, "type": "", "deprecated": false, @@ -11687,7 +11923,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 152, + "weight": 154, "cookies": false, "type": "", "deprecated": false, @@ -11776,7 +12012,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 146, + "weight": 148, "cookies": false, "type": "", "deprecated": false, @@ -11839,7 +12075,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 137, + "weight": 139, "cookies": false, "type": "", "deprecated": false, @@ -11902,7 +12138,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 143, + "weight": 145, "cookies": false, "type": "", "deprecated": false, @@ -11965,7 +12201,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 144, + "weight": 146, "cookies": false, "type": "", "deprecated": false, @@ -12028,7 +12264,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 145, + "weight": 147, "cookies": false, "type": "", "deprecated": false, @@ -12091,7 +12327,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 147, + "weight": 149, "cookies": false, "type": "", "deprecated": false, @@ -12154,7 +12390,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 148, + "weight": 150, "cookies": false, "type": "", "deprecated": false, @@ -12217,7 +12453,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 136, + "weight": 138, "cookies": false, "type": "", "deprecated": false, @@ -12280,7 +12516,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 150, + "weight": 152, "cookies": false, "type": "", "deprecated": false, @@ -12330,7 +12566,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 149, + "weight": 151, "cookies": false, "type": "", "deprecated": false, @@ -12380,7 +12616,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 135, + "weight": 137, "cookies": false, "type": "", "deprecated": false, @@ -12430,7 +12666,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 122, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -12484,7 +12720,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 123, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -12538,7 +12774,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 127, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -12592,7 +12828,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 124, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -12646,7 +12882,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 125, + "weight": 127, "cookies": false, "type": "", "deprecated": false, @@ -12700,7 +12936,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 126, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -12754,7 +12990,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 128, + "weight": 130, "cookies": false, "type": "", "deprecated": false, @@ -12808,7 +13044,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 129, + "weight": 131, "cookies": false, "type": "", "deprecated": false, @@ -12862,7 +13098,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 360, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -12939,7 +13175,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 357, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -13084,7 +13320,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 364, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -13231,7 +13467,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 359, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -13406,7 +13642,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 366, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -13585,7 +13821,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 358, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -13695,7 +13931,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 365, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -13808,7 +14044,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 363, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -13862,7 +14098,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 367, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -13925,7 +14161,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 361, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -14001,7 +14237,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 362, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -14077,7 +14313,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 332, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -14154,7 +14390,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 331, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -14260,7 +14496,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 344, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -14369,7 +14605,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 330, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -14455,7 +14691,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 343, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -14544,7 +14780,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 322, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -14660,7 +14896,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 335, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -14779,7 +15015,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 325, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -14875,7 +15111,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 338, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -14974,7 +15210,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 323, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -15080,7 +15316,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 336, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -15189,7 +15425,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 324, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -15333,7 +15569,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 337, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -15479,7 +15715,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 326, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -15575,7 +15811,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 339, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -15674,7 +15910,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 327, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -15770,7 +16006,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 340, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -15869,7 +16105,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 328, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -15965,7 +16201,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 341, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -16064,7 +16300,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 329, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -16160,7 +16396,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 342, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -16259,7 +16495,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 334, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -16313,7 +16549,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 345, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -16376,7 +16612,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 333, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -16452,7 +16688,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 354, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -16528,7 +16764,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 347, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -16603,7 +16839,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 346, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -16687,7 +16923,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 349, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -16748,7 +16984,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 350, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -16826,7 +17062,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 351, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -16889,7 +17125,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 348, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -16965,7 +17201,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 353, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -17050,7 +17286,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 352, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -17142,7 +17378,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 355, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -17206,7 +17442,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 356, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -17283,7 +17519,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 405, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -17354,7 +17590,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 403, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -17490,6 +17726,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -17515,7 +17752,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -17602,7 +17840,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 408, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -17652,7 +17890,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 431, + "weight": 433, "cookies": false, "type": "", "deprecated": false, @@ -17703,7 +17941,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 404, + "weight": 406, "cookies": false, "type": "", "deprecated": false, @@ -17763,7 +18001,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 406, + "weight": 408, "cookies": false, "type": "", "deprecated": false, @@ -17906,6 +18144,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -17931,7 +18170,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -18007,7 +18247,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 407, + "weight": 409, "cookies": false, "type": "", "deprecated": false, @@ -18069,7 +18309,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 414, + "weight": 416, "cookies": false, "type": "", "deprecated": false, @@ -18150,7 +18390,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 413, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -18234,7 +18474,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 409, + "weight": 411, "cookies": false, "type": "upload", "deprecated": false, @@ -18336,7 +18576,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 417, + "weight": 419, "cookies": false, "type": "", "deprecated": false, @@ -18417,7 +18657,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 410, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -18521,7 +18761,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 411, + "weight": 413, "cookies": false, "type": "", "deprecated": false, @@ -18620,7 +18860,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 412, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -18683,7 +18923,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 415, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -18748,7 +18988,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 416, + "weight": 418, "cookies": false, "type": "location", "deprecated": false, @@ -18839,7 +19079,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 418, + "weight": 420, "cookies": false, "type": "", "deprecated": false, @@ -18911,7 +19151,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 420, + "weight": 422, "cookies": false, "type": "", "deprecated": false, @@ -18983,7 +19223,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 419, + "weight": 421, "cookies": false, "type": "", "deprecated": false, @@ -19046,7 +19286,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 421, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -19118,7 +19358,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 424, + "weight": 426, "cookies": false, "type": "", "deprecated": false, @@ -19178,7 +19418,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 422, + "weight": 424, "cookies": false, "type": "", "deprecated": false, @@ -19270,7 +19510,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 423, + "weight": 425, "cookies": false, "type": "", "deprecated": false, @@ -19340,7 +19580,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 425, + "weight": 427, "cookies": false, "type": "", "deprecated": false, @@ -19432,7 +19672,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 426, + "weight": 428, "cookies": false, "type": "", "deprecated": false, @@ -19504,7 +19744,7 @@ "x-appwrite": { "method": "listBuckets", "group": "buckets", - "weight": 207, + "weight": 209, "cookies": false, "type": "", "deprecated": false, @@ -19578,7 +19818,7 @@ "x-appwrite": { "method": "createBucket", "group": "buckets", - "weight": 206, + "weight": 208, "cookies": false, "type": "", "deprecated": false, @@ -19706,7 +19946,7 @@ "x-appwrite": { "method": "getBucket", "group": "buckets", - "weight": 208, + "weight": 210, "cookies": false, "type": "", "deprecated": false, @@ -19766,7 +20006,7 @@ "x-appwrite": { "method": "updateBucket", "group": "buckets", - "weight": 209, + "weight": 211, "cookies": false, "type": "", "deprecated": false, @@ -19891,7 +20131,7 @@ "x-appwrite": { "method": "deleteBucket", "group": "buckets", - "weight": 210, + "weight": 212, "cookies": false, "type": "", "deprecated": false, @@ -19953,7 +20193,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 212, + "weight": 214, "cookies": false, "type": "", "deprecated": false, @@ -20041,7 +20281,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 211, + "weight": 213, "cookies": false, "type": "upload", "deprecated": false, @@ -20141,7 +20381,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 213, + "weight": 215, "cookies": false, "type": "", "deprecated": false, @@ -20215,7 +20455,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 218, + "weight": 220, "cookies": false, "type": "", "deprecated": false, @@ -20306,7 +20546,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 219, + "weight": 221, "cookies": false, "type": "", "deprecated": false, @@ -20375,7 +20615,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 215, + "weight": 217, "cookies": false, "type": "location", "deprecated": false, @@ -20455,7 +20695,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 214, + "weight": 216, "cookies": false, "type": "location", "deprecated": false, @@ -20646,7 +20886,8 @@ "png", "webp", "heic", - "avif" + "avif", + "gif" ], "x-enum-name": "ImageFormat", "x-enum-keys": [], @@ -20684,7 +20925,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 216, + "weight": 218, "cookies": false, "type": "location", "deprecated": false, @@ -20771,7 +21012,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 223, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -20849,7 +21090,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 222, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -20936,7 +21177,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 224, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -21000,7 +21241,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 226, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -21076,7 +21317,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 228, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -21142,7 +21383,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 230, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -21230,7 +21471,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 229, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -21343,7 +21584,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 231, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -21417,7 +21658,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 232, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -21506,7 +21747,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 234, + "weight": 236, "cookies": false, "type": "", "deprecated": false, @@ -21582,7 +21823,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 233, + "weight": 235, "cookies": false, "type": "", "deprecated": false, @@ -21681,7 +21922,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 225, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -21743,7 +21984,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 227, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -21826,7 +22067,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 439, + "weight": 441, "cookies": false, "type": "", "deprecated": false, @@ -21907,7 +22148,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 437, + "weight": 439, "cookies": false, "type": "", "deprecated": false, @@ -21997,7 +22238,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 438, + "weight": 440, "cookies": false, "type": "", "deprecated": false, @@ -22058,7 +22299,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 440, + "weight": 442, "cookies": false, "type": "", "deprecated": false, @@ -22129,7 +22370,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 441, + "weight": 443, "cookies": false, "type": "", "deprecated": false, @@ -22192,7 +22433,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 245, + "weight": 247, "cookies": false, "type": "", "deprecated": false, @@ -22266,7 +22507,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 236, + "weight": 238, "cookies": false, "type": "", "deprecated": false, @@ -22355,7 +22596,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 239, + "weight": 241, "cookies": false, "type": "", "deprecated": false, @@ -22441,7 +22682,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 237, + "weight": 239, "cookies": false, "type": "", "deprecated": false, @@ -22527,7 +22768,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 253, + "weight": 255, "cookies": false, "type": "", "deprecated": false, @@ -22596,7 +22837,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 276, + "weight": 278, "cookies": false, "type": "", "deprecated": false, @@ -22658,7 +22899,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 238, + "weight": 240, "cookies": false, "type": "", "deprecated": false, @@ -22744,7 +22985,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 241, + "weight": 243, "cookies": false, "type": "", "deprecated": false, @@ -22830,7 +23071,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 242, + "weight": 244, "cookies": false, "type": "", "deprecated": false, @@ -22946,7 +23187,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 243, + "weight": 245, "cookies": false, "type": "", "deprecated": false, @@ -23050,7 +23291,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 240, + "weight": 242, "cookies": false, "type": "", "deprecated": false, @@ -23156,7 +23397,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 246, + "weight": 248, "cookies": false, "type": "", "deprecated": false, @@ -23209,7 +23450,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 274, + "weight": 276, "cookies": false, "type": "", "deprecated": false, @@ -23271,7 +23512,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 259, + "weight": 261, "cookies": false, "type": "", "deprecated": false, @@ -23352,7 +23593,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 277, + "weight": 279, "cookies": false, "type": "", "deprecated": false, @@ -23435,7 +23676,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 255, + "weight": 257, "cookies": false, "type": "", "deprecated": false, @@ -23519,7 +23760,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 251, + "weight": 253, "cookies": false, "type": "", "deprecated": false, @@ -23594,7 +23835,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 250, + "weight": 252, "cookies": false, "type": "", "deprecated": false, @@ -23680,7 +23921,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 264, + "weight": 266, "cookies": false, "type": "", "deprecated": false, @@ -23754,7 +23995,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 269, + "weight": 271, "cookies": false, "type": "", "deprecated": false, @@ -23831,7 +24072,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 265, + "weight": 267, "cookies": false, "type": "", "deprecated": false, @@ -23893,7 +24134,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 266, + "weight": 268, "cookies": false, "type": "", "deprecated": false, @@ -23953,7 +24194,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 268, + "weight": 270, "cookies": false, "type": "", "deprecated": false, @@ -24013,7 +24254,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 267, + "weight": 269, "cookies": false, "type": "", "deprecated": false, @@ -24075,7 +24316,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 257, + "weight": 259, "cookies": false, "type": "", "deprecated": false, @@ -24156,7 +24397,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 258, + "weight": 260, "cookies": false, "type": "", "deprecated": false, @@ -24237,7 +24478,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 260, + "weight": 262, "cookies": false, "type": "", "deprecated": false, @@ -24318,7 +24559,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 247, + "weight": 249, "cookies": false, "type": "", "deprecated": false, @@ -24378,7 +24619,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 262, + "weight": 264, "cookies": false, "type": "", "deprecated": false, @@ -24459,7 +24700,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 249, + "weight": 251, "cookies": false, "type": "", "deprecated": false, @@ -24519,7 +24760,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 270, + "weight": 272, "cookies": false, "type": "", "deprecated": false, @@ -24572,7 +24813,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 273, + "weight": 275, "cookies": false, "type": "", "deprecated": false, @@ -24627,7 +24868,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 272, + "weight": 274, "cookies": false, "type": "", "deprecated": false, @@ -24699,7 +24940,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 254, + "weight": 256, "cookies": false, "type": "", "deprecated": false, @@ -24780,7 +25021,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 252, + "weight": 254, "cookies": false, "type": "", "deprecated": false, @@ -24819,7 +25060,7 @@ }, { "name": "queries", - "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, email, phone, status, passwordUpdate, registration, emailVerification, phoneVerification, labels", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, providerId, identifier, providerType", "required": false, "schema": { "type": "array", @@ -24854,7 +25095,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 244, + "weight": 246, "cookies": false, "type": "", "deprecated": false, @@ -24965,7 +25206,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 248, + "weight": 250, "cookies": false, "type": "", "deprecated": false, @@ -25036,7 +25277,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 263, + "weight": 265, "cookies": false, "type": "", "deprecated": false, @@ -25126,7 +25367,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 275, + "weight": 277, "cookies": false, "type": "", "deprecated": false, @@ -25199,7 +25440,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 271, + "weight": 273, "cookies": false, "type": "", "deprecated": false, @@ -25282,7 +25523,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 261, + "weight": 263, "cookies": false, "type": "", "deprecated": false, @@ -25363,7 +25604,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 256, + "weight": 258, "cookies": false, "type": "", "deprecated": false, @@ -26558,6 +26799,12 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "default", "nullable": true + }, + "encrypt": { + "type": "boolean", + "description": "Defines whether this attribute is encrypted or not.", + "x-example": false, + "nullable": true } }, "required": [ @@ -27309,6 +27556,12 @@ "description": "Document ID.", "x-example": "5e5ea5c16897e" }, + "$sequence": { + "type": "integer", + "description": "Document automatically incrementing ID.", + "x-example": 1, + "format": "int32" + }, "$collectionId": { "type": "string", "description": "Collection ID.", @@ -27343,6 +27596,7 @@ "additionalProperties": true, "required": [ "$id", + "$sequence", "$collectionId", "$databaseId", "$createdAt", diff --git a/app/config/specs/swagger2-1.8.x-client.json b/app/config/specs/swagger2-1.8.x-client.json new file mode 100644 index 0000000000..d5ff0f609c --- /dev/null +++ b/app/config/specs/swagger2-1.8.x-client.json @@ -0,0 +1,10171 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.7.4", + "title": "Appwrite", + "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", + "termsOfService": "https:\/\/appwrite.io\/policy\/terms", + "contact": { + "name": "Appwrite Team", + "url": "https:\/\/appwrite.io\/support", + "email": "team@appwrite.io" + }, + "license": { + "name": "BSD-3-Clause", + "url": "https:\/\/raw.githubusercontent.com\/appwrite\/appwrite\/master\/LICENSE" + } + }, + "host": "cloud.appwrite.io", + "x-host-docs": "<REGION>.cloud.appwrite.io", + "basePath": "\/v1", + "schemes": [ + "https" + ], + "consumes": [ + "application\/json", + "multipart\/form-data" + ], + "produces": [ + "application\/json" + ], + "securityDefinitions": { + "Project": { + "type": "apiKey", + "name": "X-Appwrite-Project", + "description": "Your project ID", + "in": "header", + "x-appwrite": { + "demo": "<YOUR_PROJECT_ID>" + } + }, + "JWT": { + "type": "apiKey", + "name": "X-Appwrite-JWT", + "description": "Your secret JSON Web Token", + "in": "header", + "x-appwrite": { + "demo": "<YOUR_JWT>" + } + }, + "Locale": { + "type": "apiKey", + "name": "X-Appwrite-Locale", + "description": "", + "in": "header", + "x-appwrite": { + "demo": "en" + } + }, + "Session": { + "type": "apiKey", + "name": "X-Appwrite-Session", + "description": "The user session to authenticate with", + "in": "header" + }, + "DevKey": { + "type": "apiKey", + "name": "X-Appwrite-Dev-Key", + "description": "Your secret dev API key", + "in": "header" + } + }, + "paths": { + "\/account": { + "get": { + "summary": "Get account", + "operationId": "accountGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get the currently logged in user.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "get", + "group": "account", + "weight": 10, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "post": { + "summary": "Create account", + "operationId": "accountCreate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to allow a new user to register a new account in your project. After the user registration completes successfully, you can use the [\/account\/verfication](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createVerification) route to start verifying the user email address. To allow the new user to login to their new account, you need to create a new [account session](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createEmailSession).", + "responses": { + "201": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "create", + "group": "account", + "weight": 9, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "New user password. Must be between 8 and 256 chars.", + "default": null, + "x-example": null + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + ] + } + }, + "\/account\/email": { + "patch": { + "summary": "Update email", + "operationId": "accountUpdateEmail", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Update currently logged in user account email address. After changing user address, the user confirmation status will get reset. A new confirmation email is not sent automatically however you can use the send confirmation email endpoint again to send the confirmation email. For security measures, user password is required to complete this request.\nThis endpoint can also be used to convert an anonymous account to a normal one, by passing an email address and a new password.\n", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateEmail", + "group": "account", + "weight": 35, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-email.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password. Must be at least 8 chars.", + "default": null, + "x-example": "password" + } + }, + "required": [ + "email", + "password" + ] + } + } + ] + } + }, + "\/account\/identities": { + "get": { + "summary": "List identities", + "operationId": "accountListIdentities", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get the list of identities for the currently logged in user.", + "responses": { + "200": { + "description": "Identities List", + "schema": { + "$ref": "#\/definitions\/identityList" + } + } + }, + "x-appwrite": { + "method": "listIdentities", + "group": "identities", + "weight": 58, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-identities.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-identities.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, provider, providerUid, providerEmail, providerAccessTokenExpiry", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/account\/identities\/{identityId}": { + "delete": { + "summary": "Delete identity", + "operationId": "accountDeleteIdentity", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "account" + ], + "description": "Delete an identity by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteIdentity", + "group": "identities", + "weight": 59, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-identity.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-identity.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "identityId", + "description": "Identity ID.", + "required": true, + "type": "string", + "x-example": "<IDENTITY_ID>", + "in": "path" + } + ] + } + }, + "\/account\/jwts": { + "post": { + "summary": "Create JWT", + "operationId": "accountCreateJWT", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to create a JSON Web Token. You can use the resulting JWT to authenticate on behalf of the current user when working with the Appwrite server-side API and SDKs. The JWT secret is valid for 15 minutes from its creation and will be invalid if the user will logout in that time frame.", + "responses": { + "201": { + "description": "JWT", + "schema": { + "$ref": "#\/definitions\/jwt" + } + } + }, + "x-appwrite": { + "method": "createJWT", + "group": "tokens", + "weight": 30, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-j-w-t.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-jwt.md", + "rate-limit": 100, + "rate-time": 3600, + "rate-key": "url:{url},userId:{userId}", + "scope": "account", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ] + } + }, + "\/account\/logs": { + "get": { + "summary": "List logs", + "operationId": "accountListLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get the list of latest security activity logs for the currently logged in user. Each log returns user IP address, location and date and time of log.", + "responses": { + "200": { + "description": "Logs List", + "schema": { + "$ref": "#\/definitions\/logList" + } + } + }, + "x-appwrite": { + "method": "listLogs", + "group": "logs", + "weight": 32, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/account\/mfa": { + "patch": { + "summary": "Update MFA", + "operationId": "accountUpdateMFA", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Enable or disable MFA on an account.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateMFA", + "group": "mfa", + "weight": 45, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-m-f-a.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "mfa": { + "type": "boolean", + "description": "Enable or disable MFA.", + "default": null, + "x-example": false + } + }, + "required": [ + "mfa" + ] + } + } + ] + } + }, + "\/account\/mfa\/authenticators\/{type}": { + "post": { + "summary": "Create authenticator", + "operationId": "accountCreateMfaAuthenticator", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Add an authenticator app to be used as an MFA factor. Verify the authenticator using the [verify authenticator](\/docs\/references\/cloud\/client-web\/account#updateMfaAuthenticator) method.", + "responses": { + "200": { + "description": "MFAType", + "schema": { + "$ref": "#\/definitions\/mfaType" + } + } + }, + "x-appwrite": { + "method": "createMfaAuthenticator", + "group": "mfa", + "weight": 47, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "type", + "description": "Type of authenticator. Must be `totp`", + "required": true, + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [], + "in": "path" + } + ] + }, + "put": { + "summary": "Update authenticator (confirmation)", + "operationId": "accountUpdateMfaAuthenticator", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Verify an authenticator app after adding it using the [add authenticator](\/docs\/references\/cloud\/client-web\/account#createMfaAuthenticator) method.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateMfaAuthenticator", + "group": "mfa", + "weight": 48, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "type", + "description": "Type of authenticator.", + "required": true, + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [], + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "otp": { + "type": "string", + "description": "Valid verification token.", + "default": null, + "x-example": "<OTP>" + } + }, + "required": [ + "otp" + ] + } + } + ] + }, + "delete": { + "summary": "Delete authenticator", + "operationId": "accountDeleteMfaAuthenticator", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "account" + ], + "description": "Delete an authenticator for a user by ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteMfaAuthenticator", + "group": "mfa", + "weight": 52, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "type", + "description": "Type of authenticator.", + "required": true, + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [], + "in": "path" + } + ] + } + }, + "\/account\/mfa\/challenge": { + "post": { + "summary": "Create MFA challenge", + "operationId": "accountCreateMfaChallenge", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Begin the process of MFA verification after sign-in. Finish the flow with [updateMfaChallenge](\/docs\/references\/cloud\/client-web\/account#updateMfaChallenge) method.", + "responses": { + "201": { + "description": "MFA Challenge", + "schema": { + "$ref": "#\/definitions\/mfaChallenge" + } + } + }, + "x-appwrite": { + "method": "createMfaChallenge", + "group": "mfa", + "weight": 53, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-mfa-challenge.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-mfa-challenge.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{userId}", + "scope": "account", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "factor": { + "type": "string", + "description": "Factor used for verification. Must be one of following: `email`, `phone`, `totp`, `recoveryCode`.", + "default": null, + "x-example": "email", + "enum": [ + "email", + "phone", + "totp", + "recoverycode" + ], + "x-enum-name": "AuthenticationFactor", + "x-enum-keys": [] + } + }, + "required": [ + "factor" + ] + } + } + ] + }, + "put": { + "summary": "Update MFA challenge (confirmation)", + "operationId": "accountUpdateMfaChallenge", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Complete the MFA challenge by providing the one-time password. Finish the process of MFA verification by providing the one-time password. To begin the flow, use [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method.", + "responses": { + "200": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "updateMfaChallenge", + "group": "mfa", + "weight": 54, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-mfa-challenge.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa-challenge.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},challengeId:{param-challengeId}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "challengeId": { + "type": "string", + "description": "ID of the challenge.", + "default": null, + "x-example": "<CHALLENGE_ID>" + }, + "otp": { + "type": "string", + "description": "Valid verification token.", + "default": null, + "x-example": "<OTP>" + } + }, + "required": [ + "challengeId", + "otp" + ] + } + } + ] + } + }, + "\/account\/mfa\/factors": { + "get": { + "summary": "List factors", + "operationId": "accountListMfaFactors", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "List the factors available on the account to be used as a MFA challange.", + "responses": { + "200": { + "description": "MFAFactors", + "schema": { + "$ref": "#\/definitions\/mfaFactors" + } + } + }, + "x-appwrite": { + "method": "listMfaFactors", + "group": "mfa", + "weight": 46, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-mfa-factors.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-mfa-factors.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/account\/mfa\/recovery-codes": { + "get": { + "summary": "List MFA recovery codes", + "operationId": "accountGetMfaRecoveryCodes", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get recovery codes that can be used as backup for MFA flow. Before getting codes, they must be generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method. An OTP challenge is required to read recovery codes.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "schema": { + "$ref": "#\/definitions\/mfaRecoveryCodes" + } + } + }, + "x-appwrite": { + "method": "getMfaRecoveryCodes", + "group": "mfa", + "weight": 51, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "post": { + "summary": "Create MFA recovery codes", + "operationId": "accountCreateMfaRecoveryCodes", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Generate recovery codes as backup for MFA flow. It's recommended to generate and show then immediately after user successfully adds their authehticator. Recovery codes can be used as a MFA verification type in [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method.", + "responses": { + "201": { + "description": "MFA Recovery Codes", + "schema": { + "$ref": "#\/definitions\/mfaRecoveryCodes" + } + } + }, + "x-appwrite": { + "method": "createMfaRecoveryCodes", + "group": "mfa", + "weight": 49, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "patch": { + "summary": "Update MFA recovery codes (regenerate)", + "operationId": "accountUpdateMfaRecoveryCodes", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Regenerate recovery codes that can be used as backup for MFA flow. Before regenerating codes, they must be first generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method. An OTP challenge is required to regenreate recovery codes.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "schema": { + "$ref": "#\/definitions\/mfaRecoveryCodes" + } + } + }, + "x-appwrite": { + "method": "updateMfaRecoveryCodes", + "group": "mfa", + "weight": 50, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/account\/name": { + "patch": { + "summary": "Update name", + "operationId": "accountUpdateName", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Update currently logged in user account name.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateName", + "group": "account", + "weight": 33, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-name.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-name.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + } + }, + "required": [ + "name" + ] + } + } + ] + } + }, + "\/account\/password": { + "patch": { + "summary": "Update password", + "operationId": "accountUpdatePassword", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Update currently logged in user password. For validation, user is required to pass in the new password, and the old password. For users created with OAuth, Team Invites and Magic URL, oldPassword is optional.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updatePassword", + "group": "account", + "weight": 34, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-password.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-password.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "password": { + "type": "string", + "description": "New user password. Must be at least 8 chars.", + "default": null, + "x-example": null + }, + "oldPassword": { + "type": "string", + "description": "Current user password. Must be at least 8 chars.", + "default": "", + "x-example": "password" + } + }, + "required": [ + "password" + ] + } + } + ] + } + }, + "\/account\/phone": { + "patch": { + "summary": "Update phone", + "operationId": "accountUpdatePhone", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Update the currently logged in user's phone number. After updating the phone number, the phone verification status will be reset. A confirmation SMS is not sent automatically, however you can use the [POST \/account\/verification\/phone](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createPhoneVerification) endpoint to send a confirmation SMS.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updatePhone", + "group": "account", + "weight": 36, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-phone.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-phone.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "default": null, + "x-example": "+12065550100" + }, + "password": { + "type": "string", + "description": "User password. Must be at least 8 chars.", + "default": null, + "x-example": "password" + } + }, + "required": [ + "phone", + "password" + ] + } + } + ] + } + }, + "\/account\/prefs": { + "get": { + "summary": "Get account preferences", + "operationId": "accountGetPrefs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get the preferences as a key-value object for the currently logged in user.", + "responses": { + "200": { + "description": "Preferences", + "schema": { + "$ref": "#\/definitions\/preferences" + } + } + }, + "x-appwrite": { + "method": "getPrefs", + "group": "account", + "weight": 31, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "patch": { + "summary": "Update preferences", + "operationId": "accountUpdatePrefs", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Update currently logged in user account preferences. The object you pass is stored as is, and replaces any previous value. The maximum allowed prefs size is 64kB and throws error if exceeded.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updatePrefs", + "group": "account", + "weight": 37, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "prefs": { + "type": "object", + "description": "Prefs key-value JSON object.", + "default": {}, + "x-example": "{}" + } + }, + "required": [ + "prefs" + ] + } + } + ] + } + }, + "\/account\/recovery": { + "post": { + "summary": "Create password recovery", + "operationId": "accountCreateRecovery", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Sends the user an email with a temporary secret key for password reset. When the user clicks the confirmation link he is redirected back to your app password reset URL with the secret key and email address values attached to the URL query string. Use the query string params to submit a request to the [PUT \/account\/recovery](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updateRecovery) endpoint to complete the process. The verification link sent to the user's email address is valid for 1 hour.", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createRecovery", + "group": "recovery", + "weight": 39, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-recovery.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-recovery.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},email:{param-email}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "default": null, + "x-example": "https:\/\/example.com" + } + }, + "required": [ + "email", + "url" + ] + } + } + ] + }, + "put": { + "summary": "Update password recovery (confirmation)", + "operationId": "accountUpdateRecovery", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to complete the user account password reset. Both the **userId** and **secret** arguments will be passed as query parameters to the redirect URL you have provided when sending your request to the [POST \/account\/recovery](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createRecovery) endpoint.\n\nPlease note that in order to avoid a [Redirect Attack](https:\/\/github.com\/OWASP\/CheatSheetSeries\/blob\/master\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) the only valid redirect URLs are the ones from domains you have set when adding your platforms in the console interface.", + "responses": { + "200": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "updateRecovery", + "group": "recovery", + "weight": 40, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-recovery.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-recovery.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid reset token.", + "default": null, + "x-example": "<SECRET>" + }, + "password": { + "type": "string", + "description": "New user password. Must be between 8 and 256 chars.", + "default": null, + "x-example": null + } + }, + "required": [ + "userId", + "secret", + "password" + ] + } + } + ] + } + }, + "\/account\/sessions": { + "get": { + "summary": "List sessions", + "operationId": "accountListSessions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get the list of active sessions across different devices for the currently logged in user.", + "responses": { + "200": { + "description": "Sessions List", + "schema": { + "$ref": "#\/definitions\/sessionList" + } + } + }, + "x-appwrite": { + "method": "listSessions", + "group": "sessions", + "weight": 12, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-sessions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "delete": { + "summary": "Delete sessions", + "operationId": "accountDeleteSessions", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "account" + ], + "description": "Delete all sessions from the user account and remove any sessions cookies from the end client.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSessions", + "group": "sessions", + "weight": 13, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-sessions.md", + "rate-limit": 100, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/account\/sessions\/anonymous": { + "post": { + "summary": "Create anonymous session", + "operationId": "accountCreateAnonymousSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to allow a new user to register an anonymous account in your project. This route will also create a new session for the user. To allow the new user to convert an anonymous account to a normal account, you need to update its [email and password](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updateEmail) or create an [OAuth2 session](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#CreateOAuth2Session).", + "responses": { + "201": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "createAnonymousSession", + "group": "sessions", + "weight": 18, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-anonymous-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session-anonymous.md", + "rate-limit": 50, + "rate-time": 3600, + "rate-key": "ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ] + } + }, + "\/account\/sessions\/email": { + "post": { + "summary": "Create email password session", + "operationId": "accountCreateEmailPasswordSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Allow the user to login into their account by providing a valid email and password combination. This route will create a new session for the user.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "201": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "createEmailPasswordSession", + "group": "sessions", + "weight": 17, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-email-password-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session-email-password.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},email:{param-email}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password. Must be at least 8 chars.", + "default": null, + "x-example": "password" + } + }, + "required": [ + "email", + "password" + ] + } + } + ] + } + }, + "\/account\/sessions\/magic-url": { + "put": { + "summary": "Update magic URL session", + "operationId": "accountUpdateMagicURLSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to create a session from token. Provide the **userId** and **secret** parameters from the successful response of authentication flows initiated by token creation. For example, magic URL and phone login.", + "responses": { + "201": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "updateMagicURLSession", + "group": "sessions", + "weight": 27, + "cookies": false, + "type": "", + "deprecated": true, + "demo": "account\/update-magic-u-r-l-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "ip:{ip},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "default": null, + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + ] + } + }, + "\/account\/sessions\/oauth2\/{provider}": { + "get": { + "summary": "Create OAuth2 session", + "operationId": "accountCreateOAuth2Session", + "consumes": [], + "produces": [ + "text\/html" + ], + "tags": [ + "account" + ], + "description": "Allow the user to login to their account using the OAuth2 provider of their choice. Each OAuth2 provider should be enabled from the Appwrite console first. Use the success and failure arguments to provide a redirect URL's back to your app when login is completed.\n\nIf there is already an active session, the new session will be attached to the logged-in account. If there are no active sessions, the server will attempt to look for a user with the same email address as the email received from the OAuth2 provider and attach the new session to the existing user. If no matching user is found - the server will create a new user.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "responses": { + "301": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "createOAuth2Session", + "group": "sessions", + "weight": 20, + "cookies": false, + "type": "webAuth", + "deprecated": false, + "demo": "account\/create-o-auth2session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session-oauth2.md", + "rate-limit": 50, + "rate-time": 3600, + "rate-key": "ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "provider", + "description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.", + "required": true, + "type": "string", + "x-example": "amazon", + "enum": [ + "amazon", + "apple", + "auth0", + "authentik", + "autodesk", + "bitbucket", + "bitly", + "box", + "dailymotion", + "discord", + "disqus", + "dropbox", + "etsy", + "facebook", + "figma", + "github", + "gitlab", + "google", + "linkedin", + "microsoft", + "notion", + "oidc", + "okta", + "paypal", + "paypalSandbox", + "podio", + "salesforce", + "slack", + "spotify", + "stripe", + "tradeshift", + "tradeshiftBox", + "twitch", + "wordpress", + "yahoo", + "yammer", + "yandex", + "zoho", + "zoom", + "mock" + ], + "x-enum-name": "OAuthProvider", + "x-enum-keys": [], + "in": "path" + }, + { + "name": "success", + "description": "URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "", + "in": "query" + }, + { + "name": "failure", + "description": "URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "", + "in": "query" + }, + { + "name": "scopes", + "description": "A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of 100 scopes are allowed, each 4096 characters long.", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/account\/sessions\/phone": { + "put": { + "summary": "Update phone session", + "operationId": "accountUpdatePhoneSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to create a session from token. Provide the **userId** and **secret** parameters from the successful response of authentication flows initiated by token creation. For example, magic URL and phone login.", + "responses": { + "201": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "updatePhoneSession", + "group": "sessions", + "weight": 28, + "cookies": false, + "type": "", + "deprecated": true, + "demo": "account\/update-phone-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "ip:{ip},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "default": null, + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + ] + } + }, + "\/account\/sessions\/token": { + "post": { + "summary": "Create session", + "operationId": "accountCreateSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to create a session from token. Provide the **userId** and **secret** parameters from the successful response of authentication flows initiated by token creation. For example, magic URL and phone login.", + "responses": { + "201": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "createSession", + "group": "sessions", + "weight": 19, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "ip:{ip},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Secret of a token generated by login methods. For example, the `createMagicURLToken` or `createPhoneToken` methods.", + "default": null, + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + ] + } + }, + "\/account\/sessions\/{sessionId}": { + "get": { + "summary": "Get session", + "operationId": "accountGetSession", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to get a logged in user's session using a Session ID. Inputting 'current' will return the current session being used.", + "responses": { + "200": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "getSession", + "group": "sessions", + "weight": 14, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get-session.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "description": "Session ID. Use the string 'current' to get the current device session.", + "required": true, + "type": "string", + "x-example": "<SESSION_ID>", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update session", + "operationId": "accountUpdateSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to extend a session's length. Extending a session is useful when session expiry is short. If the session was created using an OAuth provider, this endpoint refreshes the access token from the provider.", + "responses": { + "200": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "updateSession", + "group": "sessions", + "weight": 16, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "description": "Session ID. Use the string 'current' to update the current device session.", + "required": true, + "type": "string", + "x-example": "<SESSION_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete session", + "operationId": "accountDeleteSession", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "account" + ], + "description": "Logout the user. Use 'current' as the session ID to logout on this device, use a session ID to logout on another device. If you're looking to logout the user on all devices, use [Delete Sessions](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#deleteSessions) instead.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSession", + "group": "sessions", + "weight": 15, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-session.md", + "rate-limit": 100, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "description": "Session ID. Use the string 'current' to delete the current device session.", + "required": true, + "type": "string", + "x-example": "<SESSION_ID>", + "in": "path" + } + ] + } + }, + "\/account\/status": { + "patch": { + "summary": "Update status", + "operationId": "accountUpdateStatus", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Block the currently logged in user account. Behind the scene, the user record is not deleted but permanently blocked from any access. To completely delete a user, use the Users API instead.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateStatus", + "group": "account", + "weight": 38, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/account\/targets\/push": { + "post": { + "summary": "Create push target", + "operationId": "accountCreatePushTarget", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to register a device for push notifications. Provide a target ID (custom or generated using ID.unique()), a device identifier (usually a device token), and optionally specify which provider should send notifications to this target. The target is automatically linked to the current session and includes device information like brand and model.", + "responses": { + "201": { + "description": "Target", + "schema": { + "$ref": "#\/definitions\/target" + } + } + }, + "x-appwrite": { + "method": "createPushTarget", + "group": "pushTargets", + "weight": 55, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-push-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-push-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "targetId": { + "type": "string", + "description": "Target ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<TARGET_ID>" + }, + "identifier": { + "type": "string", + "description": "The target identifier (token, email, phone etc.)", + "default": null, + "x-example": "<IDENTIFIER>" + }, + "providerId": { + "type": "string", + "description": "Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.", + "default": "", + "x-example": "<PROVIDER_ID>" + } + }, + "required": [ + "targetId", + "identifier" + ] + } + } + ] + } + }, + "\/account\/targets\/{targetId}\/push": { + "put": { + "summary": "Update push target", + "operationId": "accountUpdatePushTarget", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Update the currently logged in user's push notification target. You can modify the target's identifier (device token) and provider ID (token, email, phone etc.). The target must exist and belong to the current user. If you change the provider ID, notifications will be sent through the new messaging provider instead.", + "responses": { + "200": { + "description": "Target", + "schema": { + "$ref": "#\/definitions\/target" + } + } + }, + "x-appwrite": { + "method": "updatePushTarget", + "group": "pushTargets", + "weight": 56, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-push-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-push-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [] + } + ], + "parameters": [ + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "type": "string", + "x-example": "<TARGET_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "description": "The target identifier (token, email, phone etc.)", + "default": null, + "x-example": "<IDENTIFIER>" + } + }, + "required": [ + "identifier" + ] + } + } + ] + }, + "delete": { + "summary": "Delete push target", + "operationId": "accountDeletePushTarget", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "account" + ], + "description": "Delete a push notification target for the currently logged in user. After deletion, the device will no longer receive push notifications. The target must exist and belong to the current user.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deletePushTarget", + "group": "pushTargets", + "weight": 57, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-push-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-push-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [] + } + ], + "parameters": [ + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "type": "string", + "x-example": "<TARGET_ID>", + "in": "path" + } + ] + } + }, + "\/account\/tokens\/email": { + "post": { + "summary": "Create email token (OTP)", + "operationId": "accountCreateEmailToken", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not be registered, a new user will be created. Use the returned user ID and secret and submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The secret sent to the user's email is valid for 15 minutes.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createEmailToken", + "group": "tokens", + "weight": 26, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-email-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-email.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},email:{param-email}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "phrase": { + "type": "boolean", + "description": "Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.", + "default": false, + "x-example": false + } + }, + "required": [ + "userId", + "email" + ] + } + } + ] + } + }, + "\/account\/tokens\/magic-url": { + "post": { + "summary": "Create magic URL token", + "operationId": "accountCreateMagicURLToken", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createMagicURLToken", + "group": "tokens", + "weight": 25, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-magic-u-r-l-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-magic-url.md", + "rate-limit": 60, + "rate-time": 3600, + "rate-key": [ + "url:{url},email:{param-email}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "default": "", + "x-example": "https:\/\/example.com" + }, + "phrase": { + "type": "boolean", + "description": "Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.", + "default": false, + "x-example": false + } + }, + "required": [ + "userId", + "email" + ] + } + } + ] + } + }, + "\/account\/tokens\/oauth2\/{provider}": { + "get": { + "summary": "Create OAuth2 token", + "operationId": "accountCreateOAuth2Token", + "consumes": [], + "produces": [ + "text\/html" + ], + "tags": [ + "account" + ], + "description": "Allow the user to login to their account using the OAuth2 provider of their choice. Each OAuth2 provider should be enabled from the Appwrite console first. Use the success and failure arguments to provide a redirect URL's back to your app when login is completed. \n\nIf authentication succeeds, `userId` and `secret` of a token will be appended to the success URL as query parameters. These can be used to create a new session using the [Create session](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "301": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "createOAuth2Token", + "group": "tokens", + "weight": 24, + "cookies": false, + "type": "webAuth", + "deprecated": false, + "demo": "account\/create-o-auth2token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-oauth2.md", + "rate-limit": 50, + "rate-time": 3600, + "rate-key": "ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "provider", + "description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.", + "required": true, + "type": "string", + "x-example": "amazon", + "enum": [ + "amazon", + "apple", + "auth0", + "authentik", + "autodesk", + "bitbucket", + "bitly", + "box", + "dailymotion", + "discord", + "disqus", + "dropbox", + "etsy", + "facebook", + "figma", + "github", + "gitlab", + "google", + "linkedin", + "microsoft", + "notion", + "oidc", + "okta", + "paypal", + "paypalSandbox", + "podio", + "salesforce", + "slack", + "spotify", + "stripe", + "tradeshift", + "tradeshiftBox", + "twitch", + "wordpress", + "yahoo", + "yammer", + "yandex", + "zoho", + "zoom", + "mock" + ], + "x-enum-name": "OAuthProvider", + "x-enum-keys": [], + "in": "path" + }, + { + "name": "success", + "description": "URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "", + "in": "query" + }, + { + "name": "failure", + "description": "URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "", + "in": "query" + }, + { + "name": "scopes", + "description": "A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of 100 scopes are allowed, each 4096 characters long.", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/account\/tokens\/phone": { + "post": { + "summary": "Create phone token", + "operationId": "accountCreatePhoneToken", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Sends the user an SMS with a secret key for creating a session. If the provided user ID has not be registered, a new user will be created. Use the returned user ID and secret and submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The secret sent to the user's phone is valid for 15 minutes.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createPhoneToken", + "group": "tokens", + "weight": 29, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-phone-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-phone.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},phone:{param-phone}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "default": null, + "x-example": "+12065550100" + } + }, + "required": [ + "userId", + "phone" + ] + } + } + ] + } + }, + "\/account\/verification": { + "post": { + "summary": "Create email verification", + "operationId": "accountCreateVerification", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to send a verification message to your user email address to confirm they are the valid owners of that address. Both the **userId** and **secret** arguments will be passed as query parameters to the URL you have provided to be attached to the verification email. The provided URL should redirect the user back to your app and allow you to complete the verification process by verifying both the **userId** and **secret** parameters. Learn more about how to [complete the verification process](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updateVerification). The verification link sent to the user's email address is valid for 7 days.\n\nPlease note that in order to avoid a [Redirect Attack](https:\/\/github.com\/OWASP\/CheatSheetSeries\/blob\/master\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md), the only valid redirect URLs are the ones from domains you have set when adding your platforms in the console interface.\n", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createVerification", + "group": "verification", + "weight": 41, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-email-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{userId}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "default": null, + "x-example": "https:\/\/example.com" + } + }, + "required": [ + "url" + ] + } + } + ] + }, + "put": { + "summary": "Update email verification (confirmation)", + "operationId": "accountUpdateVerification", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to complete the user email verification process. Use both the **userId** and **secret** parameters that were attached to your app URL to verify the user email ownership. If confirmed this route will return a 200 status code.", + "responses": { + "200": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "updateVerification", + "group": "verification", + "weight": 42, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-email-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{param-userId}", + "scope": "public", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "default": null, + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + ] + } + }, + "\/account\/verification\/phone": { + "post": { + "summary": "Create phone verification", + "operationId": "accountCreatePhoneVerification", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to send a verification SMS to the currently logged in user. This endpoint is meant for use after updating a user's phone number using the [accountUpdatePhone](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updatePhone) endpoint. Learn more about how to [complete the verification process](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updatePhoneVerification). The verification code sent to the user's phone number is valid for 15 minutes.", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createPhoneVerification", + "group": "verification", + "weight": 43, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-phone-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-phone-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},userId:{userId}", + "url:{url},ip:{ip}" + ], + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "put": { + "summary": "Update phone verification (confirmation)", + "operationId": "accountUpdatePhoneVerification", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to complete the user phone verification process. Use the **userId** and **secret** that were sent to your user's phone number to verify the user email ownership. If confirmed this route will return a 200 status code.", + "responses": { + "200": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "updatePhoneVerification", + "group": "verification", + "weight": 44, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-phone-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-phone-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "userId:{param-userId}", + "scope": "public", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "default": null, + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + ] + } + }, + "\/avatars\/browsers\/{code}": { + "get": { + "summary": "Get browser icon", + "operationId": "avatarsGetBrowser", + "consumes": [], + "produces": [ + "image\/png" + ], + "tags": [ + "avatars" + ], + "description": "You can use this endpoint to show different browser icons to your users. The code argument receives the browser code as it appears in your user [GET \/account\/sessions](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#getSessions) endpoint. Use width, height and quality arguments to change the output settings.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getBrowser", + "group": null, + "weight": 61, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-browser.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-browser.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "code", + "description": "Browser Code.", + "required": true, + "type": "string", + "x-example": "aa", + "enum": [ + "aa", + "an", + "ch", + "ci", + "cm", + "cr", + "ff", + "sf", + "mf", + "ps", + "oi", + "om", + "op", + "on" + ], + "x-enum-name": "Browser", + "x-enum-keys": [ + "Avant Browser", + "Android WebView Beta", + "Google Chrome", + "Google Chrome (iOS)", + "Google Chrome (Mobile)", + "Chromium", + "Mozilla Firefox", + "Safari", + "Mobile Safari", + "Microsoft Edge", + "Microsoft Edge (iOS)", + "Opera Mini", + "Opera", + "Opera (Next)" + ], + "in": "path" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + }, + { + "name": "quality", + "description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1, + "in": "query" + } + ] + } + }, + "\/avatars\/credit-cards\/{code}": { + "get": { + "summary": "Get credit card icon", + "operationId": "avatarsGetCreditCard", + "consumes": [], + "produces": [ + "image\/png" + ], + "tags": [ + "avatars" + ], + "description": "The credit card endpoint will return you the icon of the credit card provider you need. Use width, height and quality arguments to change the output settings.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.\n", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getCreditCard", + "group": null, + "weight": 60, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-credit-card.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-credit-card.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "code", + "description": "Credit Card Code. Possible values: amex, argencard, cabal, cencosud, diners, discover, elo, hipercard, jcb, mastercard, naranja, targeta-shopping, union-china-pay, visa, mir, maestro, rupay.", + "required": true, + "type": "string", + "x-example": "amex", + "enum": [ + "amex", + "argencard", + "cabal", + "cencosud", + "diners", + "discover", + "elo", + "hipercard", + "jcb", + "mastercard", + "naranja", + "targeta-shopping", + "union-china-pay", + "visa", + "mir", + "maestro", + "rupay" + ], + "x-enum-name": "CreditCard", + "x-enum-keys": [ + "American Express", + "Argencard", + "Cabal", + "Cencosud", + "Diners Club", + "Discover", + "Elo", + "Hipercard", + "JCB", + "Mastercard", + "Naranja", + "Tarjeta Shopping", + "Union China Pay", + "Visa", + "MIR", + "Maestro", + "Rupay" + ], + "in": "path" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + }, + { + "name": "quality", + "description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1, + "in": "query" + } + ] + } + }, + "\/avatars\/favicon": { + "get": { + "summary": "Get favicon", + "operationId": "avatarsGetFavicon", + "consumes": [], + "produces": [ + "image\/*" + ], + "tags": [ + "avatars" + ], + "description": "Use this endpoint to fetch the favorite icon (AKA favicon) of any remote website URL.\n\nThis endpoint does not follow HTTP redirects.", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getFavicon", + "group": null, + "weight": 64, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-favicon.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-favicon.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "url", + "description": "Website URL which you want to fetch the favicon from.", + "required": true, + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "in": "query" + } + ] + } + }, + "\/avatars\/flags\/{code}": { + "get": { + "summary": "Get country flag", + "operationId": "avatarsGetFlag", + "consumes": [], + "produces": [ + "image\/png" + ], + "tags": [ + "avatars" + ], + "description": "You can use this endpoint to show different country flags icons to your users. The code argument receives the 2 letter country code. Use width, height and quality arguments to change the output settings. Country codes follow the [ISO 3166-1](https:\/\/en.wikipedia.org\/wiki\/ISO_3166-1) standard.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.\n", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getFlag", + "group": null, + "weight": 62, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-flag.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-flag.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "code", + "description": "Country Code. ISO Alpha-2 country code format.", + "required": true, + "type": "string", + "x-example": "af", + "enum": [ + "af", + "ao", + "al", + "ad", + "ae", + "ar", + "am", + "ag", + "au", + "at", + "az", + "bi", + "be", + "bj", + "bf", + "bd", + "bg", + "bh", + "bs", + "ba", + "by", + "bz", + "bo", + "br", + "bb", + "bn", + "bt", + "bw", + "cf", + "ca", + "ch", + "cl", + "cn", + "ci", + "cm", + "cd", + "cg", + "co", + "km", + "cv", + "cr", + "cu", + "cy", + "cz", + "de", + "dj", + "dm", + "dk", + "do", + "dz", + "ec", + "eg", + "er", + "es", + "ee", + "et", + "fi", + "fj", + "fr", + "fm", + "ga", + "gb", + "ge", + "gh", + "gn", + "gm", + "gw", + "gq", + "gr", + "gd", + "gt", + "gy", + "hn", + "hr", + "ht", + "hu", + "id", + "in", + "ie", + "ir", + "iq", + "is", + "il", + "it", + "jm", + "jo", + "jp", + "kz", + "ke", + "kg", + "kh", + "ki", + "kn", + "kr", + "kw", + "la", + "lb", + "lr", + "ly", + "lc", + "li", + "lk", + "ls", + "lt", + "lu", + "lv", + "ma", + "mc", + "md", + "mg", + "mv", + "mx", + "mh", + "mk", + "ml", + "mt", + "mm", + "me", + "mn", + "mz", + "mr", + "mu", + "mw", + "my", + "na", + "ne", + "ng", + "ni", + "nl", + "no", + "np", + "nr", + "nz", + "om", + "pk", + "pa", + "pe", + "ph", + "pw", + "pg", + "pl", + "pf", + "kp", + "pt", + "py", + "qa", + "ro", + "ru", + "rw", + "sa", + "sd", + "sn", + "sg", + "sb", + "sl", + "sv", + "sm", + "so", + "rs", + "ss", + "st", + "sr", + "sk", + "si", + "se", + "sz", + "sc", + "sy", + "td", + "tg", + "th", + "tj", + "tm", + "tl", + "to", + "tt", + "tn", + "tr", + "tv", + "tz", + "ug", + "ua", + "uy", + "us", + "uz", + "va", + "vc", + "ve", + "vn", + "vu", + "ws", + "ye", + "za", + "zm", + "zw" + ], + "x-enum-name": "Flag", + "x-enum-keys": [ + "Afghanistan", + "Angola", + "Albania", + "Andorra", + "United Arab Emirates", + "Argentina", + "Armenia", + "Antigua and Barbuda", + "Australia", + "Austria", + "Azerbaijan", + "Burundi", + "Belgium", + "Benin", + "Burkina Faso", + "Bangladesh", + "Bulgaria", + "Bahrain", + "Bahamas", + "Bosnia and Herzegovina", + "Belarus", + "Belize", + "Bolivia", + "Brazil", + "Barbados", + "Brunei Darussalam", + "Bhutan", + "Botswana", + "Central African Republic", + "Canada", + "Switzerland", + "Chile", + "China", + "C\u00f4te d'Ivoire", + "Cameroon", + "Democratic Republic of the Congo", + "Republic of the Congo", + "Colombia", + "Comoros", + "Cape Verde", + "Costa Rica", + "Cuba", + "Cyprus", + "Czech Republic", + "Germany", + "Djibouti", + "Dominica", + "Denmark", + "Dominican Republic", + "Algeria", + "Ecuador", + "Egypt", + "Eritrea", + "Spain", + "Estonia", + "Ethiopia", + "Finland", + "Fiji", + "France", + "Micronesia (Federated States of)", + "Gabon", + "United Kingdom", + "Georgia", + "Ghana", + "Guinea", + "Gambia", + "Guinea-Bissau", + "Equatorial Guinea", + "Greece", + "Grenada", + "Guatemala", + "Guyana", + "Honduras", + "Croatia", + "Haiti", + "Hungary", + "Indonesia", + "India", + "Ireland", + "Iran (Islamic Republic of)", + "Iraq", + "Iceland", + "Israel", + "Italy", + "Jamaica", + "Jordan", + "Japan", + "Kazakhstan", + "Kenya", + "Kyrgyzstan", + "Cambodia", + "Kiribati", + "Saint Kitts and Nevis", + "South Korea", + "Kuwait", + "Lao People's Democratic Republic", + "Lebanon", + "Liberia", + "Libya", + "Saint Lucia", + "Liechtenstein", + "Sri Lanka", + "Lesotho", + "Lithuania", + "Luxembourg", + "Latvia", + "Morocco", + "Monaco", + "Moldova", + "Madagascar", + "Maldives", + "Mexico", + "Marshall Islands", + "North Macedonia", + "Mali", + "Malta", + "Myanmar", + "Montenegro", + "Mongolia", + "Mozambique", + "Mauritania", + "Mauritius", + "Malawi", + "Malaysia", + "Namibia", + "Niger", + "Nigeria", + "Nicaragua", + "Netherlands", + "Norway", + "Nepal", + "Nauru", + "New Zealand", + "Oman", + "Pakistan", + "Panama", + "Peru", + "Philippines", + "Palau", + "Papua New Guinea", + "Poland", + "French Polynesia", + "North Korea", + "Portugal", + "Paraguay", + "Qatar", + "Romania", + "Russia", + "Rwanda", + "Saudi Arabia", + "Sudan", + "Senegal", + "Singapore", + "Solomon Islands", + "Sierra Leone", + "El Salvador", + "San Marino", + "Somalia", + "Serbia", + "South Sudan", + "Sao Tome and Principe", + "Suriname", + "Slovakia", + "Slovenia", + "Sweden", + "Eswatini", + "Seychelles", + "Syria", + "Chad", + "Togo", + "Thailand", + "Tajikistan", + "Turkmenistan", + "Timor-Leste", + "Tonga", + "Trinidad and Tobago", + "Tunisia", + "Turkey", + "Tuvalu", + "Tanzania", + "Uganda", + "Ukraine", + "Uruguay", + "United States", + "Uzbekistan", + "Vatican City", + "Saint Vincent and the Grenadines", + "Venezuela", + "Vietnam", + "Vanuatu", + "Samoa", + "Yemen", + "South Africa", + "Zambia", + "Zimbabwe" + ], + "in": "path" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + }, + { + "name": "quality", + "description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1, + "in": "query" + } + ] + } + }, + "\/avatars\/image": { + "get": { + "summary": "Get image from URL", + "operationId": "avatarsGetImage", + "consumes": [], + "produces": [ + "image\/*" + ], + "tags": [ + "avatars" + ], + "description": "Use this endpoint to fetch a remote image URL and crop it to any image size you want. This endpoint is very useful if you need to crop and display remote images in your app or in case you want to make sure a 3rd party image is properly served using a TLS protocol.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 400x400px.\n\nThis endpoint does not follow HTTP redirects.", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getImage", + "group": null, + "weight": 63, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-image.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-image.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "url", + "description": "Image URL which you want to crop.", + "required": true, + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "in": "query" + }, + { + "name": "width", + "description": "Resize preview image width, Pass an integer between 0 to 2000. Defaults to 400.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 400, + "in": "query" + }, + { + "name": "height", + "description": "Resize preview image height, Pass an integer between 0 to 2000. Defaults to 400.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 400, + "in": "query" + } + ] + } + }, + "\/avatars\/initials": { + "get": { + "summary": "Get user initials", + "operationId": "avatarsGetInitials", + "consumes": [], + "produces": [ + "image\/png" + ], + "tags": [ + "avatars" + ], + "description": "Use this endpoint to show your user initials avatar icon on your website or app. By default, this route will try to print your logged-in user name or email initials. You can also overwrite the user name if you pass the 'name' parameter. If no name is given and no user is logged, an empty avatar will be returned.\n\nYou can use the color and background params to change the avatar colors. By default, a random theme will be selected. The random theme will persist for the user's initials when reloading the same theme will always return for the same initials.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.\n", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getInitials", + "group": null, + "weight": 66, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-initials.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-initials.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "name", + "description": "Full Name. When empty, current user name or email will be used. Max length: 128 chars.", + "required": false, + "type": "string", + "x-example": "<NAME>", + "default": "", + "in": "query" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 500, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 500, + "in": "query" + }, + { + "name": "background", + "description": "Changes background color. By default a random color will be picked and stay will persistent to the given name.", + "required": false, + "type": "string", + "default": "", + "in": "query" + } + ] + } + }, + "\/avatars\/qr": { + "get": { + "summary": "Get QR code", + "operationId": "avatarsGetQR", + "consumes": [], + "produces": [ + "image\/png" + ], + "tags": [ + "avatars" + ], + "description": "Converts a given plain text to a QR code image. You can use the query parameters to change the size and style of the resulting image.\n", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getQR", + "group": null, + "weight": 65, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-q-r.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-qr.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "text", + "description": "Plain text to be converted to QR code image.", + "required": true, + "type": "string", + "x-example": "<TEXT>", + "in": "query" + }, + { + "name": "size", + "description": "QR code size. Pass an integer between 1 to 1000. Defaults to 400.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 1, + "default": 400, + "in": "query" + }, + { + "name": "margin", + "description": "Margin from edge. Pass an integer between 0 to 10. Defaults to 1.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 1, + "in": "query" + }, + { + "name": "download", + "description": "Return resulting image with 'Content-Disposition: attachment ' headers for the browser to start downloading it. Pass 0 for no header, or 1 for otherwise. Default value is set to 0.", + "required": false, + "type": "boolean", + "x-example": false, + "default": false, + "in": "query" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents": { + "get": { + "summary": "List documents", + "operationId": "databasesListDocuments", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a list of all the user's documents in a given collection. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Documents List", + "schema": { + "$ref": "#\/definitions\/documentList" + } + } + }, + "x-appwrite": { + "method": "listDocuments", + "group": "documents", + "weight": 110, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-documents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-documents.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create document", + "operationId": "databasesCreateDocument", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "201": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "createDocument", + "group": "documents", + "weight": 109, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "methods": [ + { + "name": "createDocument", + "auth": { + "Session": [], + "Key": [], + "JWT": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documentId", + "data", + "permissions" + ], + "required": [ + "databaseId", + "collectionId", + "documentId", + "data" + ], + "responses": [ + { + "code": 201, + "model": "#\/definitions\/document" + } + ], + "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + } + ], + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection). Make sure to define attributes before creating documents.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "documentId": { + "type": "string", + "description": "Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": "", + "x-example": "<DOCUMENT_ID>" + }, + "data": { + "type": "object", + "description": "Document data as JSON object.", + "default": [], + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "documents": { + "type": "array", + "description": "Array of documents data as JSON objects.", + "default": [], + "x-example": null, + "items": { + "type": "object" + } + } + } + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}": { + "get": { + "summary": "Get document", + "operationId": "databasesGetDocument", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a document by its unique ID. This endpoint response returns a JSON object with the document data.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "getDocument", + "group": "documents", + "weight": 111, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-document.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "put": { + "summary": "Upsert document", + "operationId": "databasesUpsertDocument", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "upsertDocument", + "group": "documents", + "weight": 114, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include all required attributes of the document to be created or updated.", + "default": {}, + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "data" + ] + } + } + ] + }, + "patch": { + "summary": "Update document", + "operationId": "databasesUpdateDocument", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a document by its unique ID. Using the patch method you can pass only specific fields that will get updated.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "updateDocument", + "group": "documents", + "weight": 113, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include only attribute and value pairs to be updated.", + "default": [], + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + } + } + } + ] + }, + "delete": { + "summary": "Delete document", + "operationId": "databasesDeleteDocument", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "databases" + ], + "description": "Delete a document by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDocument", + "group": "documents", + "weight": 119, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-document.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/decrement": { + "patch": { + "summary": "Decrement document attribute", + "operationId": "databasesDecrementDocumentAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Decrement a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "decrementDocumentAttribute", + "group": "documents", + "weight": 116, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/decrement-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/decrement-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to decrement the attribute by. The value must be a number.", + "default": 1, + "x-example": null + }, + "min": { + "type": "mixed", + "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", + "default": null, + "x-example": null + } + } + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/increment": { + "patch": { + "summary": "Increment document attribute", + "operationId": "databasesIncrementDocumentAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Increment a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "incrementDocumentAttribute", + "group": "documents", + "weight": 115, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/increment-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/increment-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to increment the attribute by. The value must be a number.", + "default": 1, + "x-example": null + }, + "max": { + "type": "mixed", + "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", + "default": null, + "x-example": null + } + } + } + } + ] + } + }, + "\/functions\/{functionId}\/executions": { + "get": { + "summary": "List executions", + "operationId": "functionsListExecutions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a list of all the current user function execution logs. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Executions List", + "schema": { + "$ref": "#\/definitions\/executionList" + } + } + }, + "x-appwrite": { + "method": "listExecutions", + "group": "executions", + "weight": 394, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-executions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the current user function execution logs. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: trigger, status, responseStatusCode, duration, requestMethod, requestPath, deploymentId", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create execution", + "operationId": "functionsCreateExecution", + "consumes": [ + "application\/json" + ], + "produces": [ + "multipart\/form-data" + ], + "tags": [ + "functions" + ], + "description": "Trigger a function execution. The returned object will return you the current execution status. You can ping the `Get Execution` endpoint to get updates on the current execution status. Once this endpoint is called, your function execution process will start asynchronously.", + "responses": { + "201": { + "description": "Execution", + "schema": { + "$ref": "#\/definitions\/execution" + } + } + }, + "x-appwrite": { + "method": "createExecution", + "group": "executions", + "weight": 392, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-execution.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterTrigger a function execution. The returned object will return you the current execution status. You can ping the `Get Execution` endpoint to get updates on the current execution status. Once this endpoint is called, your function execution process will start asynchronously.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "body": { + "type": "string", + "description": "HTTP body of execution. Default value is empty string.", + "default": "", + "x-example": "<BODY>" + }, + "async": { + "type": "boolean", + "description": "Execute code in the background. Default value is false.", + "default": false, + "x-example": false + }, + "path": { + "type": "string", + "description": "HTTP path of execution. Path can include query params. Default value is \/", + "default": "\/", + "x-example": "<PATH>" + }, + "method": { + "type": "string", + "description": "HTTP method of execution. Default value is GET.", + "default": "POST", + "x-example": "GET", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE", + "OPTIONS" + ], + "x-enum-name": "ExecutionMethod", + "x-enum-keys": [] + }, + "headers": { + "type": "object", + "description": "HTTP headers of execution. Defaults to empty.", + "default": [], + "x-example": "{}" + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled execution time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes.", + "default": null, + "x-example": null + } + } + } + } + ] + } + }, + "\/functions\/{functionId}\/executions\/{executionId}": { + "get": { + "summary": "Get execution", + "operationId": "functionsGetExecution", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a function execution log by its unique ID.", + "responses": { + "200": { + "description": "Execution", + "schema": { + "$ref": "#\/definitions\/execution" + } + } + }, + "x-appwrite": { + "method": "getExecution", + "group": "executions", + "weight": 393, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get-execution.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function execution log by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "executionId", + "description": "Execution ID.", + "required": true, + "type": "string", + "x-example": "<EXECUTION_ID>", + "in": "path" + } + ] + } + }, + "\/graphql": { + "post": { + "summary": "GraphQL endpoint", + "operationId": "graphqlQuery", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "graphql" + ], + "description": "Execute a GraphQL mutation.", + "responses": { + "200": { + "description": "Any", + "schema": { + "$ref": "#\/definitions\/any" + } + } + }, + "x-appwrite": { + "method": "query", + "group": "graphql", + "weight": 308, + "cookies": false, + "type": "graphql", + "deprecated": false, + "demo": "graphql\/query.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/graphql\/post.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "url:{url},ip:{ip}", + "scope": "graphql", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "query": { + "type": "object", + "description": "The query or queries to execute.", + "default": {}, + "x-example": "{}" + } + }, + "required": [ + "query" + ] + } + } + ] + } + }, + "\/graphql\/mutation": { + "post": { + "summary": "GraphQL endpoint", + "operationId": "graphqlMutation", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "graphql" + ], + "description": "Execute a GraphQL mutation.", + "responses": { + "200": { + "description": "Any", + "schema": { + "$ref": "#\/definitions\/any" + } + } + }, + "x-appwrite": { + "method": "mutation", + "group": "graphql", + "weight": 307, + "cookies": false, + "type": "graphql", + "deprecated": false, + "demo": "graphql\/mutation.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/graphql\/post.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "url:{url},ip:{ip}", + "scope": "graphql", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "query": { + "type": "object", + "description": "The query or queries to execute.", + "default": {}, + "x-example": "{}" + } + }, + "required": [ + "query" + ] + } + } + ] + } + }, + "\/locale": { + "get": { + "summary": "Get user locale", + "operationId": "localeGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "Get the current user location based on IP. Returns an object with user country code, country name, continent name, continent code, ip address and suggested currency. You can use the locale header to get the data in a supported language.\n\n([IP Geolocation by DB-IP](https:\/\/db-ip.com))", + "responses": { + "200": { + "description": "Locale", + "schema": { + "$ref": "#\/definitions\/locale" + } + } + }, + "x-appwrite": { + "method": "get", + "group": null, + "weight": 124, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/get-locale.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/locale\/codes": { + "get": { + "summary": "List locale codes", + "operationId": "localeListCodes", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all locale codes in [ISO 639-1](https:\/\/en.wikipedia.org\/wiki\/List_of_ISO_639-1_codes).", + "responses": { + "200": { + "description": "Locale codes list", + "schema": { + "$ref": "#\/definitions\/localeCodeList" + } + } + }, + "x-appwrite": { + "method": "listCodes", + "group": null, + "weight": 125, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-locale-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/locale\/continents": { + "get": { + "summary": "List continents", + "operationId": "localeListContinents", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all continents. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Continents List", + "schema": { + "$ref": "#\/definitions\/continentList" + } + } + }, + "x-appwrite": { + "method": "listContinents", + "group": null, + "weight": 129, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-continents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-continents.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/locale\/countries": { + "get": { + "summary": "List countries", + "operationId": "localeListCountries", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all countries. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Countries List", + "schema": { + "$ref": "#\/definitions\/countryList" + } + } + }, + "x-appwrite": { + "method": "listCountries", + "group": null, + "weight": 126, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-countries.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-countries.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/locale\/countries\/eu": { + "get": { + "summary": "List EU countries", + "operationId": "localeListCountriesEU", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all countries that are currently members of the EU. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Countries List", + "schema": { + "$ref": "#\/definitions\/countryList" + } + } + }, + "x-appwrite": { + "method": "listCountriesEU", + "group": null, + "weight": 127, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-countries-e-u.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-countries-eu.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/locale\/countries\/phones": { + "get": { + "summary": "List countries phone codes", + "operationId": "localeListCountriesPhones", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all countries phone codes. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Phones List", + "schema": { + "$ref": "#\/definitions\/phoneList" + } + } + }, + "x-appwrite": { + "method": "listCountriesPhones", + "group": null, + "weight": 128, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-countries-phones.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-countries-phones.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/locale\/currencies": { + "get": { + "summary": "List currencies", + "operationId": "localeListCurrencies", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all currencies, including currency symbol, name, plural, and decimal digits for all major and minor currencies. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Currencies List", + "schema": { + "$ref": "#\/definitions\/currencyList" + } + } + }, + "x-appwrite": { + "method": "listCurrencies", + "group": null, + "weight": 130, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-currencies.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-currencies.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/locale\/languages": { + "get": { + "summary": "List languages", + "operationId": "localeListLanguages", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all languages classified by ISO 639-1 including 2-letter code, name in English, and name in the respective language.", + "responses": { + "200": { + "description": "Languages List", + "schema": { + "$ref": "#\/definitions\/languageList" + } + } + }, + "x-appwrite": { + "method": "listLanguages", + "group": null, + "weight": 131, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-languages.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-languages.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/messaging\/topics\/{topicId}\/subscribers": { + "post": { + "summary": "Create subscriber", + "operationId": "messagingCreateSubscriber", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new subscriber.", + "responses": { + "201": { + "description": "Subscriber", + "schema": { + "$ref": "#\/definitions\/subscriber" + } + } + }, + "x-appwrite": { + "method": "createSubscriber", + "group": "subscribers", + "weight": 354, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-subscriber.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-subscriber.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.write", + "platforms": [ + "server", + "client", + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [], + "Session": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID to subscribe to.", + "required": true, + "type": "string", + "x-example": "<TOPIC_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "subscriberId": { + "type": "string", + "description": "Subscriber ID. Choose a custom Subscriber ID or a new Subscriber ID.", + "default": null, + "x-example": "<SUBSCRIBER_ID>" + }, + "targetId": { + "type": "string", + "description": "Target ID. The target ID to link to the specified Topic ID.", + "default": null, + "x-example": "<TARGET_ID>" + } + }, + "required": [ + "subscriberId", + "targetId" + ] + } + } + ] + } + }, + "\/messaging\/topics\/{topicId}\/subscribers\/{subscriberId}": { + "delete": { + "summary": "Delete subscriber", + "operationId": "messagingDeleteSubscriber", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "messaging" + ], + "description": "Delete a subscriber by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSubscriber", + "group": "subscribers", + "weight": 358, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/delete-subscriber.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/delete-subscriber.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.write", + "platforms": [ + "server", + "client", + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [], + "Session": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID subscribed to.", + "required": true, + "type": "string", + "x-example": "<TOPIC_ID>", + "in": "path" + }, + { + "name": "subscriberId", + "description": "Subscriber ID.", + "required": true, + "type": "string", + "x-example": "<SUBSCRIBER_ID>", + "in": "path" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files": { + "get": { + "summary": "List files", + "operationId": "storageListFiles", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Get a list of all the user files. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Files List", + "schema": { + "$ref": "#\/definitions\/fileList" + } + } + }, + "x-appwrite": { + "method": "listFiles", + "group": "files", + "weight": 214, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/list-files.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/list-files.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, signature, mimeType, sizeOriginal, chunksTotal, chunksUploaded", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create file", + "operationId": "storageCreateFile", + "consumes": [ + "multipart\/form-data" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Create a new file. Before using this route, you should create a new bucket resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/storage#storageCreateBucket) API or directly from your Appwrite console.\n\nLarger files should be uploaded using multiple requests with the [content-range](https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Headers\/Content-Range) header to send a partial request with a maximum supported chunk of `5MB`. The `content-range` header values should always be in bytes.\n\nWhen the first request is sent, the server will return the **File** object, and the subsequent part request must include the file's **id** in `x-appwrite-id` header to allow the server to know that the partial upload is for the existing file and not for a new one.\n\nIf you're creating a new file using one of the Appwrite SDKs, all the chunking logic will be managed by the SDK internally.\n", + "responses": { + "201": { + "description": "File", + "schema": { + "$ref": "#\/definitions\/file" + } + } + }, + "x-appwrite": { + "method": "createFile", + "group": "files", + "weight": 213, + "cookies": false, + "type": "upload", + "deprecated": false, + "demo": "storage\/create-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/create-file.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId},chunkId:{chunkId}", + "scope": "files.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "required": true, + "x-upload-id": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "formData" + }, + { + "name": "file", + "description": "Binary file. Appwrite SDKs provide helpers to handle file input. [Learn about file input](https:\/\/appwrite.io\/docs\/products\/storage\/upload-download#input-file).", + "required": true, + "type": "file", + "in": "formData" + }, + { + "name": "permissions", + "description": "An array of permission strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "x-example": "[\"read(\"any\")\"]", + "in": "formData" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}": { + "get": { + "summary": "Get file", + "operationId": "storageGetFile", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Get a file by its unique ID. This endpoint response returns a JSON object with the file metadata.", + "responses": { + "200": { + "description": "File", + "schema": { + "$ref": "#\/definitions\/file" + } + } + }, + "x-appwrite": { + "method": "getFile", + "group": "files", + "weight": 215, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/get-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update file", + "operationId": "storageUpdateFile", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Update a file by its unique ID. Only users with write permissions have access to update this resource.", + "responses": { + "200": { + "description": "File", + "schema": { + "$ref": "#\/definitions\/file" + } + } + }, + "x-appwrite": { + "method": "updateFile", + "group": "files", + "weight": 220, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/update-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/update-file.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "files.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the file", + "default": null, + "x-example": "<NAME>" + }, + "permissions": { + "type": "array", + "description": "An array of permission string. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + } + } + } + ] + }, + "delete": { + "summary": "Delete file", + "operationId": "storageDeleteFile", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "storage" + ], + "description": "Delete a file by its unique ID. Only users with write permissions have access to delete this resource.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteFile", + "group": "files", + "weight": 221, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/delete-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/delete-file.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "files.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/download": { + "get": { + "summary": "Get file for download", + "operationId": "storageGetFileDownload", + "consumes": [], + "produces": [ + "*\/*" + ], + "tags": [ + "storage" + ], + "description": "Get a file content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "responses": { + "200": { + "description": "File", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getFileDownload", + "group": "files", + "weight": 217, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "storage\/get-file-download.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file-download.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + }, + { + "name": "token", + "description": "File token for accessing this file.", + "required": false, + "type": "string", + "x-example": "<TOKEN>", + "default": "", + "in": "query" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/preview": { + "get": { + "summary": "Get file preview", + "operationId": "storageGetFilePreview", + "consumes": [], + "produces": [ + "image\/*" + ], + "tags": [ + "storage" + ], + "description": "Get a file preview image. Currently, this method supports preview for image files (jpg, png, and gif), other supported formats, like pdf, docs, slides, and spreadsheets, will return the file icon image. You can also pass query string arguments for cutting and resizing your preview image. Preview is supported only for image files smaller than 10MB.", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getFilePreview", + "group": "files", + "weight": 216, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "storage\/get-file-preview.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file-preview.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File ID", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + }, + { + "name": "width", + "description": "Resize preview image width, Pass an integer between 0 to 4000.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0, + "in": "query" + }, + { + "name": "height", + "description": "Resize preview image height, Pass an integer between 0 to 4000.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0, + "in": "query" + }, + { + "name": "gravity", + "description": "Image crop gravity. Can be one of center,top-left,top,top-right,left,right,bottom-left,bottom,bottom-right", + "required": false, + "type": "string", + "x-example": "center", + "enum": [ + "center", + "top-left", + "top", + "top-right", + "left", + "right", + "bottom-left", + "bottom", + "bottom-right" + ], + "x-enum-name": "ImageGravity", + "x-enum-keys": [], + "default": "center", + "in": "query" + }, + { + "name": "quality", + "description": "Preview image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1, + "in": "query" + }, + { + "name": "borderWidth", + "description": "Preview image border in pixels. Pass an integer between 0 to 100. Defaults to 0.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0, + "in": "query" + }, + { + "name": "borderColor", + "description": "Preview image border color. Use a valid HEX color, no # is needed for prefix.", + "required": false, + "type": "string", + "default": "", + "in": "query" + }, + { + "name": "borderRadius", + "description": "Preview image border radius in pixels. Pass an integer between 0 to 4000.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0, + "in": "query" + }, + { + "name": "opacity", + "description": "Preview image opacity. Only works with images having an alpha channel (like png). Pass a number between 0 to 1.", + "required": false, + "type": "number", + "format": "float", + "x-example": 0, + "default": 1, + "in": "query" + }, + { + "name": "rotation", + "description": "Preview image rotation in degrees. Pass an integer between -360 and 360.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": -360, + "default": 0, + "in": "query" + }, + { + "name": "background", + "description": "Preview image background color. Only works with transparent images (png). Use a valid HEX color, no # is needed for prefix.", + "required": false, + "type": "string", + "default": "", + "in": "query" + }, + { + "name": "output", + "description": "Output format type (jpeg, jpg, png, gif and webp).", + "required": false, + "type": "string", + "x-example": "jpg", + "enum": [ + "jpg", + "jpeg", + "png", + "webp", + "heic", + "avif", + "gif" + ], + "x-enum-name": "ImageFormat", + "x-enum-keys": [], + "default": "", + "in": "query" + }, + { + "name": "token", + "description": "File token for accessing this file.", + "required": false, + "type": "string", + "x-example": "<TOKEN>", + "default": "", + "in": "query" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/view": { + "get": { + "summary": "Get file for view", + "operationId": "storageGetFileView", + "consumes": [], + "produces": [ + "*\/*" + ], + "tags": [ + "storage" + ], + "description": "Get a file content by its unique ID. This endpoint is similar to the download method but returns with no 'Content-Disposition: attachment' header.", + "responses": { + "200": { + "description": "File", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getFileView", + "group": "files", + "weight": 218, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "storage\/get-file-view.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file-view.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + }, + { + "name": "token", + "description": "File token for accessing this file.", + "required": false, + "type": "string", + "x-example": "<TOKEN>", + "default": "", + "in": "query" + } + ] + } + }, + "\/teams": { + "get": { + "summary": "List teams", + "operationId": "teamsList", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Get a list of all the teams in which the current user is a member. You can use the parameters to filter your results.", + "responses": { + "200": { + "description": "Teams List", + "schema": { + "$ref": "#\/definitions\/teamList" + } + } + }, + "x-appwrite": { + "method": "list", + "group": "teams", + "weight": 225, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/list-teams.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, total, billingPlan", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create team", + "operationId": "teamsCreate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Create a new team. The user who creates the team will automatically be assigned as the owner of the team. Only the users with the owner role can invite new members, add new owners and delete or update the team.", + "responses": { + "201": { + "description": "Team", + "schema": { + "$ref": "#\/definitions\/team" + } + } + }, + "x-appwrite": { + "method": "create", + "group": "teams", + "weight": 224, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/create-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "teamId": { + "type": "string", + "description": "Team ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<TEAM_ID>" + }, + "name": { + "type": "string", + "description": "Team name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "roles": { + "type": "array", + "description": "Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.", + "default": [ + "owner" + ], + "x-example": null, + "items": { + "type": "string" + } + } + }, + "required": [ + "teamId", + "name" + ] + } + } + ] + } + }, + "\/teams\/{teamId}": { + "get": { + "summary": "Get team", + "operationId": "teamsGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Get a team by its ID. All team members have read access for this resource.", + "responses": { + "200": { + "description": "Team", + "schema": { + "$ref": "#\/definitions\/team" + } + } + }, + "x-appwrite": { + "method": "get", + "group": "teams", + "weight": 226, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update name", + "operationId": "teamsUpdateName", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Update the team's name by its unique ID.", + "responses": { + "200": { + "description": "Team", + "schema": { + "$ref": "#\/definitions\/team" + } + } + }, + "x-appwrite": { + "method": "updateName", + "group": "teams", + "weight": 228, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-name.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-name.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "New team name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + } + }, + "required": [ + "name" + ] + } + } + ] + }, + "delete": { + "summary": "Delete team", + "operationId": "teamsDelete", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "teams" + ], + "description": "Delete a team using its ID. Only team members with the owner role can delete the team.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "teams", + "weight": 230, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/delete-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + } + ] + } + }, + "\/teams\/{teamId}\/memberships": { + "get": { + "summary": "List team memberships", + "operationId": "teamsListMemberships", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Use this endpoint to list a team's members using the team's ID. All team members have read access to this endpoint. Hide sensitive attributes from the response by toggling membership privacy in the Console.", + "responses": { + "200": { + "description": "Memberships List", + "schema": { + "$ref": "#\/definitions\/membershipList" + } + } + }, + "x-appwrite": { + "method": "listMemberships", + "group": "memberships", + "weight": 232, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/list-memberships.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/list-team-members.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create team membership", + "operationId": "teamsCreateMembership", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Invite a new member to join your team. Provide an ID for existing users, or invite unregistered users using an email or phone number. If initiated from a Client SDK, Appwrite will send an email or sms with a link to join the team to the invited user, and an account will be created for them if one doesn't exist. If initiated from a Server SDK, the new member will be added automatically to the team.\n\nYou only need to provide one of a user ID, email, or phone number. Appwrite will prioritize accepting the user ID > email > phone number if you provide more than one of these parameters.\n\nUse the `url` parameter to redirect the user from the invitation email to your app. After the user is redirected, use the [Update Team Membership Status](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/teams#updateMembershipStatus) endpoint to allow the user to accept the invitation to the team. \n\nPlease note that to avoid a [Redirect Attack](https:\/\/github.com\/OWASP\/CheatSheetSeries\/blob\/master\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) Appwrite will accept the only redirect URLs under the domains you have added as a platform on the Appwrite Console.\n", + "responses": { + "201": { + "description": "Membership", + "schema": { + "$ref": "#\/definitions\/membership" + } + } + }, + "x-appwrite": { + "method": "createMembership", + "group": "memberships", + "weight": 231, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/create-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/create-team-membership.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "Email of the new team member.", + "default": "", + "x-example": "email@example.com" + }, + "userId": { + "type": "string", + "description": "ID of the user to be added to a team.", + "default": "", + "x-example": "<USER_ID>" + }, + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "default": "", + "x-example": "+12065550100" + }, + "roles": { + "type": "array", + "description": "Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "default": "", + "x-example": "https:\/\/example.com" + }, + "name": { + "type": "string", + "description": "Name of the new team member. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "roles" + ] + } + } + ] + } + }, + "\/teams\/{teamId}\/memberships\/{membershipId}": { + "get": { + "summary": "Get team membership", + "operationId": "teamsGetMembership", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Get a team member by the membership unique id. All team members have read access for this resource. Hide sensitive attributes from the response by toggling membership privacy in the Console.", + "responses": { + "200": { + "description": "Membership", + "schema": { + "$ref": "#\/definitions\/membership" + } + } + }, + "x-appwrite": { + "method": "getMembership", + "group": "memberships", + "weight": 233, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/get-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team-member.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "type": "string", + "x-example": "<MEMBERSHIP_ID>", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update membership", + "operationId": "teamsUpdateMembership", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Modify the roles of a team member. Only team members with the owner role have access to this endpoint. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions).\n", + "responses": { + "200": { + "description": "Membership", + "schema": { + "$ref": "#\/definitions\/membership" + } + } + }, + "x-appwrite": { + "method": "updateMembership", + "group": "memberships", + "weight": 234, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-membership.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "type": "string", + "x-example": "<MEMBERSHIP_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "roles": { + "type": "array", + "description": "An array of strings. Use this param to set the user's roles in the team. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + } + }, + "required": [ + "roles" + ] + } + } + ] + }, + "delete": { + "summary": "Delete team membership", + "operationId": "teamsDeleteMembership", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "teams" + ], + "description": "This endpoint allows a user to leave a team or for a team owner to delete the membership of any other team member. You can also use this endpoint to delete a user membership even if it is not accepted.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteMembership", + "group": "memberships", + "weight": 236, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/delete-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/delete-team-membership.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "type": "string", + "x-example": "<MEMBERSHIP_ID>", + "in": "path" + } + ] + } + }, + "\/teams\/{teamId}\/memberships\/{membershipId}\/status": { + "patch": { + "summary": "Update team membership status", + "operationId": "teamsUpdateMembershipStatus", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Use this endpoint to allow a user to accept an invitation to join a team after being redirected back to your app from the invitation email received by the user.\n\nIf the request is successful, a session for the user is automatically created.\n", + "responses": { + "200": { + "description": "Membership", + "schema": { + "$ref": "#\/definitions\/membership" + } + } + }, + "x-appwrite": { + "method": "updateMembershipStatus", + "group": "memberships", + "weight": 235, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-membership-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-membership-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "type": "string", + "x-example": "<MEMBERSHIP_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Secret key.", + "default": null, + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + ] + } + }, + "\/teams\/{teamId}\/prefs": { + "get": { + "summary": "Get team preferences", + "operationId": "teamsGetPrefs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Get the team's shared preferences by its unique ID. If a preference doesn't need to be shared by all team members, prefer storing them in [user preferences](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#getPrefs).", + "responses": { + "200": { + "description": "Preferences", + "schema": { + "$ref": "#\/definitions\/preferences" + } + } + }, + "x-appwrite": { + "method": "getPrefs", + "group": "teams", + "weight": 227, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/get-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update preferences", + "operationId": "teamsUpdatePrefs", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Update the team's preferences by its unique ID. The object you pass is stored as is and replaces any previous value. The maximum allowed prefs size is 64kB and throws an error if exceeded.", + "responses": { + "200": { + "description": "Preferences", + "schema": { + "$ref": "#\/definitions\/preferences" + } + } + }, + "x-appwrite": { + "method": "updatePrefs", + "group": "teams", + "weight": 229, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "prefs": { + "type": "object", + "description": "Prefs key-value JSON object.", + "default": {}, + "x-example": "{}" + } + }, + "required": [ + "prefs" + ] + } + } + ] + } + } + }, + "tags": [ + { + "name": "account", + "description": "The Account service allows you to authenticate and manage a user account." + }, + { + "name": "avatars", + "description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars." + }, + { + "name": "databases", + "description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents" + }, + { + "name": "locale", + "description": "The Locale service allows you to customize your app based on your users' location." + }, + { + "name": "health", + "description": "The Health service allows you to both validate and monitor your Appwrite server's health." + }, + { + "name": "projects", + "description": "The Project service allows you to manage all the projects in your Appwrite server." + }, + { + "name": "project", + "description": "The Project service allows you to manage all the projects in your Appwrite server." + }, + { + "name": "storage", + "description": "The Storage service allows you to manage your project files." + }, + { + "name": "teams", + "description": "The Teams service allows you to group users of your project and to enable them to share read and write access to your project resources" + }, + { + "name": "users", + "description": "The Users service allows you to manage your project users." + }, + { + "name": "sites", + "description": "The Sites Service allows you view, create and manage your web applications." + }, + { + "name": "functions", + "description": "The Functions Service allows you view, create and manage your Cloud Functions." + }, + { + "name": "proxy", + "description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration." + }, + { + "name": "graphql", + "description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL." + }, + { + "name": "console", + "description": "The Console service allows you to interact with console relevant informations." + }, + { + "name": "migrations", + "description": "The Migrations service allows you to migrate third-party data to your Appwrite project." + }, + { + "name": "messaging", + "description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.)." + } + ], + "definitions": { + "any": { + "description": "Any", + "type": "object", + "additionalProperties": true + }, + "documentList": { + "description": "Documents List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of documents documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "documents": { + "type": "array", + "description": "List of documents.", + "items": { + "type": "object", + "$ref": "#\/definitions\/document" + }, + "x-example": "" + } + }, + "required": [ + "total", + "documents" + ] + }, + "sessionList": { + "description": "Sessions List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of sessions documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "sessions": { + "type": "array", + "description": "List of sessions.", + "items": { + "type": "object", + "$ref": "#\/definitions\/session" + }, + "x-example": "" + } + }, + "required": [ + "total", + "sessions" + ] + }, + "identityList": { + "description": "Identities List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of identities documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "identities": { + "type": "array", + "description": "List of identities.", + "items": { + "type": "object", + "$ref": "#\/definitions\/identity" + }, + "x-example": "" + } + }, + "required": [ + "total", + "identities" + ] + }, + "logList": { + "description": "Logs List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of logs documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "logs": { + "type": "array", + "description": "List of logs.", + "items": { + "type": "object", + "$ref": "#\/definitions\/log" + }, + "x-example": "" + } + }, + "required": [ + "total", + "logs" + ] + }, + "fileList": { + "description": "Files List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of files documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "files": { + "type": "array", + "description": "List of files.", + "items": { + "type": "object", + "$ref": "#\/definitions\/file" + }, + "x-example": "" + } + }, + "required": [ + "total", + "files" + ] + }, + "teamList": { + "description": "Teams List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of teams documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "teams": { + "type": "array", + "description": "List of teams.", + "items": { + "type": "object", + "$ref": "#\/definitions\/team" + }, + "x-example": "" + } + }, + "required": [ + "total", + "teams" + ] + }, + "membershipList": { + "description": "Memberships List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of memberships documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "memberships": { + "type": "array", + "description": "List of memberships.", + "items": { + "type": "object", + "$ref": "#\/definitions\/membership" + }, + "x-example": "" + } + }, + "required": [ + "total", + "memberships" + ] + }, + "executionList": { + "description": "Executions List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of executions documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "executions": { + "type": "array", + "description": "List of executions.", + "items": { + "type": "object", + "$ref": "#\/definitions\/execution" + }, + "x-example": "" + } + }, + "required": [ + "total", + "executions" + ] + }, + "countryList": { + "description": "Countries List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of countries documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "countries": { + "type": "array", + "description": "List of countries.", + "items": { + "type": "object", + "$ref": "#\/definitions\/country" + }, + "x-example": "" + } + }, + "required": [ + "total", + "countries" + ] + }, + "continentList": { + "description": "Continents List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of continents documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "continents": { + "type": "array", + "description": "List of continents.", + "items": { + "type": "object", + "$ref": "#\/definitions\/continent" + }, + "x-example": "" + } + }, + "required": [ + "total", + "continents" + ] + }, + "languageList": { + "description": "Languages List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of languages documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "languages": { + "type": "array", + "description": "List of languages.", + "items": { + "type": "object", + "$ref": "#\/definitions\/language" + }, + "x-example": "" + } + }, + "required": [ + "total", + "languages" + ] + }, + "currencyList": { + "description": "Currencies List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of currencies documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "currencies": { + "type": "array", + "description": "List of currencies.", + "items": { + "type": "object", + "$ref": "#\/definitions\/currency" + }, + "x-example": "" + } + }, + "required": [ + "total", + "currencies" + ] + }, + "phoneList": { + "description": "Phones List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of phones documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "phones": { + "type": "array", + "description": "List of phones.", + "items": { + "type": "object", + "$ref": "#\/definitions\/phone" + }, + "x-example": "" + } + }, + "required": [ + "total", + "phones" + ] + }, + "localeCodeList": { + "description": "Locale codes list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of localeCodes documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "localeCodes": { + "type": "array", + "description": "List of localeCodes.", + "items": { + "type": "object", + "$ref": "#\/definitions\/localeCode" + }, + "x-example": "" + } + }, + "required": [ + "total", + "localeCodes" + ] + }, + "document": { + "description": "Document", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Document ID.", + "x-example": "5e5ea5c16897e" + }, + "$sequence": { + "type": "integer", + "description": "Document automatically incrementing ID.", + "x-example": 1, + "format": "int32" + }, + "$collectionId": { + "type": "string", + "description": "Collection ID.", + "x-example": "5e5ea5c15117e" + }, + "$databaseId": { + "type": "string", + "description": "Database ID.", + "x-example": "5e5ea5c15117e" + }, + "$createdAt": { + "type": "string", + "description": "Document creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Document update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Document permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + } + }, + "additionalProperties": true, + "required": [ + "$id", + "$sequence", + "$collectionId", + "$databaseId", + "$createdAt", + "$updatedAt", + "$permissions" + ] + }, + "log": { + "description": "Log", + "type": "object", + "properties": { + "event": { + "type": "string", + "description": "Event name.", + "x-example": "account.sessions.create" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "610fc2f985ee0" + }, + "userEmail": { + "type": "string", + "description": "User Email.", + "x-example": "john@appwrite.io" + }, + "userName": { + "type": "string", + "description": "User Name.", + "x-example": "John Doe" + }, + "mode": { + "type": "string", + "description": "API mode when event triggered.", + "x-example": "admin" + }, + "ip": { + "type": "string", + "description": "IP session in use when the session was created.", + "x-example": "127.0.0.1" + }, + "time": { + "type": "string", + "description": "Log creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "osCode": { + "type": "string", + "description": "Operating system code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/os.json).", + "x-example": "Mac" + }, + "osName": { + "type": "string", + "description": "Operating system name.", + "x-example": "Mac" + }, + "osVersion": { + "type": "string", + "description": "Operating system version.", + "x-example": "Mac" + }, + "clientType": { + "type": "string", + "description": "Client type.", + "x-example": "browser" + }, + "clientCode": { + "type": "string", + "description": "Client code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/clients.json).", + "x-example": "CM" + }, + "clientName": { + "type": "string", + "description": "Client name.", + "x-example": "Chrome Mobile iOS" + }, + "clientVersion": { + "type": "string", + "description": "Client version.", + "x-example": "84.0" + }, + "clientEngine": { + "type": "string", + "description": "Client engine name.", + "x-example": "WebKit" + }, + "clientEngineVersion": { + "type": "string", + "description": "Client engine name.", + "x-example": "605.1.15" + }, + "deviceName": { + "type": "string", + "description": "Device name.", + "x-example": "smartphone" + }, + "deviceBrand": { + "type": "string", + "description": "Device brand name.", + "x-example": "Google" + }, + "deviceModel": { + "type": "string", + "description": "Device model name.", + "x-example": "Nexus 5" + }, + "countryCode": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + }, + "countryName": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + } + }, + "required": [ + "event", + "userId", + "userEmail", + "userName", + "mode", + "ip", + "time", + "osCode", + "osName", + "osVersion", + "clientType", + "clientCode", + "clientName", + "clientVersion", + "clientEngine", + "clientEngineVersion", + "deviceName", + "deviceBrand", + "deviceModel", + "countryCode", + "countryName" + ] + }, + "user": { + "description": "User", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "User creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "User update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "User name.", + "x-example": "John Doe" + }, + "password": { + "type": "string", + "description": "Hashed user password.", + "x-example": "$argon2id$v=19$m=2048,t=4,p=3$aUZjLnliVWRINmFNTWMudg$5S+x+7uA31xFnrHFT47yFwcJeaP0w92L\/4LdgrVRXxE", + "x-nullable": true + }, + "hash": { + "type": "string", + "description": "Password hashing algorithm.", + "x-example": "argon2", + "x-nullable": true + }, + "hashOptions": { + "type": "object", + "description": "Password hashing algorithm configuration.", + "x-example": {}, + "items": { + "x-oneOf": [ + { + "$ref": "#\/definitions\/algoArgon2" + }, + { + "$ref": "#\/definitions\/algoScrypt" + }, + { + "$ref": "#\/definitions\/algoScryptModified" + }, + { + "$ref": "#\/definitions\/algoBcrypt" + }, + { + "$ref": "#\/definitions\/algoPhpass" + }, + { + "$ref": "#\/definitions\/algoSha" + }, + { + "$ref": "#\/definitions\/algoMd5" + } + ] + }, + "x-nullable": true + }, + "registration": { + "type": "string", + "description": "User registration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "boolean", + "description": "User status. Pass `true` for enabled and `false` for disabled.", + "x-example": true + }, + "labels": { + "type": "array", + "description": "Labels for the user.", + "items": { + "type": "string" + }, + "x-example": [ + "vip" + ] + }, + "passwordUpdate": { + "type": "string", + "description": "Password update time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "email": { + "type": "string", + "description": "User email address.", + "x-example": "john@appwrite.io" + }, + "phone": { + "type": "string", + "description": "User phone number in E.164 format.", + "x-example": "+4930901820" + }, + "emailVerification": { + "type": "boolean", + "description": "Email verification status.", + "x-example": true + }, + "phoneVerification": { + "type": "boolean", + "description": "Phone verification status.", + "x-example": true + }, + "mfa": { + "type": "boolean", + "description": "Multi factor authentication status.", + "x-example": true + }, + "prefs": { + "type": "object", + "description": "User preferences as a key-value object", + "x-example": { + "theme": "pink", + "timezone": "UTC" + }, + "items": { + "type": "object", + "$ref": "#\/definitions\/preferences" + } + }, + "targets": { + "type": "array", + "description": "A user-owned message receiver. A single user may have multiple e.g. emails, phones, and a browser. Each target is registered with a single provider.", + "items": { + "type": "object", + "$ref": "#\/definitions\/target" + }, + "x-example": [] + }, + "accessedAt": { + "type": "string", + "description": "Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "registration", + "status", + "labels", + "passwordUpdate", + "email", + "phone", + "emailVerification", + "phoneVerification", + "mfa", + "prefs", + "targets", + "accessedAt" + ] + }, + "algoMd5": { + "description": "AlgoMD5", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "md5" + } + }, + "required": [ + "type" + ] + }, + "algoSha": { + "description": "AlgoSHA", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "sha" + } + }, + "required": [ + "type" + ] + }, + "algoPhpass": { + "description": "AlgoPHPass", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "phpass" + } + }, + "required": [ + "type" + ] + }, + "algoBcrypt": { + "description": "AlgoBcrypt", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "bcrypt" + } + }, + "required": [ + "type" + ] + }, + "algoScrypt": { + "description": "AlgoScrypt", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "scrypt" + }, + "costCpu": { + "type": "integer", + "description": "CPU complexity of computed hash.", + "x-example": 8, + "format": "int32" + }, + "costMemory": { + "type": "integer", + "description": "Memory complexity of computed hash.", + "x-example": 14, + "format": "int32" + }, + "costParallel": { + "type": "integer", + "description": "Parallelization of computed hash.", + "x-example": 1, + "format": "int32" + }, + "length": { + "type": "integer", + "description": "Length used to compute hash.", + "x-example": 64, + "format": "int32" + } + }, + "required": [ + "type", + "costCpu", + "costMemory", + "costParallel", + "length" + ] + }, + "algoScryptModified": { + "description": "AlgoScryptModified", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "scryptMod" + }, + "salt": { + "type": "string", + "description": "Salt used to compute hash.", + "x-example": "UxLMreBr6tYyjQ==" + }, + "saltSeparator": { + "type": "string", + "description": "Separator used to compute hash.", + "x-example": "Bw==" + }, + "signerKey": { + "type": "string", + "description": "Key used to compute hash.", + "x-example": "XyEKE9RcTDeLEsL\/RjwPDBv\/RqDl8fb3gpYEOQaPihbxf1ZAtSOHCjuAAa7Q3oHpCYhXSN9tizHgVOwn6krflQ==" + } + }, + "required": [ + "type", + "salt", + "saltSeparator", + "signerKey" + ] + }, + "algoArgon2": { + "description": "AlgoArgon2", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "argon2" + }, + "memoryCost": { + "type": "integer", + "description": "Memory used to compute hash.", + "x-example": 65536, + "format": "int32" + }, + "timeCost": { + "type": "integer", + "description": "Amount of time consumed to compute hash", + "x-example": 4, + "format": "int32" + }, + "threads": { + "type": "integer", + "description": "Number of threads used to compute hash.", + "x-example": 3, + "format": "int32" + } + }, + "required": [ + "type", + "memoryCost", + "timeCost", + "threads" + ] + }, + "preferences": { + "description": "Preferences", + "type": "object", + "additionalProperties": true + }, + "session": { + "description": "Session", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Session ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Session creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Session update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5bb8c16897e" + }, + "expire": { + "type": "string", + "description": "Session expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "provider": { + "type": "string", + "description": "Session Provider.", + "x-example": "email" + }, + "providerUid": { + "type": "string", + "description": "Session Provider User ID.", + "x-example": "user@example.com" + }, + "providerAccessToken": { + "type": "string", + "description": "Session Provider Access Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + }, + "providerAccessTokenExpiry": { + "type": "string", + "description": "The date of when the access token expires in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "providerRefreshToken": { + "type": "string", + "description": "Session Provider Refresh Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + }, + "ip": { + "type": "string", + "description": "IP in use when the session was created.", + "x-example": "127.0.0.1" + }, + "osCode": { + "type": "string", + "description": "Operating system code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/os.json).", + "x-example": "Mac" + }, + "osName": { + "type": "string", + "description": "Operating system name.", + "x-example": "Mac" + }, + "osVersion": { + "type": "string", + "description": "Operating system version.", + "x-example": "Mac" + }, + "clientType": { + "type": "string", + "description": "Client type.", + "x-example": "browser" + }, + "clientCode": { + "type": "string", + "description": "Client code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/clients.json).", + "x-example": "CM" + }, + "clientName": { + "type": "string", + "description": "Client name.", + "x-example": "Chrome Mobile iOS" + }, + "clientVersion": { + "type": "string", + "description": "Client version.", + "x-example": "84.0" + }, + "clientEngine": { + "type": "string", + "description": "Client engine name.", + "x-example": "WebKit" + }, + "clientEngineVersion": { + "type": "string", + "description": "Client engine name.", + "x-example": "605.1.15" + }, + "deviceName": { + "type": "string", + "description": "Device name.", + "x-example": "smartphone" + }, + "deviceBrand": { + "type": "string", + "description": "Device brand name.", + "x-example": "Google" + }, + "deviceModel": { + "type": "string", + "description": "Device model name.", + "x-example": "Nexus 5" + }, + "countryCode": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + }, + "countryName": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + }, + "current": { + "type": "boolean", + "description": "Returns true if this the current user session.", + "x-example": true + }, + "factors": { + "type": "array", + "description": "Returns a list of active session factors.", + "items": { + "type": "string" + }, + "x-example": [ + "email" + ] + }, + "secret": { + "type": "string", + "description": "Secret used to authenticate the user. Only included if the request was made with an API key", + "x-example": "5e5bb8c16897e" + }, + "mfaUpdatedAt": { + "type": "string", + "description": "Most recent date in ISO 8601 format when the session successfully passed MFA challenge.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "userId", + "expire", + "provider", + "providerUid", + "providerAccessToken", + "providerAccessTokenExpiry", + "providerRefreshToken", + "ip", + "osCode", + "osName", + "osVersion", + "clientType", + "clientCode", + "clientName", + "clientVersion", + "clientEngine", + "clientEngineVersion", + "deviceName", + "deviceBrand", + "deviceModel", + "countryCode", + "countryName", + "current", + "factors", + "secret", + "mfaUpdatedAt" + ] + }, + "identity": { + "description": "Identity", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Identity ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Identity creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Identity update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5bb8c16897e" + }, + "provider": { + "type": "string", + "description": "Identity Provider.", + "x-example": "email" + }, + "providerUid": { + "type": "string", + "description": "ID of the User in the Identity Provider.", + "x-example": "5e5bb8c16897e" + }, + "providerEmail": { + "type": "string", + "description": "Email of the User in the Identity Provider.", + "x-example": "user@example.com" + }, + "providerAccessToken": { + "type": "string", + "description": "Identity Provider Access Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + }, + "providerAccessTokenExpiry": { + "type": "string", + "description": "The date of when the access token expires in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "providerRefreshToken": { + "type": "string", + "description": "Identity Provider Refresh Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "userId", + "provider", + "providerUid", + "providerEmail", + "providerAccessToken", + "providerAccessTokenExpiry", + "providerRefreshToken" + ] + }, + "token": { + "description": "Token", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Token ID.", + "x-example": "bb8ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Token creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c168bb8" + }, + "secret": { + "type": "string", + "description": "Token secret key. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.", + "x-example": "" + }, + "expire": { + "type": "string", + "description": "Token expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "phrase": { + "type": "string", + "description": "Security phrase of a token. Empty if security phrase was not requested when creating a token. It includes randomly generated phrase which is also sent in the external resource such as email.", + "x-example": "Golden Fox" + } + }, + "required": [ + "$id", + "$createdAt", + "userId", + "secret", + "expire", + "phrase" + ] + }, + "jwt": { + "description": "JWT", + "type": "object", + "properties": { + "jwt": { + "type": "string", + "description": "JWT encoded string.", + "x-example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + } + }, + "required": [ + "jwt" + ] + }, + "locale": { + "description": "Locale", + "type": "object", + "properties": { + "ip": { + "type": "string", + "description": "User IP address.", + "x-example": "127.0.0.1" + }, + "countryCode": { + "type": "string", + "description": "Country code in [ISO 3166-1](http:\/\/en.wikipedia.org\/wiki\/ISO_3166-1) two-character format", + "x-example": "US" + }, + "country": { + "type": "string", + "description": "Country name. This field support localization.", + "x-example": "United States" + }, + "continentCode": { + "type": "string", + "description": "Continent code. A two character continent code \"AF\" for Africa, \"AN\" for Antarctica, \"AS\" for Asia, \"EU\" for Europe, \"NA\" for North America, \"OC\" for Oceania, and \"SA\" for South America.", + "x-example": "NA" + }, + "continent": { + "type": "string", + "description": "Continent name. This field support localization.", + "x-example": "North America" + }, + "eu": { + "type": "boolean", + "description": "True if country is part of the European Union.", + "x-example": false + }, + "currency": { + "type": "string", + "description": "Currency code in [ISO 4217-1](http:\/\/en.wikipedia.org\/wiki\/ISO_4217) three-character format", + "x-example": "USD" + } + }, + "required": [ + "ip", + "countryCode", + "country", + "continentCode", + "continent", + "eu", + "currency" + ] + }, + "localeCode": { + "description": "LocaleCode", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Locale codes in [ISO 639-1](https:\/\/en.wikipedia.org\/wiki\/List_of_ISO_639-1_codes)", + "x-example": "en-us" + }, + "name": { + "type": "string", + "description": "Locale name", + "x-example": "US" + } + }, + "required": [ + "code", + "name" + ] + }, + "file": { + "description": "File", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "File ID.", + "x-example": "5e5ea5c16897e" + }, + "bucketId": { + "type": "string", + "description": "Bucket ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "File creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "File update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "File permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + }, + "name": { + "type": "string", + "description": "File name.", + "x-example": "Pink.png" + }, + "signature": { + "type": "string", + "description": "File MD5 signature.", + "x-example": "5d529fd02b544198ae075bd57c1762bb" + }, + "mimeType": { + "type": "string", + "description": "File mime type.", + "x-example": "image\/png" + }, + "sizeOriginal": { + "type": "integer", + "description": "File original size in bytes.", + "x-example": 17890, + "format": "int32" + }, + "chunksTotal": { + "type": "integer", + "description": "Total number of chunks available", + "x-example": 17890, + "format": "int32" + }, + "chunksUploaded": { + "type": "integer", + "description": "Total number of chunks uploaded", + "x-example": 17890, + "format": "int32" + } + }, + "required": [ + "$id", + "bucketId", + "$createdAt", + "$updatedAt", + "$permissions", + "name", + "signature", + "mimeType", + "sizeOriginal", + "chunksTotal", + "chunksUploaded" + ] + }, + "team": { + "description": "Team", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Team ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Team creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Team update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Team name.", + "x-example": "VIP" + }, + "total": { + "type": "integer", + "description": "Total number of team members.", + "x-example": 7, + "format": "int32" + }, + "prefs": { + "type": "object", + "description": "Team preferences as a key-value object", + "x-example": { + "theme": "pink", + "timezone": "UTC" + }, + "items": { + "type": "object", + "$ref": "#\/definitions\/preferences" + } + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "total", + "prefs" + ] + }, + "membership": { + "description": "Membership", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Membership ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Membership creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Membership update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c16897e" + }, + "userName": { + "type": "string", + "description": "User name. Hide this attribute by toggling membership privacy in the Console.", + "x-example": "John Doe" + }, + "userEmail": { + "type": "string", + "description": "User email address. Hide this attribute by toggling membership privacy in the Console.", + "x-example": "john@appwrite.io" + }, + "teamId": { + "type": "string", + "description": "Team ID.", + "x-example": "5e5ea5c16897e" + }, + "teamName": { + "type": "string", + "description": "Team name.", + "x-example": "VIP" + }, + "invited": { + "type": "string", + "description": "Date, the user has been invited to join the team in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "joined": { + "type": "string", + "description": "Date, the user has accepted the invitation to join the team in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "confirm": { + "type": "boolean", + "description": "User confirmation status, true if the user has joined the team or false otherwise.", + "x-example": false + }, + "mfa": { + "type": "boolean", + "description": "Multi factor authentication status, true if the user has MFA enabled or false otherwise. Hide this attribute by toggling membership privacy in the Console.", + "x-example": false + }, + "roles": { + "type": "array", + "description": "User list of roles", + "items": { + "type": "string" + }, + "x-example": [ + "owner" + ] + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "userId", + "userName", + "userEmail", + "teamId", + "teamName", + "invited", + "joined", + "confirm", + "mfa", + "roles" + ] + }, + "execution": { + "description": "Execution", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Execution ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Execution creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Execution upate date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Execution roles.", + "items": { + "type": "string" + }, + "x-example": [ + "any" + ] + }, + "functionId": { + "type": "string", + "description": "Function ID.", + "x-example": "5e5ea6g16897e" + }, + "trigger": { + "type": "string", + "description": "The trigger that caused the function to execute. Possible values can be: `http`, `schedule`, or `event`.", + "x-example": "http" + }, + "status": { + "type": "string", + "description": "The status of the function execution. Possible values can be: `waiting`, `processing`, `completed`, or `failed`.", + "x-example": "processing" + }, + "requestMethod": { + "type": "string", + "description": "HTTP request method type.", + "x-example": "GET" + }, + "requestPath": { + "type": "string", + "description": "HTTP request path and query.", + "x-example": "\/articles?id=5" + }, + "requestHeaders": { + "type": "array", + "description": "HTTP response headers as a key-value object. This will return only whitelisted headers. All headers are returned if execution is created as synchronous.", + "items": { + "type": "object", + "$ref": "#\/definitions\/headers" + }, + "x-example": [ + { + "Content-Type": "application\/json" + } + ] + }, + "responseStatusCode": { + "type": "integer", + "description": "HTTP response status code.", + "x-example": 200, + "format": "int32" + }, + "responseBody": { + "type": "string", + "description": "HTTP response body. This will return empty unless execution is created as synchronous.", + "x-example": "" + }, + "responseHeaders": { + "type": "array", + "description": "HTTP response headers as a key-value object. This will return only whitelisted headers. All headers are returned if execution is created as synchronous.", + "items": { + "type": "object", + "$ref": "#\/definitions\/headers" + }, + "x-example": [ + { + "Content-Type": "application\/json" + } + ] + }, + "logs": { + "type": "string", + "description": "Function logs. Includes the last 4,000 characters. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.", + "x-example": "" + }, + "errors": { + "type": "string", + "description": "Function errors. Includes the last 4,000 characters. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.", + "x-example": "" + }, + "duration": { + "type": "number", + "description": "Resource(function\/site) execution duration in seconds.", + "x-example": 0.4, + "format": "double" + }, + "scheduledAt": { + "type": "string", + "description": "The scheduled time for execution. If left empty, execution will be queued immediately.", + "x-example": "2020-10-15T06:38:00.000+00:00", + "x-nullable": true + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "$permissions", + "functionId", + "trigger", + "status", + "requestMethod", + "requestPath", + "requestHeaders", + "responseStatusCode", + "responseBody", + "responseHeaders", + "logs", + "errors", + "duration" + ] + }, + "country": { + "description": "Country", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + }, + "code": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + } + }, + "required": [ + "name", + "code" + ] + }, + "continent": { + "description": "Continent", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Continent name.", + "x-example": "Europe" + }, + "code": { + "type": "string", + "description": "Continent two letter code.", + "x-example": "EU" + } + }, + "required": [ + "name", + "code" + ] + }, + "language": { + "description": "Language", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Language name.", + "x-example": "Italian" + }, + "code": { + "type": "string", + "description": "Language two-character ISO 639-1 codes.", + "x-example": "it" + }, + "nativeName": { + "type": "string", + "description": "Language native name.", + "x-example": "Italiano" + } + }, + "required": [ + "name", + "code", + "nativeName" + ] + }, + "currency": { + "description": "Currency", + "type": "object", + "properties": { + "symbol": { + "type": "string", + "description": "Currency symbol.", + "x-example": "$" + }, + "name": { + "type": "string", + "description": "Currency name.", + "x-example": "US dollar" + }, + "symbolNative": { + "type": "string", + "description": "Currency native symbol.", + "x-example": "$" + }, + "decimalDigits": { + "type": "integer", + "description": "Number of decimal digits.", + "x-example": 2, + "format": "int32" + }, + "rounding": { + "type": "number", + "description": "Currency digit rounding.", + "x-example": 0, + "format": "double" + }, + "code": { + "type": "string", + "description": "Currency code in [ISO 4217-1](http:\/\/en.wikipedia.org\/wiki\/ISO_4217) three-character format.", + "x-example": "USD" + }, + "namePlural": { + "type": "string", + "description": "Currency plural name", + "x-example": "US dollars" + } + }, + "required": [ + "symbol", + "name", + "symbolNative", + "decimalDigits", + "rounding", + "code", + "namePlural" + ] + }, + "phone": { + "description": "Phone", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Phone code.", + "x-example": "+1" + }, + "countryCode": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + }, + "countryName": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + } + }, + "required": [ + "code", + "countryCode", + "countryName" + ] + }, + "headers": { + "description": "Headers", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Header name.", + "x-example": "Content-Type" + }, + "value": { + "type": "string", + "description": "Header value.", + "x-example": "application\/json" + } + }, + "required": [ + "name", + "value" + ] + }, + "mfaChallenge": { + "description": "MFA Challenge", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Token ID.", + "x-example": "bb8ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Token creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c168bb8" + }, + "expire": { + "type": "string", + "description": "Token expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "userId", + "expire" + ] + }, + "mfaRecoveryCodes": { + "description": "MFA Recovery Codes", + "type": "object", + "properties": { + "recoveryCodes": { + "type": "array", + "description": "Recovery codes.", + "items": { + "type": "string" + }, + "x-example": [ + "a3kf0-s0cl2", + "s0co1-as98s" + ] + } + }, + "required": [ + "recoveryCodes" + ] + }, + "mfaType": { + "description": "MFAType", + "type": "object", + "properties": { + "secret": { + "type": "string", + "description": "Secret token used for TOTP factor.", + "x-example": true + }, + "uri": { + "type": "string", + "description": "URI for authenticator apps.", + "x-example": true + } + }, + "required": [ + "secret", + "uri" + ] + }, + "mfaFactors": { + "description": "MFAFactors", + "type": "object", + "properties": { + "totp": { + "type": "boolean", + "description": "Can TOTP be used for MFA challenge for this account.", + "x-example": true + }, + "phone": { + "type": "boolean", + "description": "Can phone (SMS) be used for MFA challenge for this account.", + "x-example": true + }, + "email": { + "type": "boolean", + "description": "Can email be used for MFA challenge for this account.", + "x-example": true + }, + "recoveryCode": { + "type": "boolean", + "description": "Can recovery code be used for MFA challenge for this account.", + "x-example": true + } + }, + "required": [ + "totp", + "phone", + "email", + "recoveryCode" + ] + }, + "subscriber": { + "description": "Subscriber", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Subscriber ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Subscriber creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Subscriber update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "targetId": { + "type": "string", + "description": "Target ID.", + "x-example": "259125845563242502" + }, + "target": { + "type": "object", + "description": "Target.", + "x-example": { + "$id": "259125845563242502", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "providerType": "email", + "providerId": "259125845563242502", + "name": "ageon-app-email", + "identifier": "random-mail@email.org", + "userId": "5e5ea5c16897e" + }, + "items": { + "type": "object", + "$ref": "#\/definitions\/target" + } + }, + "userId": { + "type": "string", + "description": "Topic ID.", + "x-example": "5e5ea5c16897e" + }, + "userName": { + "type": "string", + "description": "User Name.", + "x-example": "Aegon Targaryen" + }, + "topicId": { + "type": "string", + "description": "Topic ID.", + "x-example": "259125845563242502" + }, + "providerType": { + "type": "string", + "description": "The target provider type. Can be one of the following: `email`, `sms` or `push`.", + "x-example": "email" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "targetId", + "target", + "userId", + "userName", + "topicId", + "providerType" + ] + }, + "target": { + "description": "Target", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Target ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Target creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Target update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Target Name.", + "x-example": "Apple iPhone 12" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "259125845563242502" + }, + "providerId": { + "type": "string", + "description": "Provider ID.", + "x-example": "259125845563242502", + "x-nullable": true + }, + "providerType": { + "type": "string", + "description": "The target provider type. Can be one of the following: `email`, `sms` or `push`.", + "x-example": "email" + }, + "identifier": { + "type": "string", + "description": "The target identifier.", + "x-example": "token" + }, + "expired": { + "type": "boolean", + "description": "Is the target expired.", + "x-example": false + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "userId", + "providerType", + "identifier", + "expired" + ] + } + }, + "externalDocs": { + "description": "Full API docs, specs and tutorials", + "url": "https:\/\/appwrite.io\/docs" + } +} \ No newline at end of file diff --git a/app/config/specs/swagger2-1.8.x-console.json b/app/config/specs/swagger2-1.8.x-console.json new file mode 100644 index 0000000000..333ae6f360 --- /dev/null +++ b/app/config/specs/swagger2-1.8.x-console.json @@ -0,0 +1,44331 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.7.4", + "title": "Appwrite", + "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", + "termsOfService": "https:\/\/appwrite.io\/policy\/terms", + "contact": { + "name": "Appwrite Team", + "url": "https:\/\/appwrite.io\/support", + "email": "team@appwrite.io" + }, + "license": { + "name": "BSD-3-Clause", + "url": "https:\/\/raw.githubusercontent.com\/appwrite\/appwrite\/master\/LICENSE" + } + }, + "host": "cloud.appwrite.io", + "x-host-docs": "<REGION>.cloud.appwrite.io", + "basePath": "\/v1", + "schemes": [ + "https" + ], + "consumes": [ + "application\/json", + "multipart\/form-data" + ], + "produces": [ + "application\/json" + ], + "securityDefinitions": { + "Project": { + "type": "apiKey", + "name": "X-Appwrite-Project", + "description": "Your project ID", + "in": "header", + "x-appwrite": { + "demo": "<YOUR_PROJECT_ID>" + } + }, + "Key": { + "type": "apiKey", + "name": "X-Appwrite-Key", + "description": "Your secret API key", + "in": "header", + "x-appwrite": { + "demo": "<YOUR_API_KEY>" + } + }, + "JWT": { + "type": "apiKey", + "name": "X-Appwrite-JWT", + "description": "Your secret JSON Web Token", + "in": "header", + "x-appwrite": { + "demo": "<YOUR_JWT>" + } + }, + "Locale": { + "type": "apiKey", + "name": "X-Appwrite-Locale", + "description": "", + "in": "header", + "x-appwrite": { + "demo": "en" + } + }, + "Mode": { + "type": "apiKey", + "name": "X-Appwrite-Mode", + "description": "", + "in": "header", + "x-appwrite": { + "demo": "" + } + } + }, + "paths": { + "\/account": { + "get": { + "summary": "Get account", + "operationId": "accountGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get the currently logged in user.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "get", + "group": "account", + "weight": 10, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + }, + "post": { + "summary": "Create account", + "operationId": "accountCreate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to allow a new user to register a new account in your project. After the user registration completes successfully, you can use the [\/account\/verfication](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createVerification) route to start verifying the user email address. To allow the new user to login to their new account, you need to create a new [account session](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createEmailSession).", + "responses": { + "201": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "create", + "group": "account", + "weight": 9, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "New user password. Must be between 8 and 256 chars.", + "default": null, + "x-example": null + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + ] + }, + "delete": { + "summary": "Delete account", + "operationId": "accountDelete", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "account" + ], + "description": "Delete the currently logged in user.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "account", + "weight": 11, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ] + } + }, + "\/account\/email": { + "patch": { + "summary": "Update email", + "operationId": "accountUpdateEmail", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Update currently logged in user account email address. After changing user address, the user confirmation status will get reset. A new confirmation email is not sent automatically however you can use the send confirmation email endpoint again to send the confirmation email. For security measures, user password is required to complete this request.\nThis endpoint can also be used to convert an anonymous account to a normal one, by passing an email address and a new password.\n", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateEmail", + "group": "account", + "weight": 35, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-email.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password. Must be at least 8 chars.", + "default": null, + "x-example": "password" + } + }, + "required": [ + "email", + "password" + ] + } + } + ] + } + }, + "\/account\/identities": { + "get": { + "summary": "List identities", + "operationId": "accountListIdentities", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get the list of identities for the currently logged in user.", + "responses": { + "200": { + "description": "Identities List", + "schema": { + "$ref": "#\/definitions\/identityList" + } + } + }, + "x-appwrite": { + "method": "listIdentities", + "group": "identities", + "weight": 58, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-identities.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-identities.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, provider, providerUid, providerEmail, providerAccessTokenExpiry", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/account\/identities\/{identityId}": { + "delete": { + "summary": "Delete identity", + "operationId": "accountDeleteIdentity", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "account" + ], + "description": "Delete an identity by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteIdentity", + "group": "identities", + "weight": 59, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-identity.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-identity.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "identityId", + "description": "Identity ID.", + "required": true, + "type": "string", + "x-example": "<IDENTITY_ID>", + "in": "path" + } + ] + } + }, + "\/account\/jwts": { + "post": { + "summary": "Create JWT", + "operationId": "accountCreateJWT", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to create a JSON Web Token. You can use the resulting JWT to authenticate on behalf of the current user when working with the Appwrite server-side API and SDKs. The JWT secret is valid for 15 minutes from its creation and will be invalid if the user will logout in that time frame.", + "responses": { + "201": { + "description": "JWT", + "schema": { + "$ref": "#\/definitions\/jwt" + } + } + }, + "x-appwrite": { + "method": "createJWT", + "group": "tokens", + "weight": 30, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-j-w-t.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-jwt.md", + "rate-limit": 100, + "rate-time": 3600, + "rate-key": "url:{url},userId:{userId}", + "scope": "account", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ] + } + }, + "\/account\/logs": { + "get": { + "summary": "List logs", + "operationId": "accountListLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get the list of latest security activity logs for the currently logged in user. Each log returns user IP address, location and date and time of log.", + "responses": { + "200": { + "description": "Logs List", + "schema": { + "$ref": "#\/definitions\/logList" + } + } + }, + "x-appwrite": { + "method": "listLogs", + "group": "logs", + "weight": 32, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/account\/mfa": { + "patch": { + "summary": "Update MFA", + "operationId": "accountUpdateMFA", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Enable or disable MFA on an account.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateMFA", + "group": "mfa", + "weight": 45, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-m-f-a.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "mfa": { + "type": "boolean", + "description": "Enable or disable MFA.", + "default": null, + "x-example": false + } + }, + "required": [ + "mfa" + ] + } + } + ] + } + }, + "\/account\/mfa\/authenticators\/{type}": { + "post": { + "summary": "Create authenticator", + "operationId": "accountCreateMfaAuthenticator", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Add an authenticator app to be used as an MFA factor. Verify the authenticator using the [verify authenticator](\/docs\/references\/cloud\/client-web\/account#updateMfaAuthenticator) method.", + "responses": { + "200": { + "description": "MFAType", + "schema": { + "$ref": "#\/definitions\/mfaType" + } + } + }, + "x-appwrite": { + "method": "createMfaAuthenticator", + "group": "mfa", + "weight": 47, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "type", + "description": "Type of authenticator. Must be `totp`", + "required": true, + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [], + "in": "path" + } + ] + }, + "put": { + "summary": "Update authenticator (confirmation)", + "operationId": "accountUpdateMfaAuthenticator", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Verify an authenticator app after adding it using the [add authenticator](\/docs\/references\/cloud\/client-web\/account#createMfaAuthenticator) method.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateMfaAuthenticator", + "group": "mfa", + "weight": 48, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "type", + "description": "Type of authenticator.", + "required": true, + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [], + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "otp": { + "type": "string", + "description": "Valid verification token.", + "default": null, + "x-example": "<OTP>" + } + }, + "required": [ + "otp" + ] + } + } + ] + }, + "delete": { + "summary": "Delete authenticator", + "operationId": "accountDeleteMfaAuthenticator", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "account" + ], + "description": "Delete an authenticator for a user by ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteMfaAuthenticator", + "group": "mfa", + "weight": 52, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "type", + "description": "Type of authenticator.", + "required": true, + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [], + "in": "path" + } + ] + } + }, + "\/account\/mfa\/challenge": { + "post": { + "summary": "Create MFA challenge", + "operationId": "accountCreateMfaChallenge", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Begin the process of MFA verification after sign-in. Finish the flow with [updateMfaChallenge](\/docs\/references\/cloud\/client-web\/account#updateMfaChallenge) method.", + "responses": { + "201": { + "description": "MFA Challenge", + "schema": { + "$ref": "#\/definitions\/mfaChallenge" + } + } + }, + "x-appwrite": { + "method": "createMfaChallenge", + "group": "mfa", + "weight": 53, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-mfa-challenge.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-mfa-challenge.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{userId}", + "scope": "account", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "factor": { + "type": "string", + "description": "Factor used for verification. Must be one of following: `email`, `phone`, `totp`, `recoveryCode`.", + "default": null, + "x-example": "email", + "enum": [ + "email", + "phone", + "totp", + "recoverycode" + ], + "x-enum-name": "AuthenticationFactor", + "x-enum-keys": [] + } + }, + "required": [ + "factor" + ] + } + } + ] + }, + "put": { + "summary": "Update MFA challenge (confirmation)", + "operationId": "accountUpdateMfaChallenge", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Complete the MFA challenge by providing the one-time password. Finish the process of MFA verification by providing the one-time password. To begin the flow, use [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method.", + "responses": { + "200": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "updateMfaChallenge", + "group": "mfa", + "weight": 54, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-mfa-challenge.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa-challenge.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},challengeId:{param-challengeId}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "challengeId": { + "type": "string", + "description": "ID of the challenge.", + "default": null, + "x-example": "<CHALLENGE_ID>" + }, + "otp": { + "type": "string", + "description": "Valid verification token.", + "default": null, + "x-example": "<OTP>" + } + }, + "required": [ + "challengeId", + "otp" + ] + } + } + ] + } + }, + "\/account\/mfa\/factors": { + "get": { + "summary": "List factors", + "operationId": "accountListMfaFactors", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "List the factors available on the account to be used as a MFA challange.", + "responses": { + "200": { + "description": "MFAFactors", + "schema": { + "$ref": "#\/definitions\/mfaFactors" + } + } + }, + "x-appwrite": { + "method": "listMfaFactors", + "group": "mfa", + "weight": 46, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-mfa-factors.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-mfa-factors.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + } + }, + "\/account\/mfa\/recovery-codes": { + "get": { + "summary": "List MFA recovery codes", + "operationId": "accountGetMfaRecoveryCodes", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get recovery codes that can be used as backup for MFA flow. Before getting codes, they must be generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method. An OTP challenge is required to read recovery codes.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "schema": { + "$ref": "#\/definitions\/mfaRecoveryCodes" + } + } + }, + "x-appwrite": { + "method": "getMfaRecoveryCodes", + "group": "mfa", + "weight": 51, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + }, + "post": { + "summary": "Create MFA recovery codes", + "operationId": "accountCreateMfaRecoveryCodes", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Generate recovery codes as backup for MFA flow. It's recommended to generate and show then immediately after user successfully adds their authehticator. Recovery codes can be used as a MFA verification type in [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method.", + "responses": { + "201": { + "description": "MFA Recovery Codes", + "schema": { + "$ref": "#\/definitions\/mfaRecoveryCodes" + } + } + }, + "x-appwrite": { + "method": "createMfaRecoveryCodes", + "group": "mfa", + "weight": 49, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + }, + "patch": { + "summary": "Update MFA recovery codes (regenerate)", + "operationId": "accountUpdateMfaRecoveryCodes", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Regenerate recovery codes that can be used as backup for MFA flow. Before regenerating codes, they must be first generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method. An OTP challenge is required to regenreate recovery codes.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "schema": { + "$ref": "#\/definitions\/mfaRecoveryCodes" + } + } + }, + "x-appwrite": { + "method": "updateMfaRecoveryCodes", + "group": "mfa", + "weight": 50, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + } + }, + "\/account\/name": { + "patch": { + "summary": "Update name", + "operationId": "accountUpdateName", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Update currently logged in user account name.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateName", + "group": "account", + "weight": 33, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-name.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-name.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + } + }, + "required": [ + "name" + ] + } + } + ] + } + }, + "\/account\/password": { + "patch": { + "summary": "Update password", + "operationId": "accountUpdatePassword", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Update currently logged in user password. For validation, user is required to pass in the new password, and the old password. For users created with OAuth, Team Invites and Magic URL, oldPassword is optional.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updatePassword", + "group": "account", + "weight": 34, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-password.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-password.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "password": { + "type": "string", + "description": "New user password. Must be at least 8 chars.", + "default": null, + "x-example": null + }, + "oldPassword": { + "type": "string", + "description": "Current user password. Must be at least 8 chars.", + "default": "", + "x-example": "password" + } + }, + "required": [ + "password" + ] + } + } + ] + } + }, + "\/account\/phone": { + "patch": { + "summary": "Update phone", + "operationId": "accountUpdatePhone", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Update the currently logged in user's phone number. After updating the phone number, the phone verification status will be reset. A confirmation SMS is not sent automatically, however you can use the [POST \/account\/verification\/phone](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createPhoneVerification) endpoint to send a confirmation SMS.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updatePhone", + "group": "account", + "weight": 36, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-phone.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-phone.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "default": null, + "x-example": "+12065550100" + }, + "password": { + "type": "string", + "description": "User password. Must be at least 8 chars.", + "default": null, + "x-example": "password" + } + }, + "required": [ + "phone", + "password" + ] + } + } + ] + } + }, + "\/account\/prefs": { + "get": { + "summary": "Get account preferences", + "operationId": "accountGetPrefs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get the preferences as a key-value object for the currently logged in user.", + "responses": { + "200": { + "description": "Preferences", + "schema": { + "$ref": "#\/definitions\/preferences" + } + } + }, + "x-appwrite": { + "method": "getPrefs", + "group": "account", + "weight": 31, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + }, + "patch": { + "summary": "Update preferences", + "operationId": "accountUpdatePrefs", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Update currently logged in user account preferences. The object you pass is stored as is, and replaces any previous value. The maximum allowed prefs size is 64kB and throws error if exceeded.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updatePrefs", + "group": "account", + "weight": 37, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "prefs": { + "type": "object", + "description": "Prefs key-value JSON object.", + "default": {}, + "x-example": "{}" + } + }, + "required": [ + "prefs" + ] + } + } + ] + } + }, + "\/account\/recovery": { + "post": { + "summary": "Create password recovery", + "operationId": "accountCreateRecovery", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Sends the user an email with a temporary secret key for password reset. When the user clicks the confirmation link he is redirected back to your app password reset URL with the secret key and email address values attached to the URL query string. Use the query string params to submit a request to the [PUT \/account\/recovery](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updateRecovery) endpoint to complete the process. The verification link sent to the user's email address is valid for 1 hour.", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createRecovery", + "group": "recovery", + "weight": 39, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-recovery.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-recovery.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},email:{param-email}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "default": null, + "x-example": "https:\/\/example.com" + } + }, + "required": [ + "email", + "url" + ] + } + } + ] + }, + "put": { + "summary": "Update password recovery (confirmation)", + "operationId": "accountUpdateRecovery", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to complete the user account password reset. Both the **userId** and **secret** arguments will be passed as query parameters to the redirect URL you have provided when sending your request to the [POST \/account\/recovery](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createRecovery) endpoint.\n\nPlease note that in order to avoid a [Redirect Attack](https:\/\/github.com\/OWASP\/CheatSheetSeries\/blob\/master\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) the only valid redirect URLs are the ones from domains you have set when adding your platforms in the console interface.", + "responses": { + "200": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "updateRecovery", + "group": "recovery", + "weight": 40, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-recovery.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-recovery.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid reset token.", + "default": null, + "x-example": "<SECRET>" + }, + "password": { + "type": "string", + "description": "New user password. Must be between 8 and 256 chars.", + "default": null, + "x-example": null + } + }, + "required": [ + "userId", + "secret", + "password" + ] + } + } + ] + } + }, + "\/account\/sessions": { + "get": { + "summary": "List sessions", + "operationId": "accountListSessions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get the list of active sessions across different devices for the currently logged in user.", + "responses": { + "200": { + "description": "Sessions List", + "schema": { + "$ref": "#\/definitions\/sessionList" + } + } + }, + "x-appwrite": { + "method": "listSessions", + "group": "sessions", + "weight": 12, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-sessions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + }, + "delete": { + "summary": "Delete sessions", + "operationId": "accountDeleteSessions", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "account" + ], + "description": "Delete all sessions from the user account and remove any sessions cookies from the end client.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSessions", + "group": "sessions", + "weight": 13, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-sessions.md", + "rate-limit": 100, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + } + }, + "\/account\/sessions\/anonymous": { + "post": { + "summary": "Create anonymous session", + "operationId": "accountCreateAnonymousSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to allow a new user to register an anonymous account in your project. This route will also create a new session for the user. To allow the new user to convert an anonymous account to a normal account, you need to update its [email and password](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updateEmail) or create an [OAuth2 session](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#CreateOAuth2Session).", + "responses": { + "201": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "createAnonymousSession", + "group": "sessions", + "weight": 18, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-anonymous-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session-anonymous.md", + "rate-limit": 50, + "rate-time": 3600, + "rate-key": "ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ] + } + }, + "\/account\/sessions\/email": { + "post": { + "summary": "Create email password session", + "operationId": "accountCreateEmailPasswordSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Allow the user to login into their account by providing a valid email and password combination. This route will create a new session for the user.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "201": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "createEmailPasswordSession", + "group": "sessions", + "weight": 17, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-email-password-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session-email-password.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},email:{param-email}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password. Must be at least 8 chars.", + "default": null, + "x-example": "password" + } + }, + "required": [ + "email", + "password" + ] + } + } + ] + } + }, + "\/account\/sessions\/magic-url": { + "put": { + "summary": "Update magic URL session", + "operationId": "accountUpdateMagicURLSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to create a session from token. Provide the **userId** and **secret** parameters from the successful response of authentication flows initiated by token creation. For example, magic URL and phone login.", + "responses": { + "201": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "updateMagicURLSession", + "group": "sessions", + "weight": 27, + "cookies": false, + "type": "", + "deprecated": true, + "demo": "account\/update-magic-u-r-l-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "ip:{ip},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "default": null, + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + ] + } + }, + "\/account\/sessions\/oauth2\/{provider}": { + "get": { + "summary": "Create OAuth2 session", + "operationId": "accountCreateOAuth2Session", + "consumes": [], + "produces": [ + "text\/html" + ], + "tags": [ + "account" + ], + "description": "Allow the user to login to their account using the OAuth2 provider of their choice. Each OAuth2 provider should be enabled from the Appwrite console first. Use the success and failure arguments to provide a redirect URL's back to your app when login is completed.\n\nIf there is already an active session, the new session will be attached to the logged-in account. If there are no active sessions, the server will attempt to look for a user with the same email address as the email received from the OAuth2 provider and attach the new session to the existing user. If no matching user is found - the server will create a new user.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "responses": { + "301": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "createOAuth2Session", + "group": "sessions", + "weight": 20, + "cookies": false, + "type": "webAuth", + "deprecated": false, + "demo": "account\/create-o-auth2session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session-oauth2.md", + "rate-limit": 50, + "rate-time": 3600, + "rate-key": "ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "provider", + "description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.", + "required": true, + "type": "string", + "x-example": "amazon", + "enum": [ + "amazon", + "apple", + "auth0", + "authentik", + "autodesk", + "bitbucket", + "bitly", + "box", + "dailymotion", + "discord", + "disqus", + "dropbox", + "etsy", + "facebook", + "figma", + "github", + "gitlab", + "google", + "linkedin", + "microsoft", + "notion", + "oidc", + "okta", + "paypal", + "paypalSandbox", + "podio", + "salesforce", + "slack", + "spotify", + "stripe", + "tradeshift", + "tradeshiftBox", + "twitch", + "wordpress", + "yahoo", + "yammer", + "yandex", + "zoho", + "zoom", + "mock" + ], + "x-enum-name": "OAuthProvider", + "x-enum-keys": [], + "in": "path" + }, + { + "name": "success", + "description": "URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "", + "in": "query" + }, + { + "name": "failure", + "description": "URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "", + "in": "query" + }, + { + "name": "scopes", + "description": "A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of 100 scopes are allowed, each 4096 characters long.", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/account\/sessions\/phone": { + "put": { + "summary": "Update phone session", + "operationId": "accountUpdatePhoneSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to create a session from token. Provide the **userId** and **secret** parameters from the successful response of authentication flows initiated by token creation. For example, magic URL and phone login.", + "responses": { + "201": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "updatePhoneSession", + "group": "sessions", + "weight": 28, + "cookies": false, + "type": "", + "deprecated": true, + "demo": "account\/update-phone-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "ip:{ip},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "default": null, + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + ] + } + }, + "\/account\/sessions\/token": { + "post": { + "summary": "Create session", + "operationId": "accountCreateSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to create a session from token. Provide the **userId** and **secret** parameters from the successful response of authentication flows initiated by token creation. For example, magic URL and phone login.", + "responses": { + "201": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "createSession", + "group": "sessions", + "weight": 19, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "ip:{ip},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Secret of a token generated by login methods. For example, the `createMagicURLToken` or `createPhoneToken` methods.", + "default": null, + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + ] + } + }, + "\/account\/sessions\/{sessionId}": { + "get": { + "summary": "Get session", + "operationId": "accountGetSession", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to get a logged in user's session using a Session ID. Inputting 'current' will return the current session being used.", + "responses": { + "200": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "getSession", + "group": "sessions", + "weight": 14, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get-session.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "description": "Session ID. Use the string 'current' to get the current device session.", + "required": true, + "type": "string", + "x-example": "<SESSION_ID>", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update session", + "operationId": "accountUpdateSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to extend a session's length. Extending a session is useful when session expiry is short. If the session was created using an OAuth provider, this endpoint refreshes the access token from the provider.", + "responses": { + "200": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "updateSession", + "group": "sessions", + "weight": 16, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "description": "Session ID. Use the string 'current' to update the current device session.", + "required": true, + "type": "string", + "x-example": "<SESSION_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete session", + "operationId": "accountDeleteSession", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "account" + ], + "description": "Logout the user. Use 'current' as the session ID to logout on this device, use a session ID to logout on another device. If you're looking to logout the user on all devices, use [Delete Sessions](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#deleteSessions) instead.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSession", + "group": "sessions", + "weight": 15, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-session.md", + "rate-limit": 100, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "description": "Session ID. Use the string 'current' to delete the current device session.", + "required": true, + "type": "string", + "x-example": "<SESSION_ID>", + "in": "path" + } + ] + } + }, + "\/account\/status": { + "patch": { + "summary": "Update status", + "operationId": "accountUpdateStatus", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Block the currently logged in user account. Behind the scene, the user record is not deleted but permanently blocked from any access. To completely delete a user, use the Users API instead.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateStatus", + "group": "account", + "weight": 38, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + } + }, + "\/account\/targets\/push": { + "post": { + "summary": "Create push target", + "operationId": "accountCreatePushTarget", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to register a device for push notifications. Provide a target ID (custom or generated using ID.unique()), a device identifier (usually a device token), and optionally specify which provider should send notifications to this target. The target is automatically linked to the current session and includes device information like brand and model.", + "responses": { + "201": { + "description": "Target", + "schema": { + "$ref": "#\/definitions\/target" + } + } + }, + "x-appwrite": { + "method": "createPushTarget", + "group": "pushTargets", + "weight": 55, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-push-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-push-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "targetId": { + "type": "string", + "description": "Target ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<TARGET_ID>" + }, + "identifier": { + "type": "string", + "description": "The target identifier (token, email, phone etc.)", + "default": null, + "x-example": "<IDENTIFIER>" + }, + "providerId": { + "type": "string", + "description": "Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.", + "default": "", + "x-example": "<PROVIDER_ID>" + } + }, + "required": [ + "targetId", + "identifier" + ] + } + } + ] + } + }, + "\/account\/targets\/{targetId}\/push": { + "put": { + "summary": "Update push target", + "operationId": "accountUpdatePushTarget", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Update the currently logged in user's push notification target. You can modify the target's identifier (device token) and provider ID (token, email, phone etc.). The target must exist and belong to the current user. If you change the provider ID, notifications will be sent through the new messaging provider instead.", + "responses": { + "200": { + "description": "Target", + "schema": { + "$ref": "#\/definitions\/target" + } + } + }, + "x-appwrite": { + "method": "updatePushTarget", + "group": "pushTargets", + "weight": 56, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-push-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-push-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "type": "string", + "x-example": "<TARGET_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "description": "The target identifier (token, email, phone etc.)", + "default": null, + "x-example": "<IDENTIFIER>" + } + }, + "required": [ + "identifier" + ] + } + } + ] + }, + "delete": { + "summary": "Delete push target", + "operationId": "accountDeletePushTarget", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "account" + ], + "description": "Delete a push notification target for the currently logged in user. After deletion, the device will no longer receive push notifications. The target must exist and belong to the current user.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deletePushTarget", + "group": "pushTargets", + "weight": 57, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-push-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-push-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "type": "string", + "x-example": "<TARGET_ID>", + "in": "path" + } + ] + } + }, + "\/account\/tokens\/email": { + "post": { + "summary": "Create email token (OTP)", + "operationId": "accountCreateEmailToken", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not be registered, a new user will be created. Use the returned user ID and secret and submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The secret sent to the user's email is valid for 15 minutes.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createEmailToken", + "group": "tokens", + "weight": 26, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-email-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-email.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},email:{param-email}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "phrase": { + "type": "boolean", + "description": "Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.", + "default": false, + "x-example": false + } + }, + "required": [ + "userId", + "email" + ] + } + } + ] + } + }, + "\/account\/tokens\/magic-url": { + "post": { + "summary": "Create magic URL token", + "operationId": "accountCreateMagicURLToken", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createMagicURLToken", + "group": "tokens", + "weight": 25, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-magic-u-r-l-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-magic-url.md", + "rate-limit": 60, + "rate-time": 3600, + "rate-key": [ + "url:{url},email:{param-email}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "default": "", + "x-example": "https:\/\/example.com" + }, + "phrase": { + "type": "boolean", + "description": "Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.", + "default": false, + "x-example": false + } + }, + "required": [ + "userId", + "email" + ] + } + } + ] + } + }, + "\/account\/tokens\/oauth2\/{provider}": { + "get": { + "summary": "Create OAuth2 token", + "operationId": "accountCreateOAuth2Token", + "consumes": [], + "produces": [ + "text\/html" + ], + "tags": [ + "account" + ], + "description": "Allow the user to login to their account using the OAuth2 provider of their choice. Each OAuth2 provider should be enabled from the Appwrite console first. Use the success and failure arguments to provide a redirect URL's back to your app when login is completed. \n\nIf authentication succeeds, `userId` and `secret` of a token will be appended to the success URL as query parameters. These can be used to create a new session using the [Create session](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "301": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "createOAuth2Token", + "group": "tokens", + "weight": 24, + "cookies": false, + "type": "webAuth", + "deprecated": false, + "demo": "account\/create-o-auth2token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-oauth2.md", + "rate-limit": 50, + "rate-time": 3600, + "rate-key": "ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "provider", + "description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.", + "required": true, + "type": "string", + "x-example": "amazon", + "enum": [ + "amazon", + "apple", + "auth0", + "authentik", + "autodesk", + "bitbucket", + "bitly", + "box", + "dailymotion", + "discord", + "disqus", + "dropbox", + "etsy", + "facebook", + "figma", + "github", + "gitlab", + "google", + "linkedin", + "microsoft", + "notion", + "oidc", + "okta", + "paypal", + "paypalSandbox", + "podio", + "salesforce", + "slack", + "spotify", + "stripe", + "tradeshift", + "tradeshiftBox", + "twitch", + "wordpress", + "yahoo", + "yammer", + "yandex", + "zoho", + "zoom", + "mock" + ], + "x-enum-name": "OAuthProvider", + "x-enum-keys": [], + "in": "path" + }, + { + "name": "success", + "description": "URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "", + "in": "query" + }, + { + "name": "failure", + "description": "URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "", + "in": "query" + }, + { + "name": "scopes", + "description": "A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of 100 scopes are allowed, each 4096 characters long.", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/account\/tokens\/phone": { + "post": { + "summary": "Create phone token", + "operationId": "accountCreatePhoneToken", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Sends the user an SMS with a secret key for creating a session. If the provided user ID has not be registered, a new user will be created. Use the returned user ID and secret and submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The secret sent to the user's phone is valid for 15 minutes.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createPhoneToken", + "group": "tokens", + "weight": 29, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-phone-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-phone.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},phone:{param-phone}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "default": null, + "x-example": "+12065550100" + } + }, + "required": [ + "userId", + "phone" + ] + } + } + ] + } + }, + "\/account\/verification": { + "post": { + "summary": "Create email verification", + "operationId": "accountCreateVerification", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to send a verification message to your user email address to confirm they are the valid owners of that address. Both the **userId** and **secret** arguments will be passed as query parameters to the URL you have provided to be attached to the verification email. The provided URL should redirect the user back to your app and allow you to complete the verification process by verifying both the **userId** and **secret** parameters. Learn more about how to [complete the verification process](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updateVerification). The verification link sent to the user's email address is valid for 7 days.\n\nPlease note that in order to avoid a [Redirect Attack](https:\/\/github.com\/OWASP\/CheatSheetSeries\/blob\/master\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md), the only valid redirect URLs are the ones from domains you have set when adding your platforms in the console interface.\n", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createVerification", + "group": "verification", + "weight": 41, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-email-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{userId}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "default": null, + "x-example": "https:\/\/example.com" + } + }, + "required": [ + "url" + ] + } + } + ] + }, + "put": { + "summary": "Update email verification (confirmation)", + "operationId": "accountUpdateVerification", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to complete the user email verification process. Use both the **userId** and **secret** parameters that were attached to your app URL to verify the user email ownership. If confirmed this route will return a 200 status code.", + "responses": { + "200": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "updateVerification", + "group": "verification", + "weight": 42, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-email-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{param-userId}", + "scope": "public", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "default": null, + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + ] + } + }, + "\/account\/verification\/phone": { + "post": { + "summary": "Create phone verification", + "operationId": "accountCreatePhoneVerification", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to send a verification SMS to the currently logged in user. This endpoint is meant for use after updating a user's phone number using the [accountUpdatePhone](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updatePhone) endpoint. Learn more about how to [complete the verification process](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updatePhoneVerification). The verification code sent to the user's phone number is valid for 15 minutes.", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createPhoneVerification", + "group": "verification", + "weight": 43, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-phone-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-phone-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},userId:{userId}", + "url:{url},ip:{ip}" + ], + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ] + }, + "put": { + "summary": "Update phone verification (confirmation)", + "operationId": "accountUpdatePhoneVerification", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to complete the user phone verification process. Use the **userId** and **secret** that were sent to your user's phone number to verify the user email ownership. If confirmed this route will return a 200 status code.", + "responses": { + "200": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "updatePhoneVerification", + "group": "verification", + "weight": 44, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-phone-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-phone-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "userId:{param-userId}", + "scope": "public", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "default": null, + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + ] + } + }, + "\/avatars\/browsers\/{code}": { + "get": { + "summary": "Get browser icon", + "operationId": "avatarsGetBrowser", + "consumes": [], + "produces": [ + "image\/png" + ], + "tags": [ + "avatars" + ], + "description": "You can use this endpoint to show different browser icons to your users. The code argument receives the browser code as it appears in your user [GET \/account\/sessions](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#getSessions) endpoint. Use width, height and quality arguments to change the output settings.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getBrowser", + "group": null, + "weight": 61, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-browser.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-browser.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "code", + "description": "Browser Code.", + "required": true, + "type": "string", + "x-example": "aa", + "enum": [ + "aa", + "an", + "ch", + "ci", + "cm", + "cr", + "ff", + "sf", + "mf", + "ps", + "oi", + "om", + "op", + "on" + ], + "x-enum-name": "Browser", + "x-enum-keys": [ + "Avant Browser", + "Android WebView Beta", + "Google Chrome", + "Google Chrome (iOS)", + "Google Chrome (Mobile)", + "Chromium", + "Mozilla Firefox", + "Safari", + "Mobile Safari", + "Microsoft Edge", + "Microsoft Edge (iOS)", + "Opera Mini", + "Opera", + "Opera (Next)" + ], + "in": "path" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + }, + { + "name": "quality", + "description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1, + "in": "query" + } + ] + } + }, + "\/avatars\/credit-cards\/{code}": { + "get": { + "summary": "Get credit card icon", + "operationId": "avatarsGetCreditCard", + "consumes": [], + "produces": [ + "image\/png" + ], + "tags": [ + "avatars" + ], + "description": "The credit card endpoint will return you the icon of the credit card provider you need. Use width, height and quality arguments to change the output settings.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.\n", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getCreditCard", + "group": null, + "weight": 60, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-credit-card.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-credit-card.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "code", + "description": "Credit Card Code. Possible values: amex, argencard, cabal, cencosud, diners, discover, elo, hipercard, jcb, mastercard, naranja, targeta-shopping, union-china-pay, visa, mir, maestro, rupay.", + "required": true, + "type": "string", + "x-example": "amex", + "enum": [ + "amex", + "argencard", + "cabal", + "cencosud", + "diners", + "discover", + "elo", + "hipercard", + "jcb", + "mastercard", + "naranja", + "targeta-shopping", + "union-china-pay", + "visa", + "mir", + "maestro", + "rupay" + ], + "x-enum-name": "CreditCard", + "x-enum-keys": [ + "American Express", + "Argencard", + "Cabal", + "Cencosud", + "Diners Club", + "Discover", + "Elo", + "Hipercard", + "JCB", + "Mastercard", + "Naranja", + "Tarjeta Shopping", + "Union China Pay", + "Visa", + "MIR", + "Maestro", + "Rupay" + ], + "in": "path" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + }, + { + "name": "quality", + "description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1, + "in": "query" + } + ] + } + }, + "\/avatars\/favicon": { + "get": { + "summary": "Get favicon", + "operationId": "avatarsGetFavicon", + "consumes": [], + "produces": [ + "image\/*" + ], + "tags": [ + "avatars" + ], + "description": "Use this endpoint to fetch the favorite icon (AKA favicon) of any remote website URL.\n\nThis endpoint does not follow HTTP redirects.", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getFavicon", + "group": null, + "weight": 64, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-favicon.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-favicon.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "url", + "description": "Website URL which you want to fetch the favicon from.", + "required": true, + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "in": "query" + } + ] + } + }, + "\/avatars\/flags\/{code}": { + "get": { + "summary": "Get country flag", + "operationId": "avatarsGetFlag", + "consumes": [], + "produces": [ + "image\/png" + ], + "tags": [ + "avatars" + ], + "description": "You can use this endpoint to show different country flags icons to your users. The code argument receives the 2 letter country code. Use width, height and quality arguments to change the output settings. Country codes follow the [ISO 3166-1](https:\/\/en.wikipedia.org\/wiki\/ISO_3166-1) standard.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.\n", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getFlag", + "group": null, + "weight": 62, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-flag.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-flag.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "code", + "description": "Country Code. ISO Alpha-2 country code format.", + "required": true, + "type": "string", + "x-example": "af", + "enum": [ + "af", + "ao", + "al", + "ad", + "ae", + "ar", + "am", + "ag", + "au", + "at", + "az", + "bi", + "be", + "bj", + "bf", + "bd", + "bg", + "bh", + "bs", + "ba", + "by", + "bz", + "bo", + "br", + "bb", + "bn", + "bt", + "bw", + "cf", + "ca", + "ch", + "cl", + "cn", + "ci", + "cm", + "cd", + "cg", + "co", + "km", + "cv", + "cr", + "cu", + "cy", + "cz", + "de", + "dj", + "dm", + "dk", + "do", + "dz", + "ec", + "eg", + "er", + "es", + "ee", + "et", + "fi", + "fj", + "fr", + "fm", + "ga", + "gb", + "ge", + "gh", + "gn", + "gm", + "gw", + "gq", + "gr", + "gd", + "gt", + "gy", + "hn", + "hr", + "ht", + "hu", + "id", + "in", + "ie", + "ir", + "iq", + "is", + "il", + "it", + "jm", + "jo", + "jp", + "kz", + "ke", + "kg", + "kh", + "ki", + "kn", + "kr", + "kw", + "la", + "lb", + "lr", + "ly", + "lc", + "li", + "lk", + "ls", + "lt", + "lu", + "lv", + "ma", + "mc", + "md", + "mg", + "mv", + "mx", + "mh", + "mk", + "ml", + "mt", + "mm", + "me", + "mn", + "mz", + "mr", + "mu", + "mw", + "my", + "na", + "ne", + "ng", + "ni", + "nl", + "no", + "np", + "nr", + "nz", + "om", + "pk", + "pa", + "pe", + "ph", + "pw", + "pg", + "pl", + "pf", + "kp", + "pt", + "py", + "qa", + "ro", + "ru", + "rw", + "sa", + "sd", + "sn", + "sg", + "sb", + "sl", + "sv", + "sm", + "so", + "rs", + "ss", + "st", + "sr", + "sk", + "si", + "se", + "sz", + "sc", + "sy", + "td", + "tg", + "th", + "tj", + "tm", + "tl", + "to", + "tt", + "tn", + "tr", + "tv", + "tz", + "ug", + "ua", + "uy", + "us", + "uz", + "va", + "vc", + "ve", + "vn", + "vu", + "ws", + "ye", + "za", + "zm", + "zw" + ], + "x-enum-name": "Flag", + "x-enum-keys": [ + "Afghanistan", + "Angola", + "Albania", + "Andorra", + "United Arab Emirates", + "Argentina", + "Armenia", + "Antigua and Barbuda", + "Australia", + "Austria", + "Azerbaijan", + "Burundi", + "Belgium", + "Benin", + "Burkina Faso", + "Bangladesh", + "Bulgaria", + "Bahrain", + "Bahamas", + "Bosnia and Herzegovina", + "Belarus", + "Belize", + "Bolivia", + "Brazil", + "Barbados", + "Brunei Darussalam", + "Bhutan", + "Botswana", + "Central African Republic", + "Canada", + "Switzerland", + "Chile", + "China", + "C\u00f4te d'Ivoire", + "Cameroon", + "Democratic Republic of the Congo", + "Republic of the Congo", + "Colombia", + "Comoros", + "Cape Verde", + "Costa Rica", + "Cuba", + "Cyprus", + "Czech Republic", + "Germany", + "Djibouti", + "Dominica", + "Denmark", + "Dominican Republic", + "Algeria", + "Ecuador", + "Egypt", + "Eritrea", + "Spain", + "Estonia", + "Ethiopia", + "Finland", + "Fiji", + "France", + "Micronesia (Federated States of)", + "Gabon", + "United Kingdom", + "Georgia", + "Ghana", + "Guinea", + "Gambia", + "Guinea-Bissau", + "Equatorial Guinea", + "Greece", + "Grenada", + "Guatemala", + "Guyana", + "Honduras", + "Croatia", + "Haiti", + "Hungary", + "Indonesia", + "India", + "Ireland", + "Iran (Islamic Republic of)", + "Iraq", + "Iceland", + "Israel", + "Italy", + "Jamaica", + "Jordan", + "Japan", + "Kazakhstan", + "Kenya", + "Kyrgyzstan", + "Cambodia", + "Kiribati", + "Saint Kitts and Nevis", + "South Korea", + "Kuwait", + "Lao People's Democratic Republic", + "Lebanon", + "Liberia", + "Libya", + "Saint Lucia", + "Liechtenstein", + "Sri Lanka", + "Lesotho", + "Lithuania", + "Luxembourg", + "Latvia", + "Morocco", + "Monaco", + "Moldova", + "Madagascar", + "Maldives", + "Mexico", + "Marshall Islands", + "North Macedonia", + "Mali", + "Malta", + "Myanmar", + "Montenegro", + "Mongolia", + "Mozambique", + "Mauritania", + "Mauritius", + "Malawi", + "Malaysia", + "Namibia", + "Niger", + "Nigeria", + "Nicaragua", + "Netherlands", + "Norway", + "Nepal", + "Nauru", + "New Zealand", + "Oman", + "Pakistan", + "Panama", + "Peru", + "Philippines", + "Palau", + "Papua New Guinea", + "Poland", + "French Polynesia", + "North Korea", + "Portugal", + "Paraguay", + "Qatar", + "Romania", + "Russia", + "Rwanda", + "Saudi Arabia", + "Sudan", + "Senegal", + "Singapore", + "Solomon Islands", + "Sierra Leone", + "El Salvador", + "San Marino", + "Somalia", + "Serbia", + "South Sudan", + "Sao Tome and Principe", + "Suriname", + "Slovakia", + "Slovenia", + "Sweden", + "Eswatini", + "Seychelles", + "Syria", + "Chad", + "Togo", + "Thailand", + "Tajikistan", + "Turkmenistan", + "Timor-Leste", + "Tonga", + "Trinidad and Tobago", + "Tunisia", + "Turkey", + "Tuvalu", + "Tanzania", + "Uganda", + "Ukraine", + "Uruguay", + "United States", + "Uzbekistan", + "Vatican City", + "Saint Vincent and the Grenadines", + "Venezuela", + "Vietnam", + "Vanuatu", + "Samoa", + "Yemen", + "South Africa", + "Zambia", + "Zimbabwe" + ], + "in": "path" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + }, + { + "name": "quality", + "description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1, + "in": "query" + } + ] + } + }, + "\/avatars\/image": { + "get": { + "summary": "Get image from URL", + "operationId": "avatarsGetImage", + "consumes": [], + "produces": [ + "image\/*" + ], + "tags": [ + "avatars" + ], + "description": "Use this endpoint to fetch a remote image URL and crop it to any image size you want. This endpoint is very useful if you need to crop and display remote images in your app or in case you want to make sure a 3rd party image is properly served using a TLS protocol.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 400x400px.\n\nThis endpoint does not follow HTTP redirects.", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getImage", + "group": null, + "weight": 63, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-image.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-image.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "url", + "description": "Image URL which you want to crop.", + "required": true, + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "in": "query" + }, + { + "name": "width", + "description": "Resize preview image width, Pass an integer between 0 to 2000. Defaults to 400.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 400, + "in": "query" + }, + { + "name": "height", + "description": "Resize preview image height, Pass an integer between 0 to 2000. Defaults to 400.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 400, + "in": "query" + } + ] + } + }, + "\/avatars\/initials": { + "get": { + "summary": "Get user initials", + "operationId": "avatarsGetInitials", + "consumes": [], + "produces": [ + "image\/png" + ], + "tags": [ + "avatars" + ], + "description": "Use this endpoint to show your user initials avatar icon on your website or app. By default, this route will try to print your logged-in user name or email initials. You can also overwrite the user name if you pass the 'name' parameter. If no name is given and no user is logged, an empty avatar will be returned.\n\nYou can use the color and background params to change the avatar colors. By default, a random theme will be selected. The random theme will persist for the user's initials when reloading the same theme will always return for the same initials.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.\n", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getInitials", + "group": null, + "weight": 66, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-initials.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-initials.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "name", + "description": "Full Name. When empty, current user name or email will be used. Max length: 128 chars.", + "required": false, + "type": "string", + "x-example": "<NAME>", + "default": "", + "in": "query" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 500, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 500, + "in": "query" + }, + { + "name": "background", + "description": "Changes background color. By default a random color will be picked and stay will persistent to the given name.", + "required": false, + "type": "string", + "default": "", + "in": "query" + } + ] + } + }, + "\/avatars\/qr": { + "get": { + "summary": "Get QR code", + "operationId": "avatarsGetQR", + "consumes": [], + "produces": [ + "image\/png" + ], + "tags": [ + "avatars" + ], + "description": "Converts a given plain text to a QR code image. You can use the query parameters to change the size and style of the resulting image.\n", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getQR", + "group": null, + "weight": 65, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-q-r.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-qr.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "text", + "description": "Plain text to be converted to QR code image.", + "required": true, + "type": "string", + "x-example": "<TEXT>", + "in": "query" + }, + { + "name": "size", + "description": "QR code size. Pass an integer between 1 to 1000. Defaults to 400.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 1, + "default": 400, + "in": "query" + }, + { + "name": "margin", + "description": "Margin from edge. Pass an integer between 0 to 10. Defaults to 1.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 1, + "in": "query" + }, + { + "name": "download", + "description": "Return resulting image with 'Content-Disposition: attachment ' headers for the browser to start downloading it. Pass 0 for no header, or 1 for otherwise. Default value is set to 0.", + "required": false, + "type": "boolean", + "x-example": false, + "default": false, + "in": "query" + } + ] + } + }, + "\/console\/assistant": { + "post": { + "summary": "Create assistant query", + "operationId": "assistantChat", + "consumes": [ + "application\/json" + ], + "produces": [ + "text\/plain" + ], + "tags": [ + "assistant" + ], + "description": "Send a prompt to the AI assistant and receive a response. This endpoint allows you to interact with Appwrite's AI assistant by sending questions or prompts and receiving helpful responses in real-time through a server-sent events stream. ", + "responses": { + "200": { + "description": "File", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "chat", + "group": "console", + "weight": 310, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "assistant\/chat.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/assistant\/chat.md", + "rate-limit": 15, + "rate-time": 3600, + "rate-key": "userId:{userId}", + "scope": "assistant.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "prompt": { + "type": "string", + "description": "Prompt. A string containing questions asked to the AI assistant.", + "default": null, + "x-example": "<PROMPT>" + } + }, + "required": [ + "prompt" + ] + } + } + ] + } + }, + "\/console\/resources": { + "get": { + "summary": "Check resource ID availability", + "operationId": "consoleGetResource", + "consumes": [], + "produces": [], + "tags": [ + "console" + ], + "description": "Check if a resource ID is available.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "getResource", + "group": null, + "weight": 434, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "console\/get-resource.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCheck if a resource ID is available.", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "userId:{userId}, url:{url}", + "scope": "rules.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "value", + "description": "Resource value.", + "required": true, + "type": "string", + "x-example": "<VALUE>", + "in": "query" + }, + { + "name": "type", + "description": "Resource type.", + "required": true, + "type": "string", + "x-example": "rules", + "enum": [ + "rules" + ], + "x-enum-name": "ConsoleResourceType", + "x-enum-keys": [], + "in": "query" + } + ] + } + }, + "\/console\/variables": { + "get": { + "summary": "Get variables", + "operationId": "consoleVariables", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "console" + ], + "description": "Get all Environment Variables that are relevant for the console.", + "responses": { + "200": { + "description": "Console Variables", + "schema": { + "$ref": "#\/definitions\/consoleVariables" + } + } + }, + "x-appwrite": { + "method": "variables", + "group": "console", + "weight": 309, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "console\/variables.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/console\/variables.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ] + } + }, + "\/databases": { + "get": { + "summary": "List databases", + "operationId": "databasesList", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a list of all databases from the current Appwrite project. You can use the search parameter to filter your results.", + "responses": { + "200": { + "description": "Databases List", + "schema": { + "$ref": "#\/definitions\/databaseList" + } + } + }, + "x-appwrite": { + "method": "list", + "group": "databases", + "weight": 71, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create database", + "operationId": "databasesCreate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a new Database.\n", + "responses": { + "201": { + "description": "Database", + "schema": { + "$ref": "#\/definitions\/database" + } + } + }, + "x-appwrite": { + "method": "create", + "group": "databases", + "weight": 70, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "databaseId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<DATABASE_ID>" + }, + "name": { + "type": "string", + "description": "Database name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Is the database enabled? When set to 'disabled', users cannot access the database but Server SDKs with an API key can still read and write to the database. No data is lost when this is toggled.", + "default": true, + "x-example": false + } + }, + "required": [ + "databaseId", + "name" + ] + } + } + ] + } + }, + "\/databases\/usage": { + "get": { + "summary": "Get databases usage stats", + "operationId": "databasesGetUsage", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get usage metrics and statistics for all databases in the project. You can view the total number of databases, collections, documents, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.", + "responses": { + "200": { + "description": "UsageDatabases", + "schema": { + "$ref": "#\/definitions\/usageDatabases" + } + } + }, + "x-appwrite": { + "method": "getUsage", + "group": null, + "weight": 121, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-usage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "range", + "description": "`Date range.", + "required": false, + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "DatabaseUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d", + "in": "query" + } + ] + } + }, + "\/databases\/{databaseId}": { + "get": { + "summary": "Get database", + "operationId": "databasesGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a database by its unique ID. This endpoint response returns a JSON object with the database metadata.", + "responses": { + "200": { + "description": "Database", + "schema": { + "$ref": "#\/definitions\/database" + } + } + }, + "x-appwrite": { + "method": "get", + "group": "databases", + "weight": 72, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update database", + "operationId": "databasesUpdate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a database by its unique ID.", + "responses": { + "200": { + "description": "Database", + "schema": { + "$ref": "#\/definitions\/database" + } + } + }, + "x-appwrite": { + "method": "update", + "group": "databases", + "weight": 74, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Database name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Is database enabled? When set to 'disabled', users cannot access the database but Server SDKs with an API key can still read and write to the database. No data is lost when this is toggled.", + "default": true, + "x-example": false + } + }, + "required": [ + "name" + ] + } + } + ] + }, + "delete": { + "summary": "Delete database", + "operationId": "databasesDelete", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "databases" + ], + "description": "Delete a database by its unique ID. Only API keys with with databases.write scope can delete a database.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "databases", + "weight": 75, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections": { + "get": { + "summary": "List collections", + "operationId": "databasesListCollections", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a list of all collections that belong to the provided databaseId. You can use the search parameter to filter your results.", + "responses": { + "200": { + "description": "Collections List", + "schema": { + "$ref": "#\/definitions\/collectionList" + } + } + }, + "x-appwrite": { + "method": "listCollections", + "group": "collections", + "weight": 77, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-collections.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-collections.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, enabled, documentSecurity", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create collection", + "operationId": "databasesCreateCollection", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a new Collection. Before using this route, you should create a new database resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "201": { + "description": "Collection", + "schema": { + "$ref": "#\/definitions\/collection" + } + } + }, + "x-appwrite": { + "method": "createCollection", + "group": "collections", + "weight": 76, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-collection.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-collection.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "collectionId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<COLLECTION_ID>" + }, + "name": { + "type": "string", + "description": "Collection name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "documentSecurity": { + "type": "boolean", + "description": "Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": false, + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Is collection enabled? When set to 'disabled', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.", + "default": true, + "x-example": false + } + }, + "required": [ + "collectionId", + "name" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}": { + "get": { + "summary": "Get collection", + "operationId": "databasesGetCollection", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a collection by its unique ID. This endpoint response returns a JSON object with the collection metadata.", + "responses": { + "200": { + "description": "Collection", + "schema": { + "$ref": "#\/definitions\/collection" + } + } + }, + "x-appwrite": { + "method": "getCollection", + "group": "collections", + "weight": 78, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-collection.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-collection.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update collection", + "operationId": "databasesUpdateCollection", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a collection by its unique ID.", + "responses": { + "200": { + "description": "Collection", + "schema": { + "$ref": "#\/definitions\/collection" + } + } + }, + "x-appwrite": { + "method": "updateCollection", + "group": "collections", + "weight": 80, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-collection.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-collection.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Collection name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "permissions": { + "type": "array", + "description": "An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "documentSecurity": { + "type": "boolean", + "description": "Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": false, + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Is collection enabled? When set to 'disabled', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.", + "default": true, + "x-example": false + } + }, + "required": [ + "name" + ] + } + } + ] + }, + "delete": { + "summary": "Delete collection", + "operationId": "databasesDeleteCollection", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "databases" + ], + "description": "Delete a collection by its unique ID. Only users with write permissions have access to delete this resource.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteCollection", + "group": "collections", + "weight": 81, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-collection.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-collection.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes": { + "get": { + "summary": "List attributes", + "operationId": "databasesListAttributes", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "List attributes in the collection.", + "responses": { + "200": { + "description": "Attributes List", + "schema": { + "$ref": "#\/definitions\/attributeList" + } + } + }, + "x-appwrite": { + "method": "listAttributes", + "group": "attributes", + "weight": 92, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-attributes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-attributes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: key, type, size, required, array, status, error", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/boolean": { + "post": { + "summary": "Create boolean attribute", + "operationId": "databasesCreateBooleanAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a boolean attribute.\n", + "responses": { + "202": { + "description": "AttributeBoolean", + "schema": { + "$ref": "#\/definitions\/attributeBoolean" + } + } + }, + "x-appwrite": { + "method": "createBooleanAttribute", + "group": "attributes", + "weight": 89, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-boolean-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-boolean-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "boolean", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": false + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "default": false, + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/boolean\/{key}": { + "patch": { + "summary": "Update boolean attribute", + "operationId": "databasesUpdateBooleanAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a boolean attribute. Changing the `default` value will not update already existing documents.", + "responses": { + "200": { + "description": "AttributeBoolean", + "schema": { + "$ref": "#\/definitions\/attributeBoolean" + } + } + }, + "x-appwrite": { + "method": "updateBooleanAttribute", + "group": "attributes", + "weight": 101, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-boolean-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-boolean-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "boolean", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": false, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/datetime": { + "post": { + "summary": "Create datetime attribute", + "operationId": "databasesCreateDatetimeAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a date time attribute according to the ISO 8601 standard.", + "responses": { + "202": { + "description": "AttributeDatetime", + "schema": { + "$ref": "#\/definitions\/attributeDatetime" + } + } + }, + "x-appwrite": { + "method": "createDatetimeAttribute", + "group": "attributes", + "weight": 90, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-datetime-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-datetime-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for the attribute in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when attribute is required.", + "default": null, + "x-example": null + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "default": false, + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/datetime\/{key}": { + "patch": { + "summary": "Update dateTime attribute", + "operationId": "databasesUpdateDatetimeAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a date time attribute. Changing the `default` value will not update already existing documents.", + "responses": { + "200": { + "description": "AttributeDatetime", + "schema": { + "$ref": "#\/definitions\/attributeDatetime" + } + } + }, + "x-appwrite": { + "method": "updateDatetimeAttribute", + "group": "attributes", + "weight": 102, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-datetime-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-datetime-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": null, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/email": { + "post": { + "summary": "Create email attribute", + "operationId": "databasesCreateEmailAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create an email attribute.\n", + "responses": { + "202": { + "description": "AttributeEmail", + "schema": { + "$ref": "#\/definitions\/attributeEmail" + } + } + }, + "x-appwrite": { + "method": "createEmailAttribute", + "group": "attributes", + "weight": 83, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-email-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-email-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": "email@example.com" + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "default": false, + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/email\/{key}": { + "patch": { + "summary": "Update email attribute", + "operationId": "databasesUpdateEmailAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update an email attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeEmail", + "schema": { + "$ref": "#\/definitions\/attributeEmail" + } + } + }, + "x-appwrite": { + "method": "updateEmailAttribute", + "group": "attributes", + "weight": 95, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-email-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-email-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": "email@example.com", + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/enum": { + "post": { + "summary": "Create enum attribute", + "operationId": "databasesCreateEnumAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create an enumeration attribute. The `elements` param acts as a white-list of accepted values for this attribute. \n", + "responses": { + "202": { + "description": "AttributeEnum", + "schema": { + "$ref": "#\/definitions\/attributeEnum" + } + } + }, + "x-appwrite": { + "method": "createEnumAttribute", + "group": "attributes", + "weight": 84, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-enum-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-attribute-enum.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "elements": { + "type": "array", + "description": "Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of 100 elements are allowed, each 255 characters long.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": "<DEFAULT>" + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "default": false, + "x-example": false + } + }, + "required": [ + "key", + "elements", + "required" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/enum\/{key}": { + "patch": { + "summary": "Update enum attribute", + "operationId": "databasesUpdateEnumAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update an enum attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeEnum", + "schema": { + "$ref": "#\/definitions\/attributeEnum" + } + } + }, + "x-appwrite": { + "method": "updateEnumAttribute", + "group": "attributes", + "weight": 96, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-enum-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-enum-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "elements": { + "type": "array", + "description": "Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of 100 elements are allowed, each 255 characters long.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": "<DEFAULT>", + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + }, + "required": [ + "elements", + "required", + "default" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/float": { + "post": { + "summary": "Create float attribute", + "operationId": "databasesCreateFloatAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a float attribute. Optionally, minimum and maximum values can be provided.\n", + "responses": { + "202": { + "description": "AttributeFloat", + "schema": { + "$ref": "#\/definitions\/attributeFloat" + } + } + }, + "x-appwrite": { + "method": "createFloatAttribute", + "group": "attributes", + "weight": 88, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-float-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-float-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "min": { + "type": "number", + "description": "Minimum value to enforce on new documents", + "default": null, + "x-example": null + }, + "max": { + "type": "number", + "description": "Maximum value to enforce on new documents", + "default": null, + "x-example": null + }, + "default": { + "type": "number", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": null + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "default": false, + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/float\/{key}": { + "patch": { + "summary": "Update float attribute", + "operationId": "databasesUpdateFloatAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a float attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeFloat", + "schema": { + "$ref": "#\/definitions\/attributeFloat" + } + } + }, + "x-appwrite": { + "method": "updateFloatAttribute", + "group": "attributes", + "weight": 100, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-float-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-float-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "min": { + "type": "number", + "description": "Minimum value to enforce on new documents", + "default": null, + "x-example": null + }, + "max": { + "type": "number", + "description": "Maximum value to enforce on new documents", + "default": null, + "x-example": null + }, + "default": { + "type": "number", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": null, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/integer": { + "post": { + "summary": "Create integer attribute", + "operationId": "databasesCreateIntegerAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create an integer attribute. Optionally, minimum and maximum values can be provided.\n", + "responses": { + "202": { + "description": "AttributeInteger", + "schema": { + "$ref": "#\/definitions\/attributeInteger" + } + } + }, + "x-appwrite": { + "method": "createIntegerAttribute", + "group": "attributes", + "weight": 87, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-integer-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-integer-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "min": { + "type": "integer", + "description": "Minimum value to enforce on new documents", + "default": null, + "x-example": null + }, + "max": { + "type": "integer", + "description": "Maximum value to enforce on new documents", + "default": null, + "x-example": null + }, + "default": { + "type": "integer", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": null + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "default": false, + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/integer\/{key}": { + "patch": { + "summary": "Update integer attribute", + "operationId": "databasesUpdateIntegerAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update an integer attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeInteger", + "schema": { + "$ref": "#\/definitions\/attributeInteger" + } + } + }, + "x-appwrite": { + "method": "updateIntegerAttribute", + "group": "attributes", + "weight": 99, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-integer-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-integer-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "min": { + "type": "integer", + "description": "Minimum value to enforce on new documents", + "default": null, + "x-example": null + }, + "max": { + "type": "integer", + "description": "Maximum value to enforce on new documents", + "default": null, + "x-example": null + }, + "default": { + "type": "integer", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": null, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/ip": { + "post": { + "summary": "Create IP address attribute", + "operationId": "databasesCreateIpAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create IP address attribute.\n", + "responses": { + "202": { + "description": "AttributeIP", + "schema": { + "$ref": "#\/definitions\/attributeIp" + } + } + }, + "x-appwrite": { + "method": "createIpAttribute", + "group": "attributes", + "weight": 85, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-ip-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-ip-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": null + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "default": false, + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/ip\/{key}": { + "patch": { + "summary": "Update IP address attribute", + "operationId": "databasesUpdateIpAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update an ip attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeIP", + "schema": { + "$ref": "#\/definitions\/attributeIp" + } + } + }, + "x-appwrite": { + "method": "updateIpAttribute", + "group": "attributes", + "weight": 97, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-ip-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-ip-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": null, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/relationship": { + "post": { + "summary": "Create relationship attribute", + "operationId": "databasesCreateRelationshipAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create relationship attribute. [Learn more about relationship attributes](https:\/\/appwrite.io\/docs\/databases-relationships#relationship-attributes).\n", + "responses": { + "202": { + "description": "AttributeRelationship", + "schema": { + "$ref": "#\/definitions\/attributeRelationship" + } + } + }, + "x-appwrite": { + "method": "createRelationshipAttribute", + "group": "attributes", + "weight": 91, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-relationship-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-relationship-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "relatedCollectionId": { + "type": "string", + "description": "Related Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "default": null, + "x-example": "<RELATED_COLLECTION_ID>" + }, + "type": { + "type": "string", + "description": "Relation type", + "default": null, + "x-example": "oneToOne", + "enum": [ + "oneToOne", + "manyToOne", + "manyToMany", + "oneToMany" + ], + "x-enum-name": "RelationshipType", + "x-enum-keys": [] + }, + "twoWay": { + "type": "boolean", + "description": "Is Two Way?", + "default": false, + "x-example": false + }, + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "twoWayKey": { + "type": "string", + "description": "Two Way Attribute Key.", + "default": null, + "x-example": null + }, + "onDelete": { + "type": "string", + "description": "Constraints option", + "default": "restrict", + "x-example": "cascade", + "enum": [ + "cascade", + "restrict", + "setNull" + ], + "x-enum-name": "RelationMutate", + "x-enum-keys": [] + } + }, + "required": [ + "relatedCollectionId", + "type" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/string": { + "post": { + "summary": "Create string attribute", + "operationId": "databasesCreateStringAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a string attribute.\n", + "responses": { + "202": { + "description": "AttributeString", + "schema": { + "$ref": "#\/definitions\/attributeString" + } + } + }, + "x-appwrite": { + "method": "createStringAttribute", + "group": "attributes", + "weight": 82, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-string-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-string-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "size": { + "type": "integer", + "description": "Attribute size for text attributes, in number of characters.", + "default": null, + "x-example": 1 + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": "<DEFAULT>" + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "default": false, + "x-example": false + }, + "encrypt": { + "type": "boolean", + "description": "Toggle encryption for the attribute. Encryption enhances security by not storing any plain text values in the database. However, encrypted attributes cannot be queried.", + "default": false, + "x-example": false + } + }, + "required": [ + "key", + "size", + "required" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/string\/{key}": { + "patch": { + "summary": "Update string attribute", + "operationId": "databasesUpdateStringAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a string attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeString", + "schema": { + "$ref": "#\/definitions\/attributeString" + } + } + }, + "x-appwrite": { + "method": "updateStringAttribute", + "group": "attributes", + "weight": 94, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-string-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-string-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": "<DEFAULT>", + "x-nullable": true + }, + "size": { + "type": "integer", + "description": "Maximum size of the string attribute.", + "default": null, + "x-example": 1 + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/url": { + "post": { + "summary": "Create URL attribute", + "operationId": "databasesCreateUrlAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a URL attribute.\n", + "responses": { + "202": { + "description": "AttributeURL", + "schema": { + "$ref": "#\/definitions\/attributeUrl" + } + } + }, + "x-appwrite": { + "method": "createUrlAttribute", + "group": "attributes", + "weight": 86, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-url-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-url-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": "https:\/\/example.com" + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "default": false, + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/url\/{key}": { + "patch": { + "summary": "Update URL attribute", + "operationId": "databasesUpdateUrlAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update an url attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeURL", + "schema": { + "$ref": "#\/definitions\/attributeUrl" + } + } + }, + "x-appwrite": { + "method": "updateUrlAttribute", + "group": "attributes", + "weight": 98, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-url-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-url-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": "https:\/\/example.com", + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/{key}": { + "get": { + "summary": "Get attribute", + "operationId": "databasesGetAttribute", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get attribute by ID.", + "responses": { + "200": { + "description": "AttributeBoolean, or AttributeInteger, or AttributeFloat, or AttributeEmail, or AttributeEnum, or AttributeURL, or AttributeIP, or AttributeDatetime, or AttributeRelationship, or AttributeString", + "schema": { + "x-oneOf": [ + { + "$ref": "#\/definitions\/attributeBoolean" + }, + { + "$ref": "#\/definitions\/attributeInteger" + }, + { + "$ref": "#\/definitions\/attributeFloat" + }, + { + "$ref": "#\/definitions\/attributeEmail" + }, + { + "$ref": "#\/definitions\/attributeEnum" + }, + { + "$ref": "#\/definitions\/attributeUrl" + }, + { + "$ref": "#\/definitions\/attributeIp" + }, + { + "$ref": "#\/definitions\/attributeDatetime" + }, + { + "$ref": "#\/definitions\/attributeRelationship" + }, + { + "$ref": "#\/definitions\/attributeString" + } + ] + } + } + }, + "x-appwrite": { + "method": "getAttribute", + "group": "attributes", + "weight": 93, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete attribute", + "operationId": "databasesDeleteAttribute", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "databases" + ], + "description": "Deletes an attribute.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteAttribute", + "group": "attributes", + "weight": 104, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/{key}\/relationship": { + "patch": { + "summary": "Update relationship attribute", + "operationId": "databasesUpdateRelationshipAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update relationship attribute. [Learn more about relationship attributes](https:\/\/appwrite.io\/docs\/databases-relationships#relationship-attributes).\n", + "responses": { + "200": { + "description": "AttributeRelationship", + "schema": { + "$ref": "#\/definitions\/attributeRelationship" + } + } + }, + "x-appwrite": { + "method": "updateRelationshipAttribute", + "group": "attributes", + "weight": 103, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-relationship-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-relationship-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "onDelete": { + "type": "string", + "description": "Constraints option", + "default": null, + "x-example": "cascade", + "enum": [ + "cascade", + "restrict", + "setNull" + ], + "x-enum-name": "RelationMutate", + "x-enum-keys": [] + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + } + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents": { + "get": { + "summary": "List documents", + "operationId": "databasesListDocuments", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a list of all the user's documents in a given collection. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Documents List", + "schema": { + "$ref": "#\/definitions\/documentList" + } + } + }, + "x-appwrite": { + "method": "listDocuments", + "group": "documents", + "weight": 110, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-documents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-documents.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create document", + "operationId": "databasesCreateDocument", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "201": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "createDocument", + "group": "documents", + "weight": 109, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "methods": [ + { + "name": "createDocument", + "auth": { + "Session": [], + "Key": [], + "JWT": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documentId", + "data", + "permissions" + ], + "required": [ + "databaseId", + "collectionId", + "documentId", + "data" + ], + "responses": [ + { + "code": 201, + "model": "#\/definitions\/document" + } + ], + "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/definitions\/documentList" + } + ], + "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + } + ], + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection). Make sure to define attributes before creating documents.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "documentId": { + "type": "string", + "description": "Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": "", + "x-example": "<DOCUMENT_ID>" + }, + "data": { + "type": "object", + "description": "Document data as JSON object.", + "default": [], + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "documents": { + "type": "array", + "description": "Array of documents data as JSON objects.", + "default": [], + "x-example": null, + "items": { + "type": "object" + } + } + } + } + } + ] + }, + "put": { + "summary": "Create or update documents", + "operationId": "databasesUpsertDocuments", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n", + "responses": { + "200": { + "description": "Documents List", + "schema": { + "$ref": "#\/definitions\/documentList" + } + } + }, + "x-appwrite": { + "method": "upsertDocuments", + "group": "documents", + "weight": 118, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-documents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-documents.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "documents": { + "type": "array", + "description": "Array of document data as JSON objects. May contain partial documents.", + "default": null, + "x-example": null, + "items": { + "type": "object" + } + } + }, + "required": [ + "documents" + ] + } + } + ] + }, + "patch": { + "summary": "Update documents", + "operationId": "databasesUpdateDocuments", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", + "responses": { + "200": { + "description": "Documents List", + "schema": { + "$ref": "#\/definitions\/documentList" + } + } + }, + "x-appwrite": { + "method": "updateDocuments", + "group": "documents", + "weight": 117, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-documents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-documents.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include only attribute and value pairs to be updated.", + "default": [], + "x-example": "{}" + }, + "queries": { + "type": "array", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + } + } + } + } + ] + }, + "delete": { + "summary": "Delete documents", + "operationId": "databasesDeleteDocuments", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Bulk delete documents using queries, if no queries are passed then all documents are deleted.", + "responses": { + "200": { + "description": "Documents List", + "schema": { + "$ref": "#\/definitions\/documentList" + } + } + }, + "x-appwrite": { + "method": "deleteDocuments", + "group": "documents", + "weight": 120, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-documents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-documents.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "queries": { + "type": "array", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + } + } + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}": { + "get": { + "summary": "Get document", + "operationId": "databasesGetDocument", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a document by its unique ID. This endpoint response returns a JSON object with the document data.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "getDocument", + "group": "documents", + "weight": 111, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-document.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "put": { + "summary": "Upsert document", + "operationId": "databasesUpsertDocument", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "upsertDocument", + "group": "documents", + "weight": 114, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include all required attributes of the document to be created or updated.", + "default": {}, + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "data" + ] + } + } + ] + }, + "patch": { + "summary": "Update document", + "operationId": "databasesUpdateDocument", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a document by its unique ID. Using the patch method you can pass only specific fields that will get updated.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "updateDocument", + "group": "documents", + "weight": 113, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include only attribute and value pairs to be updated.", + "default": [], + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + } + } + } + ] + }, + "delete": { + "summary": "Delete document", + "operationId": "databasesDeleteDocument", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "databases" + ], + "description": "Delete a document by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDocument", + "group": "documents", + "weight": 119, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-document.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/logs": { + "get": { + "summary": "List document logs", + "operationId": "databasesListDocumentLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get the document activity logs list by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "schema": { + "$ref": "#\/definitions\/logList" + } + } + }, + "x-appwrite": { + "method": "listDocumentLogs", + "group": "logs", + "weight": 112, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-document-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-document-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/decrement": { + "patch": { + "summary": "Decrement document attribute", + "operationId": "databasesDecrementDocumentAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Decrement a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "decrementDocumentAttribute", + "group": "documents", + "weight": 116, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/decrement-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/decrement-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to decrement the attribute by. The value must be a number.", + "default": 1, + "x-example": null + }, + "min": { + "type": "mixed", + "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", + "default": null, + "x-example": null + } + } + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/increment": { + "patch": { + "summary": "Increment document attribute", + "operationId": "databasesIncrementDocumentAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Increment a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "incrementDocumentAttribute", + "group": "documents", + "weight": 115, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/increment-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/increment-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to increment the attribute by. The value must be a number.", + "default": 1, + "x-example": null + }, + "max": { + "type": "mixed", + "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", + "default": null, + "x-example": null + } + } + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/indexes": { + "get": { + "summary": "List indexes", + "operationId": "databasesListIndexes", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "List indexes in the collection.", + "responses": { + "200": { + "description": "Indexes List", + "schema": { + "$ref": "#\/definitions\/indexList" + } + } + }, + "x-appwrite": { + "method": "listIndexes", + "group": "indexes", + "weight": 106, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-indexes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-indexes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: key, type, status, attributes, error", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create index", + "operationId": "databasesCreateIndex", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Creates an index on the attributes listed. Your index should include all the attributes you will query in a single request.\nAttributes can be `key`, `fulltext`, and `unique`.", + "responses": { + "202": { + "description": "Index", + "schema": { + "$ref": "#\/definitions\/index" + } + } + }, + "x-appwrite": { + "method": "createIndex", + "group": "collections", + "weight": 105, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-index.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-index.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Index Key.", + "default": null, + "x-example": null + }, + "type": { + "type": "string", + "description": "Index type.", + "default": null, + "x-example": "key", + "enum": [ + "key", + "fulltext", + "unique" + ], + "x-enum-name": "IndexType", + "x-enum-keys": [] + }, + "attributes": { + "type": "array", + "description": "Array of attributes to index. Maximum of 100 attributes are allowed, each 32 characters long.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "orders": { + "type": "array", + "description": "Array of index orders. Maximum of 100 orders are allowed.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "lengths": { + "type": "array", + "description": "Length of index. Maximum of 100", + "default": [], + "x-example": null, + "items": { + "type": "integer" + } + } + }, + "required": [ + "key", + "type", + "attributes" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/indexes\/{key}": { + "get": { + "summary": "Get index", + "operationId": "databasesGetIndex", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get index by ID.", + "responses": { + "200": { + "description": "Index", + "schema": { + "$ref": "#\/definitions\/index" + } + } + }, + "x-appwrite": { + "method": "getIndex", + "group": "indexes", + "weight": 107, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-index.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-index.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Index Key.", + "required": true, + "type": "string", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete index", + "operationId": "databasesDeleteIndex", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "databases" + ], + "description": "Delete an index.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteIndex", + "group": "indexes", + "weight": 108, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-index.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-index.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Index Key.", + "required": true, + "type": "string", + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/logs": { + "get": { + "summary": "List collection logs", + "operationId": "databasesListCollectionLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get the collection activity logs list by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "schema": { + "$ref": "#\/definitions\/logList" + } + } + }, + "x-appwrite": { + "method": "listCollectionLogs", + "group": "collections", + "weight": 79, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-collection-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-collection-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/usage": { + "get": { + "summary": "Get collection usage stats", + "operationId": "databasesGetCollectionUsage", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get usage metrics and statistics for a collection. Returning the total number of documents. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.", + "responses": { + "200": { + "description": "UsageCollection", + "schema": { + "$ref": "#\/definitions\/usageCollection" + } + } + }, + "x-appwrite": { + "method": "getCollectionUsage", + "group": null, + "weight": 123, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-collection-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-collection-usage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "range", + "description": "Date range.", + "required": false, + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "DatabaseUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d", + "in": "query" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/logs": { + "get": { + "summary": "List database logs", + "operationId": "databasesListLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get the database activity logs list by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "schema": { + "$ref": "#\/definitions\/logList" + } + } + }, + "x-appwrite": { + "method": "listLogs", + "group": "logs", + "weight": 73, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/databases\/{databaseId}\/usage": { + "get": { + "summary": "Get database usage stats", + "operationId": "databasesGetDatabaseUsage", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get usage metrics and statistics for a database. You can view the total number of collections, documents, and storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.", + "responses": { + "200": { + "description": "UsageDatabase", + "schema": { + "$ref": "#\/definitions\/usageDatabase" + } + } + }, + "x-appwrite": { + "method": "getDatabaseUsage", + "group": null, + "weight": 122, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-database-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-database-usage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "range", + "description": "`Date range.", + "required": false, + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "DatabaseUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d", + "in": "query" + } + ] + } + }, + "\/functions": { + "get": { + "summary": "List functions", + "operationId": "functionsList", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a list of all the project's functions. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Functions List", + "schema": { + "$ref": "#\/definitions\/functionList" + } + } + }, + "x-appwrite": { + "method": "list", + "group": "functions", + "weight": 378, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the project's functions. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, enabled, runtime, deploymentId, schedule, scheduleNext, schedulePrevious, timeout, entrypoint, commands, installationId", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create function", + "operationId": "functionsCreate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Create a new function. You can pass a list of [permissions](https:\/\/appwrite.io\/docs\/permissions) to allow different project users or team with access to execute the function using the client API.", + "responses": { + "201": { + "description": "Function", + "schema": { + "$ref": "#\/definitions\/function" + } + } + }, + "x-appwrite": { + "method": "create", + "group": "functions", + "weight": 375, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new function. You can pass a list of [permissions](https:\/\/appwrite.io\/docs\/permissions) to allow different project users or team with access to execute the function using the client API.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "functionId": { + "type": "string", + "description": "Function ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<FUNCTION_ID>" + }, + "name": { + "type": "string", + "description": "Function name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "runtime": { + "type": "string", + "description": "Execution runtime.", + "default": null, + "x-example": "node-14.5", + "enum": [ + "node-14.5", + "node-16.0", + "node-18.0", + "node-19.0", + "node-20.0", + "node-21.0", + "node-22", + "php-8.0", + "php-8.1", + "php-8.2", + "php-8.3", + "ruby-3.0", + "ruby-3.1", + "ruby-3.2", + "ruby-3.3", + "python-3.8", + "python-3.9", + "python-3.10", + "python-3.11", + "python-3.12", + "python-ml-3.11", + "python-ml-3.12", + "deno-1.21", + "deno-1.24", + "deno-1.35", + "deno-1.40", + "deno-1.46", + "deno-2.0", + "dart-2.15", + "dart-2.16", + "dart-2.17", + "dart-2.18", + "dart-2.19", + "dart-3.0", + "dart-3.1", + "dart-3.3", + "dart-3.5", + "dart-3.8", + "dotnet-6.0", + "dotnet-7.0", + "dotnet-8.0", + "java-8.0", + "java-11.0", + "java-17.0", + "java-18.0", + "java-21.0", + "java-22", + "swift-5.5", + "swift-5.8", + "swift-5.9", + "swift-5.10", + "kotlin-1.6", + "kotlin-1.8", + "kotlin-1.9", + "kotlin-2.0", + "cpp-17", + "cpp-20", + "bun-1.0", + "bun-1.1", + "go-1.23", + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29", + "flutter-3.32" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "execute": { + "type": "array", + "description": "An array of role strings with execution permissions. By default no user is granted with any execute permissions. [learn more about roles](https:\/\/appwrite.io\/docs\/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.", + "default": [], + "x-example": "[\"any\"]", + "items": { + "type": "string" + } + }, + "events": { + "type": "array", + "description": "Events list. Maximum of 100 events are allowed.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "schedule": { + "type": "string", + "description": "Schedule CRON syntax.", + "default": "", + "x-example": null + }, + "timeout": { + "type": "integer", + "description": "Function maximum execution time in seconds.", + "default": 15, + "x-example": 1 + }, + "enabled": { + "type": "boolean", + "description": "Is function enabled? When set to 'disabled', users cannot access the function but Server SDKs with and API key can still access the function. No data is lost when this is toggled.", + "default": true, + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", + "default": true, + "x-example": false + }, + "entrypoint": { + "type": "string", + "description": "Entrypoint File. This path is relative to the \"providerRootDirectory\".", + "default": "", + "x-example": "<ENTRYPOINT>" + }, + "commands": { + "type": "string", + "description": "Build Commands.", + "default": "", + "x-example": "<COMMANDS>" + }, + "scopes": { + "type": "array", + "description": "List of scopes allowed for API key auto-generated for every execution. Maximum of 100 scopes are allowed.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "installationId": { + "type": "string", + "description": "Appwrite Installation ID for VCS (Version Control System) deployment.", + "default": "", + "x-example": "<INSTALLATION_ID>" + }, + "providerRepositoryId": { + "type": "string", + "description": "Repository ID of the repo linked to the function.", + "default": "", + "x-example": "<PROVIDER_REPOSITORY_ID>" + }, + "providerBranch": { + "type": "string", + "description": "Production branch for the repo linked to the function.", + "default": "", + "x-example": "<PROVIDER_BRANCH>" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is the VCS (Version Control System) connection in silent mode for the repo linked to the function? In silent mode, comments will not be made on commits and pull requests.", + "default": false, + "x-example": false + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to function code in the linked repo.", + "default": "", + "x-example": "<PROVIDER_ROOT_DIRECTORY>" + }, + "specification": { + "type": "string", + "description": "Runtime specification for the function and builds.", + "default": "s-1vcpu-512mb", + "x-example": null + } + }, + "required": [ + "functionId", + "name", + "runtime" + ] + } + } + ] + } + }, + "\/functions\/runtimes": { + "get": { + "summary": "List runtimes", + "operationId": "functionsListRuntimes", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a list of all runtimes that are currently active on your instance.", + "responses": { + "200": { + "description": "Runtimes List", + "schema": { + "$ref": "#\/definitions\/runtimeList" + } + } + }, + "x-appwrite": { + "method": "listRuntimes", + "group": "runtimes", + "weight": 380, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-runtimes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all runtimes that are currently active on your instance.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/functions\/specifications": { + "get": { + "summary": "List specifications", + "operationId": "functionsListSpecifications", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "List allowed function specifications for this instance.", + "responses": { + "200": { + "description": "Specifications List", + "schema": { + "$ref": "#\/definitions\/specificationList" + } + } + }, + "x-appwrite": { + "method": "listSpecifications", + "group": "runtimes", + "weight": 381, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-specifications.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList allowed function specifications for this instance.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/functions\/templates": { + "get": { + "summary": "List templates", + "operationId": "functionsListTemplates", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "List available function templates. You can use template details in [createFunction](\/docs\/references\/cloud\/server-nodejs\/functions#create) method.", + "responses": { + "200": { + "description": "Function Templates List", + "schema": { + "$ref": "#\/definitions\/templateFunctionList" + } + } + }, + "x-appwrite": { + "method": "listTemplates", + "group": "templates", + "weight": 404, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-templates.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList available function templates. You can use template details in [createFunction](\/docs\/references\/cloud\/server-nodejs\/functions#create) method.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "runtimes", + "description": "List of runtimes allowed for filtering function templates. Maximum of 100 runtimes are allowed.", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "useCases", + "description": "List of use cases allowed for filtering function templates. Maximum of 100 use cases are allowed.", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "limit", + "description": "Limit the number of templates returned in the response. Default limit is 25, and maximum limit is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 1, + "default": 25, + "in": "query" + }, + { + "name": "offset", + "description": "Offset the list of returned templates. Maximum offset is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0, + "in": "query" + } + ] + } + }, + "\/functions\/templates\/{templateId}": { + "get": { + "summary": "Get function template", + "operationId": "functionsGetTemplate", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a function template using ID. You can use template details in [createFunction](\/docs\/references\/cloud\/server-nodejs\/functions#create) method.", + "responses": { + "200": { + "description": "Template Function", + "schema": { + "$ref": "#\/definitions\/templateFunction" + } + } + }, + "x-appwrite": { + "method": "getTemplate", + "group": "templates", + "weight": 403, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get-template.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function template using ID. You can use template details in [createFunction](\/docs\/references\/cloud\/server-nodejs\/functions#create) method.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "templateId", + "description": "Template ID.", + "required": true, + "type": "string", + "x-example": "<TEMPLATE_ID>", + "in": "path" + } + ] + } + }, + "\/functions\/usage": { + "get": { + "summary": "Get functions usage", + "operationId": "functionsListUsage", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get usage metrics and statistics for all functions in the project. View statistics including total deployments, builds, logs, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", + "responses": { + "200": { + "description": "UsageFunctions", + "schema": { + "$ref": "#\/definitions\/usageFunctions" + } + } + }, + "x-appwrite": { + "method": "listUsage", + "group": null, + "weight": 397, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet usage metrics and statistics for all functions in the project. View statistics including total deployments, builds, logs, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "range", + "description": "Date range.", + "required": false, + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "FunctionUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d", + "in": "query" + } + ] + } + }, + "\/functions\/{functionId}": { + "get": { + "summary": "Get function", + "operationId": "functionsGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a function by its unique ID.", + "responses": { + "200": { + "description": "Function", + "schema": { + "$ref": "#\/definitions\/function" + } + } + }, + "x-appwrite": { + "method": "get", + "group": "functions", + "weight": 376, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update function", + "operationId": "functionsUpdate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Update function by its unique ID.", + "responses": { + "200": { + "description": "Function", + "schema": { + "$ref": "#\/definitions\/function" + } + } + }, + "x-appwrite": { + "method": "update", + "group": "functions", + "weight": 377, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/update.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate function by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Function name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "runtime": { + "type": "string", + "description": "Execution runtime.", + "default": "", + "x-example": "node-14.5", + "enum": [ + "node-14.5", + "node-16.0", + "node-18.0", + "node-19.0", + "node-20.0", + "node-21.0", + "node-22", + "php-8.0", + "php-8.1", + "php-8.2", + "php-8.3", + "ruby-3.0", + "ruby-3.1", + "ruby-3.2", + "ruby-3.3", + "python-3.8", + "python-3.9", + "python-3.10", + "python-3.11", + "python-3.12", + "python-ml-3.11", + "python-ml-3.12", + "deno-1.21", + "deno-1.24", + "deno-1.35", + "deno-1.40", + "deno-1.46", + "deno-2.0", + "dart-2.15", + "dart-2.16", + "dart-2.17", + "dart-2.18", + "dart-2.19", + "dart-3.0", + "dart-3.1", + "dart-3.3", + "dart-3.5", + "dart-3.8", + "dotnet-6.0", + "dotnet-7.0", + "dotnet-8.0", + "java-8.0", + "java-11.0", + "java-17.0", + "java-18.0", + "java-21.0", + "java-22", + "swift-5.5", + "swift-5.8", + "swift-5.9", + "swift-5.10", + "kotlin-1.6", + "kotlin-1.8", + "kotlin-1.9", + "kotlin-2.0", + "cpp-17", + "cpp-20", + "bun-1.0", + "bun-1.1", + "go-1.23", + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29", + "flutter-3.32" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "execute": { + "type": "array", + "description": "An array of role strings with execution permissions. By default no user is granted with any execute permissions. [learn more about roles](https:\/\/appwrite.io\/docs\/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.", + "default": [], + "x-example": "[\"any\"]", + "items": { + "type": "string" + } + }, + "events": { + "type": "array", + "description": "Events list. Maximum of 100 events are allowed.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "schedule": { + "type": "string", + "description": "Schedule CRON syntax.", + "default": "", + "x-example": null + }, + "timeout": { + "type": "integer", + "description": "Maximum execution time in seconds.", + "default": 15, + "x-example": 1 + }, + "enabled": { + "type": "boolean", + "description": "Is function enabled? When set to 'disabled', users cannot access the function but Server SDKs with and API key can still access the function. No data is lost when this is toggled.", + "default": true, + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", + "default": true, + "x-example": false + }, + "entrypoint": { + "type": "string", + "description": "Entrypoint File. This path is relative to the \"providerRootDirectory\".", + "default": "", + "x-example": "<ENTRYPOINT>" + }, + "commands": { + "type": "string", + "description": "Build Commands.", + "default": "", + "x-example": "<COMMANDS>" + }, + "scopes": { + "type": "array", + "description": "List of scopes allowed for API Key auto-generated for every execution. Maximum of 100 scopes are allowed.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "installationId": { + "type": "string", + "description": "Appwrite Installation ID for VCS (Version Controle System) deployment.", + "default": "", + "x-example": "<INSTALLATION_ID>" + }, + "providerRepositoryId": { + "type": "string", + "description": "Repository ID of the repo linked to the function", + "default": null, + "x-example": "<PROVIDER_REPOSITORY_ID>", + "x-nullable": true + }, + "providerBranch": { + "type": "string", + "description": "Production branch for the repo linked to the function", + "default": "", + "x-example": "<PROVIDER_BRANCH>" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is the VCS (Version Control System) connection in silent mode for the repo linked to the function? In silent mode, comments will not be made on commits and pull requests.", + "default": false, + "x-example": false + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to function code in the linked repo.", + "default": "", + "x-example": "<PROVIDER_ROOT_DIRECTORY>" + }, + "specification": { + "type": "string", + "description": "Runtime specification for the function and builds.", + "default": "s-1vcpu-512mb", + "x-example": null + } + }, + "required": [ + "name" + ] + } + } + ] + }, + "delete": { + "summary": "Delete function", + "operationId": "functionsDelete", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "functions" + ], + "description": "Delete a function by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "functions", + "weight": 379, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a function by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + } + ] + } + }, + "\/functions\/{functionId}\/deployment": { + "patch": { + "summary": "Update function's deployment", + "operationId": "functionsUpdateFunctionDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Update the function active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your function.", + "responses": { + "200": { + "description": "Function", + "schema": { + "$ref": "#\/definitions\/function" + } + } + }, + "x-appwrite": { + "method": "updateFunctionDeployment", + "group": "functions", + "weight": 384, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/update-function-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate the function active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your function.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "deploymentId": { + "type": "string", + "description": "Deployment ID.", + "default": null, + "x-example": "<DEPLOYMENT_ID>" + } + }, + "required": [ + "deploymentId" + ] + } + } + ] + } + }, + "\/functions\/{functionId}\/deployments": { + "get": { + "summary": "List deployments", + "operationId": "functionsListDeployments", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a list of all the function's code deployments. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Deployments List", + "schema": { + "$ref": "#\/definitions\/deploymentList" + } + } + }, + "x-appwrite": { + "method": "listDeployments", + "group": "deployments", + "weight": 385, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-deployments.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the function's code deployments. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create deployment", + "operationId": "functionsCreateDeployment", + "consumes": [ + "multipart\/form-data" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Create a new function code deployment. Use this endpoint to upload a new version of your code function. To execute your newly uploaded code, you'll need to update the function's deployment to use your new deployment UID.\n\nThis endpoint accepts a tar.gz file compressed with your code. Make sure to include any dependencies your code has within the compressed file. You can learn more about code packaging in the [Appwrite Cloud Functions tutorial](https:\/\/appwrite.io\/docs\/functions).\n\nUse the \"command\" param to set the entrypoint used to execute your code.", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createDeployment", + "group": "deployments", + "weight": 382, + "cookies": false, + "type": "upload", + "deprecated": false, + "demo": "functions\/create-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new function code deployment. Use this endpoint to upload a new version of your code function. To execute your newly uploaded code, you'll need to update the function's deployment to use your new deployment UID.\n\nThis endpoint accepts a tar.gz file compressed with your code. Make sure to include any dependencies your code has within the compressed file. You can learn more about code packaging in the [Appwrite Cloud Functions tutorial](https:\/\/appwrite.io\/docs\/functions).\n\nUse the \"command\" param to set the entrypoint used to execute your code.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": true, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "entrypoint", + "description": "Entrypoint File.", + "required": false, + "type": "string", + "x-example": "<ENTRYPOINT>", + "in": "formData" + }, + { + "name": "commands", + "description": "Build Commands.", + "required": false, + "type": "string", + "x-example": "<COMMANDS>", + "in": "formData" + }, + { + "name": "code", + "description": "Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.", + "required": true, + "type": "file", + "in": "formData" + }, + { + "name": "activate", + "description": "Automatically activate the deployment when it is finished building.", + "required": true, + "type": "boolean", + "x-example": false, + "in": "formData" + } + ] + } + }, + "\/functions\/{functionId}\/deployments\/duplicate": { + "post": { + "summary": "Create duplicate deployment", + "operationId": "functionsCreateDuplicateDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Create a new build for an existing function deployment. This endpoint allows you to rebuild a deployment with the updated function configuration, including its entrypoint and build commands if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createDuplicateDeployment", + "group": "deployments", + "weight": 390, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-duplicate-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new build for an existing function deployment. This endpoint allows you to rebuild a deployment with the updated function configuration, including its entrypoint and build commands if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "deploymentId": { + "type": "string", + "description": "Deployment ID.", + "default": null, + "x-example": "<DEPLOYMENT_ID>" + }, + "buildId": { + "type": "string", + "description": "Build unique ID.", + "default": "", + "x-example": "<BUILD_ID>" + } + }, + "required": [ + "deploymentId" + ] + } + } + ] + } + }, + "\/functions\/{functionId}\/deployments\/template": { + "post": { + "summary": "Create template deployment", + "operationId": "functionsCreateTemplateDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Create a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/functions#listTemplates) to find the template details.", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createTemplateDeployment", + "group": "deployments", + "weight": 387, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-template-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/functions#listTemplates) to find the template details.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "repository": { + "type": "string", + "description": "Repository name of the template.", + "default": null, + "x-example": "<REPOSITORY>" + }, + "owner": { + "type": "string", + "description": "The name of the owner of the template.", + "default": null, + "x-example": "<OWNER>" + }, + "rootDirectory": { + "type": "string", + "description": "Path to function code in the template repo.", + "default": null, + "x-example": "<ROOT_DIRECTORY>" + }, + "version": { + "type": "string", + "description": "Version (tag) for the repo linked to the function template.", + "default": null, + "x-example": "<VERSION>" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "default": false, + "x-example": false + } + }, + "required": [ + "repository", + "owner", + "rootDirectory", + "version" + ] + } + } + ] + } + }, + "\/functions\/{functionId}\/deployments\/vcs": { + "post": { + "summary": "Create VCS deployment", + "operationId": "functionsCreateVcsDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Create a deployment when a function is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createVcsDeployment", + "group": "deployments", + "weight": 388, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-vcs-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment when a function is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Type of reference passed. Allowed values are: branch, commit", + "default": null, + "x-example": "branch", + "enum": [ + "branch", + "commit" + ], + "x-enum-name": "VCSDeploymentType", + "x-enum-keys": [] + }, + "reference": { + "type": "string", + "description": "VCS reference to create deployment from. Depending on type this can be: branch name, commit hash", + "default": null, + "x-example": "<REFERENCE>" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "default": false, + "x-example": false + } + }, + "required": [ + "type", + "reference" + ] + } + } + ] + } + }, + "\/functions\/{functionId}\/deployments\/{deploymentId}": { + "get": { + "summary": "Get deployment", + "operationId": "functionsGetDeployment", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a function deployment by its unique ID.", + "responses": { + "200": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "getDeployment", + "group": "deployments", + "weight": 383, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function deployment by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "type": "string", + "x-example": "<DEPLOYMENT_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete deployment", + "operationId": "functionsDeleteDeployment", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "functions" + ], + "description": "Delete a code deployment by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDeployment", + "group": "deployments", + "weight": 386, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/delete-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a code deployment by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "type": "string", + "x-example": "<DEPLOYMENT_ID>", + "in": "path" + } + ] + } + }, + "\/functions\/{functionId}\/deployments\/{deploymentId}\/download": { + "get": { + "summary": "Get deployment download", + "operationId": "functionsGetDeploymentDownload", + "consumes": [], + "produces": [ + "*\/*" + ], + "tags": [ + "functions" + ], + "description": "Get a function deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "responses": { + "200": { + "description": "File", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getDeploymentDownload", + "group": "deployments", + "weight": 389, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "functions\/get-deployment-download.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "type": "string", + "x-example": "<DEPLOYMENT_ID>", + "in": "path" + }, + { + "name": "type", + "description": "Deployment file to download. Can be: \"source\", \"output\".", + "required": false, + "type": "string", + "x-example": "source", + "enum": [ + "source", + "output" + ], + "x-enum-name": "DeploymentDownloadType", + "x-enum-keys": [], + "default": "source", + "in": "query" + } + ] + } + }, + "\/functions\/{functionId}\/deployments\/{deploymentId}\/status": { + "patch": { + "summary": "Update deployment status", + "operationId": "functionsUpdateDeploymentStatus", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Cancel an ongoing function deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", + "responses": { + "200": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "updateDeploymentStatus", + "group": "deployments", + "weight": 391, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/update-deployment-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCancel an ongoing function deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "type": "string", + "x-example": "<DEPLOYMENT_ID>", + "in": "path" + } + ] + } + }, + "\/functions\/{functionId}\/executions": { + "get": { + "summary": "List executions", + "operationId": "functionsListExecutions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a list of all the current user function execution logs. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Executions List", + "schema": { + "$ref": "#\/definitions\/executionList" + } + } + }, + "x-appwrite": { + "method": "listExecutions", + "group": "executions", + "weight": 394, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-executions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the current user function execution logs. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: trigger, status, responseStatusCode, duration, requestMethod, requestPath, deploymentId", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create execution", + "operationId": "functionsCreateExecution", + "consumes": [ + "application\/json" + ], + "produces": [ + "multipart\/form-data" + ], + "tags": [ + "functions" + ], + "description": "Trigger a function execution. The returned object will return you the current execution status. You can ping the `Get Execution` endpoint to get updates on the current execution status. Once this endpoint is called, your function execution process will start asynchronously.", + "responses": { + "201": { + "description": "Execution", + "schema": { + "$ref": "#\/definitions\/execution" + } + } + }, + "x-appwrite": { + "method": "createExecution", + "group": "executions", + "weight": 392, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-execution.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterTrigger a function execution. The returned object will return you the current execution status. You can ping the `Get Execution` endpoint to get updates on the current execution status. Once this endpoint is called, your function execution process will start asynchronously.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "body": { + "type": "string", + "description": "HTTP body of execution. Default value is empty string.", + "default": "", + "x-example": "<BODY>" + }, + "async": { + "type": "boolean", + "description": "Execute code in the background. Default value is false.", + "default": false, + "x-example": false + }, + "path": { + "type": "string", + "description": "HTTP path of execution. Path can include query params. Default value is \/", + "default": "\/", + "x-example": "<PATH>" + }, + "method": { + "type": "string", + "description": "HTTP method of execution. Default value is GET.", + "default": "POST", + "x-example": "GET", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE", + "OPTIONS" + ], + "x-enum-name": "ExecutionMethod", + "x-enum-keys": [] + }, + "headers": { + "type": "object", + "description": "HTTP headers of execution. Defaults to empty.", + "default": [], + "x-example": "{}" + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled execution time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes.", + "default": null, + "x-example": null + } + } + } + } + ] + } + }, + "\/functions\/{functionId}\/executions\/{executionId}": { + "get": { + "summary": "Get execution", + "operationId": "functionsGetExecution", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a function execution log by its unique ID.", + "responses": { + "200": { + "description": "Execution", + "schema": { + "$ref": "#\/definitions\/execution" + } + } + }, + "x-appwrite": { + "method": "getExecution", + "group": "executions", + "weight": 393, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get-execution.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function execution log by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "executionId", + "description": "Execution ID.", + "required": true, + "type": "string", + "x-example": "<EXECUTION_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete execution", + "operationId": "functionsDeleteExecution", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "functions" + ], + "description": "Delete a function execution by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteExecution", + "group": "executions", + "weight": 395, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/delete-execution.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a function execution by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "executionId", + "description": "Execution ID.", + "required": true, + "type": "string", + "x-example": "<EXECUTION_ID>", + "in": "path" + } + ] + } + }, + "\/functions\/{functionId}\/usage": { + "get": { + "summary": "Get function usage", + "operationId": "functionsGetUsage", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get usage metrics and statistics for a for a specific function. View statistics including total deployments, builds, executions, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", + "responses": { + "200": { + "description": "UsageFunction", + "schema": { + "$ref": "#\/definitions\/usageFunction" + } + } + }, + "x-appwrite": { + "method": "getUsage", + "group": null, + "weight": 396, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet usage metrics and statistics for a for a specific function. View statistics including total deployments, builds, executions, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "range", + "description": "Date range.", + "required": false, + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "FunctionUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d", + "in": "query" + } + ] + } + }, + "\/functions\/{functionId}\/variables": { + "get": { + "summary": "List variables", + "operationId": "functionsListVariables", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a list of all variables of a specific function.", + "responses": { + "200": { + "description": "Variables List", + "schema": { + "$ref": "#\/definitions\/variableList" + } + } + }, + "x-appwrite": { + "method": "listVariables", + "group": "variables", + "weight": 400, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-variables.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all variables of a specific function.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + } + ] + }, + "post": { + "summary": "Create variable", + "operationId": "functionsCreateVariable", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Create a new function environment variable. These variables can be accessed in the function at runtime as environment variables.", + "responses": { + "201": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "createVariable", + "group": "variables", + "weight": 398, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new function environment variable. These variables can be accessed in the function at runtime as environment variables.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "default": null, + "x-example": "<KEY>" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "default": null, + "x-example": "<VALUE>" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only functions can read them during build and runtime.", + "default": true, + "x-example": false + } + }, + "required": [ + "key", + "value" + ] + } + } + ] + } + }, + "\/functions\/{functionId}\/variables\/{variableId}": { + "get": { + "summary": "Get variable", + "operationId": "functionsGetVariable", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a variable by its unique ID.", + "responses": { + "200": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "getVariable", + "group": "variables", + "weight": 399, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "type": "string", + "x-example": "<VARIABLE_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update variable", + "operationId": "functionsUpdateVariable", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Update variable by its unique ID.", + "responses": { + "200": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "updateVariable", + "group": "variables", + "weight": 401, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/update-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "type": "string", + "x-example": "<VARIABLE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "default": null, + "x-example": "<KEY>" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "default": null, + "x-example": "<VALUE>" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only functions can read them during build and runtime.", + "default": null, + "x-example": false + } + }, + "required": [ + "key" + ] + } + } + ] + }, + "delete": { + "summary": "Delete variable", + "operationId": "functionsDeleteVariable", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "functions" + ], + "description": "Delete a variable by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteVariable", + "group": "variables", + "weight": 402, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/delete-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "type": "string", + "x-example": "<VARIABLE_ID>", + "in": "path" + } + ] + } + }, + "\/graphql": { + "post": { + "summary": "GraphQL endpoint", + "operationId": "graphqlQuery", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "graphql" + ], + "description": "Execute a GraphQL mutation.", + "responses": { + "200": { + "description": "Any", + "schema": { + "$ref": "#\/definitions\/any" + } + } + }, + "x-appwrite": { + "method": "query", + "group": "graphql", + "weight": 308, + "cookies": false, + "type": "graphql", + "deprecated": false, + "demo": "graphql\/query.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/graphql\/post.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "url:{url},ip:{ip}", + "scope": "graphql", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "query": { + "type": "object", + "description": "The query or queries to execute.", + "default": {}, + "x-example": "{}" + } + }, + "required": [ + "query" + ] + } + } + ] + } + }, + "\/graphql\/mutation": { + "post": { + "summary": "GraphQL endpoint", + "operationId": "graphqlMutation", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "graphql" + ], + "description": "Execute a GraphQL mutation.", + "responses": { + "200": { + "description": "Any", + "schema": { + "$ref": "#\/definitions\/any" + } + } + }, + "x-appwrite": { + "method": "mutation", + "group": "graphql", + "weight": 307, + "cookies": false, + "type": "graphql", + "deprecated": false, + "demo": "graphql\/mutation.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/graphql\/post.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "url:{url},ip:{ip}", + "scope": "graphql", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "query": { + "type": "object", + "description": "The query or queries to execute.", + "default": {}, + "x-example": "{}" + } + }, + "required": [ + "query" + ] + } + } + ] + } + }, + "\/health": { + "get": { + "summary": "Get HTTP", + "operationId": "healthGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Check the Appwrite HTTP server is up and responsive.", + "responses": { + "200": { + "description": "Health Status", + "schema": { + "$ref": "#\/definitions\/healthStatus" + } + } + }, + "x-appwrite": { + "method": "get", + "group": "health", + "weight": 132, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/anti-virus": { + "get": { + "summary": "Get antivirus", + "operationId": "healthGetAntivirus", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Check the Appwrite Antivirus server is up and connection is successful.", + "responses": { + "200": { + "description": "Health Antivirus", + "schema": { + "$ref": "#\/definitions\/healthAntivirus" + } + } + }, + "x-appwrite": { + "method": "getAntivirus", + "group": "health", + "weight": 153, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-antivirus.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-storage-anti-virus.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/cache": { + "get": { + "summary": "Get cache", + "operationId": "healthGetCache", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Check the Appwrite in-memory cache servers are up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "schema": { + "$ref": "#\/definitions\/healthStatus" + } + } + }, + "x-appwrite": { + "method": "getCache", + "group": "health", + "weight": 135, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-cache.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-cache.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/certificate": { + "get": { + "summary": "Get the SSL certificate for a domain", + "operationId": "healthGetCertificate", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the SSL certificate for a domain", + "responses": { + "200": { + "description": "Health Certificate", + "schema": { + "$ref": "#\/definitions\/healthCertificate" + } + } + }, + "x-appwrite": { + "method": "getCertificate", + "group": "health", + "weight": 140, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-certificate.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-certificate.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "domain", + "description": "string", + "required": false, + "type": "string", + "in": "query" + } + ] + } + }, + "\/health\/db": { + "get": { + "summary": "Get DB", + "operationId": "healthGetDB", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Check the Appwrite database servers are up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "schema": { + "$ref": "#\/definitions\/healthStatus" + } + } + }, + "x-appwrite": { + "method": "getDB", + "group": "health", + "weight": 134, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-d-b.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-db.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/pubsub": { + "get": { + "summary": "Get pubsub", + "operationId": "healthGetPubSub", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Check the Appwrite pub-sub servers are up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "schema": { + "$ref": "#\/definitions\/healthStatus" + } + } + }, + "x-appwrite": { + "method": "getPubSub", + "group": "health", + "weight": 136, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-pub-sub.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-pubsub.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/queue\/builds": { + "get": { + "summary": "Get builds queue", + "operationId": "healthGetQueueBuilds", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of builds that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueBuilds", + "group": "queue", + "weight": 142, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-builds.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-builds.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/certificates": { + "get": { + "summary": "Get certificates queue", + "operationId": "healthGetQueueCertificates", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of certificates that are waiting to be issued against [Letsencrypt](https:\/\/letsencrypt.org\/) in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueCertificates", + "group": "queue", + "weight": 141, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-certificates.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-certificates.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/databases": { + "get": { + "summary": "Get databases queue", + "operationId": "healthGetQueueDatabases", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of database changes that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueDatabases", + "group": "queue", + "weight": 143, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-databases.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-databases.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "name", + "description": "Queue name for which to check the queue size", + "required": false, + "type": "string", + "x-example": "<NAME>", + "default": "database_db_main", + "in": "query" + }, + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/deletes": { + "get": { + "summary": "Get deletes queue", + "operationId": "healthGetQueueDeletes", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of background destructive changes that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueDeletes", + "group": "queue", + "weight": 144, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-deletes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-deletes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/failed\/{name}": { + "get": { + "summary": "Get number of failed queue jobs", + "operationId": "healthGetFailedJobs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Returns the amount of failed jobs in a given queue.\n", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getFailedJobs", + "group": "queue", + "weight": 154, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-failed-jobs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-failed-queue-jobs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "name", + "description": "The name of the queue", + "required": true, + "type": "string", + "x-example": "v1-database", + "enum": [ + "v1-database", + "v1-deletes", + "v1-audits", + "v1-mails", + "v1-functions", + "v1-stats-resources", + "v1-stats-usage", + "v1-webhooks", + "v1-certificates", + "v1-builds", + "v1-messaging", + "v1-migrations" + ], + "x-enum-name": null, + "x-enum-keys": [], + "in": "path" + }, + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/functions": { + "get": { + "summary": "Get functions queue", + "operationId": "healthGetQueueFunctions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of function executions that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueFunctions", + "group": "queue", + "weight": 148, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-functions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-functions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/logs": { + "get": { + "summary": "Get logs queue", + "operationId": "healthGetQueueLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of logs that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueLogs", + "group": "queue", + "weight": 139, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/mails": { + "get": { + "summary": "Get mails queue", + "operationId": "healthGetQueueMails", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of mails that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueMails", + "group": "queue", + "weight": 145, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-mails.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-mails.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/messaging": { + "get": { + "summary": "Get messaging queue", + "operationId": "healthGetQueueMessaging", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of messages that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueMessaging", + "group": "queue", + "weight": 146, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-messaging.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-messaging.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/migrations": { + "get": { + "summary": "Get migrations queue", + "operationId": "healthGetQueueMigrations", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of migrations that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueMigrations", + "group": "queue", + "weight": 147, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-migrations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-migrations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/stats-resources": { + "get": { + "summary": "Get stats resources queue", + "operationId": "healthGetQueueStatsResources", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of metrics that are waiting to be processed in the Appwrite stats resources queue.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueStatsResources", + "group": "queue", + "weight": 149, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-stats-resources.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-resources.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/stats-usage": { + "get": { + "summary": "Get stats usage queue", + "operationId": "healthGetQueueUsage", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of metrics that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueUsage", + "group": "queue", + "weight": 150, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-usage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/webhooks": { + "get": { + "summary": "Get webhooks queue", + "operationId": "healthGetQueueWebhooks", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of webhooks that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueWebhooks", + "group": "queue", + "weight": 138, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-webhooks.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-webhooks.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/storage": { + "get": { + "summary": "Get storage", + "operationId": "healthGetStorage", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Check the Appwrite storage device is up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "schema": { + "$ref": "#\/definitions\/healthStatus" + } + } + }, + "x-appwrite": { + "method": "getStorage", + "group": "storage", + "weight": 152, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-storage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-storage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/storage\/local": { + "get": { + "summary": "Get local storage", + "operationId": "healthGetStorageLocal", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Check the Appwrite local storage device is up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "schema": { + "$ref": "#\/definitions\/healthStatus" + } + } + }, + "x-appwrite": { + "method": "getStorageLocal", + "group": "storage", + "weight": 151, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-storage-local.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-storage-local.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/time": { + "get": { + "summary": "Get time", + "operationId": "healthGetTime", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Check the Appwrite server time is synced with Google remote NTP server. We use this technology to smoothly handle leap seconds with no disruptive events. The [Network Time Protocol](https:\/\/en.wikipedia.org\/wiki\/Network_Time_Protocol) (NTP) is used by hundreds of millions of computers and devices to synchronize their clocks over the Internet. If your computer sets its own clock, it likely uses NTP.", + "responses": { + "200": { + "description": "Health Time", + "schema": { + "$ref": "#\/definitions\/healthTime" + } + } + }, + "x-appwrite": { + "method": "getTime", + "group": "health", + "weight": 137, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-time.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-time.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/locale": { + "get": { + "summary": "Get user locale", + "operationId": "localeGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "Get the current user location based on IP. Returns an object with user country code, country name, continent name, continent code, ip address and suggested currency. You can use the locale header to get the data in a supported language.\n\n([IP Geolocation by DB-IP](https:\/\/db-ip.com))", + "responses": { + "200": { + "description": "Locale", + "schema": { + "$ref": "#\/definitions\/locale" + } + } + }, + "x-appwrite": { + "method": "get", + "group": null, + "weight": 124, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/get-locale.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/codes": { + "get": { + "summary": "List locale codes", + "operationId": "localeListCodes", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all locale codes in [ISO 639-1](https:\/\/en.wikipedia.org\/wiki\/List_of_ISO_639-1_codes).", + "responses": { + "200": { + "description": "Locale codes list", + "schema": { + "$ref": "#\/definitions\/localeCodeList" + } + } + }, + "x-appwrite": { + "method": "listCodes", + "group": null, + "weight": 125, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-locale-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/continents": { + "get": { + "summary": "List continents", + "operationId": "localeListContinents", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all continents. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Continents List", + "schema": { + "$ref": "#\/definitions\/continentList" + } + } + }, + "x-appwrite": { + "method": "listContinents", + "group": null, + "weight": 129, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-continents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-continents.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/countries": { + "get": { + "summary": "List countries", + "operationId": "localeListCountries", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all countries. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Countries List", + "schema": { + "$ref": "#\/definitions\/countryList" + } + } + }, + "x-appwrite": { + "method": "listCountries", + "group": null, + "weight": 126, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-countries.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-countries.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/countries\/eu": { + "get": { + "summary": "List EU countries", + "operationId": "localeListCountriesEU", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all countries that are currently members of the EU. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Countries List", + "schema": { + "$ref": "#\/definitions\/countryList" + } + } + }, + "x-appwrite": { + "method": "listCountriesEU", + "group": null, + "weight": 127, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-countries-e-u.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-countries-eu.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/countries\/phones": { + "get": { + "summary": "List countries phone codes", + "operationId": "localeListCountriesPhones", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all countries phone codes. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Phones List", + "schema": { + "$ref": "#\/definitions\/phoneList" + } + } + }, + "x-appwrite": { + "method": "listCountriesPhones", + "group": null, + "weight": 128, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-countries-phones.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-countries-phones.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/currencies": { + "get": { + "summary": "List currencies", + "operationId": "localeListCurrencies", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all currencies, including currency symbol, name, plural, and decimal digits for all major and minor currencies. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Currencies List", + "schema": { + "$ref": "#\/definitions\/currencyList" + } + } + }, + "x-appwrite": { + "method": "listCurrencies", + "group": null, + "weight": 130, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-currencies.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-currencies.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/languages": { + "get": { + "summary": "List languages", + "operationId": "localeListLanguages", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all languages classified by ISO 639-1 including 2-letter code, name in English, and name in the respective language.", + "responses": { + "200": { + "description": "Languages List", + "schema": { + "$ref": "#\/definitions\/languageList" + } + } + }, + "x-appwrite": { + "method": "listLanguages", + "group": null, + "weight": 131, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-languages.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-languages.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/messaging\/messages": { + "get": { + "summary": "List messages", + "operationId": "messagingListMessages", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get a list of all messages from the current Appwrite project.", + "responses": { + "200": { + "description": "Message list", + "schema": { + "$ref": "#\/definitions\/messageList" + } + } + }, + "x-appwrite": { + "method": "listMessages", + "group": "messages", + "weight": 362, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-messages.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-messages.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: scheduledAt, deliveredAt, deliveredTotal, status, description, providerType", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + } + }, + "\/messaging\/messages\/email": { + "post": { + "summary": "Create email", + "operationId": "messagingCreateEmail", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new email message.", + "responses": { + "201": { + "description": "Message", + "schema": { + "$ref": "#\/definitions\/message" + } + } + }, + "x-appwrite": { + "method": "createEmail", + "group": "messages", + "weight": 359, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-email.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "messageId": { + "type": "string", + "description": "Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<MESSAGE_ID>" + }, + "subject": { + "type": "string", + "description": "Email Subject.", + "default": null, + "x-example": "<SUBJECT>" + }, + "content": { + "type": "string", + "description": "Email Content.", + "default": null, + "x-example": "<CONTENT>" + }, + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "cc": { + "type": "array", + "description": "Array of target IDs to be added as CC.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "bcc": { + "type": "array", + "description": "Array of target IDs to be added as BCC.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "attachments": { + "type": "array", + "description": "Array of compound ID strings of bucket IDs and file IDs to be attached to the email. They should be formatted as <BUCKET_ID>:<FILE_ID>.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "default": false, + "x-example": false + }, + "html": { + "type": "boolean", + "description": "Is content of type HTML", + "default": false, + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "default": null, + "x-example": null + } + }, + "required": [ + "messageId", + "subject", + "content" + ] + } + } + ] + } + }, + "\/messaging\/messages\/email\/{messageId}": { + "patch": { + "summary": "Update email", + "operationId": "messagingUpdateEmail", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update an email message by its unique ID. This endpoint only works on messages that are in draft status. Messages that are already processing, sent, or failed cannot be updated.\n", + "responses": { + "200": { + "description": "Message", + "schema": { + "$ref": "#\/definitions\/message" + } + } + }, + "x-appwrite": { + "method": "updateEmail", + "group": "messages", + "weight": 366, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-email.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "type": "string", + "x-example": "<MESSAGE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "subject": { + "type": "string", + "description": "Email Subject.", + "default": null, + "x-example": "<SUBJECT>" + }, + "content": { + "type": "string", + "description": "Email Content.", + "default": null, + "x-example": "<CONTENT>" + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "default": null, + "x-example": false + }, + "html": { + "type": "boolean", + "description": "Is content of type HTML", + "default": null, + "x-example": false + }, + "cc": { + "type": "array", + "description": "Array of target IDs to be added as CC.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "bcc": { + "type": "array", + "description": "Array of target IDs to be added as BCC.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "default": null, + "x-example": null + }, + "attachments": { + "type": "array", + "description": "Array of compound ID strings of bucket IDs and file IDs to be attached to the email. They should be formatted as <BUCKET_ID>:<FILE_ID>.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + } + } + } + } + ] + } + }, + "\/messaging\/messages\/push": { + "post": { + "summary": "Create push notification", + "operationId": "messagingCreatePush", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new push notification.", + "responses": { + "201": { + "description": "Message", + "schema": { + "$ref": "#\/definitions\/message" + } + } + }, + "x-appwrite": { + "method": "createPush", + "group": "messages", + "weight": 361, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-push.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-push.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "messageId": { + "type": "string", + "description": "Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<MESSAGE_ID>" + }, + "title": { + "type": "string", + "description": "Title for push notification.", + "default": "", + "x-example": "<TITLE>" + }, + "body": { + "type": "string", + "description": "Body for push notification.", + "default": "", + "x-example": "<BODY>" + }, + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "data": { + "type": "object", + "description": "Additional key-value pair data for push notification.", + "default": {}, + "x-example": "{}" + }, + "action": { + "type": "string", + "description": "Action for push notification.", + "default": "", + "x-example": "<ACTION>" + }, + "image": { + "type": "string", + "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as <BUCKET_ID>:<FILE_ID>.", + "default": "", + "x-example": "[ID1:ID2]" + }, + "icon": { + "type": "string", + "description": "Icon for push notification. Available only for Android and Web Platform.", + "default": "", + "x-example": "<ICON>" + }, + "sound": { + "type": "string", + "description": "Sound for push notification. Available only for Android and iOS Platform.", + "default": "", + "x-example": "<SOUND>" + }, + "color": { + "type": "string", + "description": "Color for push notification. Available only for Android Platform.", + "default": "", + "x-example": "<COLOR>" + }, + "tag": { + "type": "string", + "description": "Tag for push notification. Available only for Android Platform.", + "default": "", + "x-example": "<TAG>" + }, + "badge": { + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "default": -1, + "x-example": null + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "default": false, + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "default": null, + "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "default": false, + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "default": false, + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device state and may not deliver notifications immediately. \"high\" will always attempt to immediately deliver the notification.", + "default": "high", + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": "MessagePriority", + "x-enum-keys": [] + } + }, + "required": [ + "messageId" + ] + } + } + ] + } + }, + "\/messaging\/messages\/push\/{messageId}": { + "patch": { + "summary": "Update push notification", + "operationId": "messagingUpdatePush", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a push notification by its unique ID. This endpoint only works on messages that are in draft status. Messages that are already processing, sent, or failed cannot be updated.\n", + "responses": { + "200": { + "description": "Message", + "schema": { + "$ref": "#\/definitions\/message" + } + } + }, + "x-appwrite": { + "method": "updatePush", + "group": "messages", + "weight": 368, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-push.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-push.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "type": "string", + "x-example": "<MESSAGE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "title": { + "type": "string", + "description": "Title for push notification.", + "default": null, + "x-example": "<TITLE>" + }, + "body": { + "type": "string", + "description": "Body for push notification.", + "default": null, + "x-example": "<BODY>" + }, + "data": { + "type": "object", + "description": "Additional Data for push notification.", + "default": {}, + "x-example": "{}" + }, + "action": { + "type": "string", + "description": "Action for push notification.", + "default": null, + "x-example": "<ACTION>" + }, + "image": { + "type": "string", + "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as <BUCKET_ID>:<FILE_ID>.", + "default": null, + "x-example": "[ID1:ID2]" + }, + "icon": { + "type": "string", + "description": "Icon for push notification. Available only for Android and Web platforms.", + "default": null, + "x-example": "<ICON>" + }, + "sound": { + "type": "string", + "description": "Sound for push notification. Available only for Android and iOS platforms.", + "default": null, + "x-example": "<SOUND>" + }, + "color": { + "type": "string", + "description": "Color for push notification. Available only for Android platforms.", + "default": null, + "x-example": "<COLOR>" + }, + "tag": { + "type": "string", + "description": "Tag for push notification. Available only for Android platforms.", + "default": null, + "x-example": "<TAG>" + }, + "badge": { + "type": "integer", + "description": "Badge for push notification. Available only for iOS platforms.", + "default": null, + "x-example": null + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "default": null, + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "default": null, + "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "default": null, + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "default": null, + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "default": null, + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": "MessagePriority", + "x-enum-keys": [] + } + } + } + } + ] + } + }, + "\/messaging\/messages\/sms": { + "post": { + "summary": "Create SMS", + "operationId": "messagingCreateSms", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new SMS message.", + "responses": { + "201": { + "description": "Message", + "schema": { + "$ref": "#\/definitions\/message" + } + } + }, + "x-appwrite": { + "method": "createSms", + "group": "messages", + "weight": 360, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-sms.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-sms.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "messageId": { + "type": "string", + "description": "Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<MESSAGE_ID>" + }, + "content": { + "type": "string", + "description": "SMS Content.", + "default": null, + "x-example": "<CONTENT>" + }, + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "default": false, + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "default": null, + "x-example": null + } + }, + "required": [ + "messageId", + "content" + ] + } + } + ] + } + }, + "\/messaging\/messages\/sms\/{messageId}": { + "patch": { + "summary": "Update SMS", + "operationId": "messagingUpdateSms", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update an SMS message by its unique ID. This endpoint only works on messages that are in draft status. Messages that are already processing, sent, or failed cannot be updated.\n", + "responses": { + "200": { + "description": "Message", + "schema": { + "$ref": "#\/definitions\/message" + } + } + }, + "x-appwrite": { + "method": "updateSms", + "group": "messages", + "weight": 367, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-sms.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-sms.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "type": "string", + "x-example": "<MESSAGE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "content": { + "type": "string", + "description": "Email Content.", + "default": null, + "x-example": "<CONTENT>" + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "default": null, + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "default": null, + "x-example": null + } + } + } + } + ] + } + }, + "\/messaging\/messages\/{messageId}": { + "get": { + "summary": "Get message", + "operationId": "messagingGetMessage", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get a message by its unique ID.\n", + "responses": { + "200": { + "description": "Message", + "schema": { + "$ref": "#\/definitions\/message" + } + } + }, + "x-appwrite": { + "method": "getMessage", + "group": "messages", + "weight": 365, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/get-message.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/get-message.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "type": "string", + "x-example": "<MESSAGE_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete message", + "operationId": "messagingDelete", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "messaging" + ], + "description": "Delete a message. If the message is not a draft or scheduled, but has been sent, this will not recall the message.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "messages", + "weight": 369, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/delete-message.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "type": "string", + "x-example": "<MESSAGE_ID>", + "in": "path" + } + ] + } + }, + "\/messaging\/messages\/{messageId}\/logs": { + "get": { + "summary": "List message logs", + "operationId": "messagingListMessageLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get the message activity logs listed by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "schema": { + "$ref": "#\/definitions\/logList" + } + } + }, + "x-appwrite": { + "method": "listMessageLogs", + "group": "logs", + "weight": 363, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-message-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-message-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "type": "string", + "x-example": "<MESSAGE_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/messaging\/messages\/{messageId}\/targets": { + "get": { + "summary": "List message targets", + "operationId": "messagingListTargets", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get a list of the targets associated with a message.", + "responses": { + "200": { + "description": "Target list", + "schema": { + "$ref": "#\/definitions\/targetList" + } + } + }, + "x-appwrite": { + "method": "listTargets", + "group": "messages", + "weight": 364, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-targets.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-message-targets.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "type": "string", + "x-example": "<MESSAGE_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, providerId, identifier, providerType", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/messaging\/providers": { + "get": { + "summary": "List providers", + "operationId": "messagingListProviders", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get a list of all providers from the current Appwrite project.", + "responses": { + "200": { + "description": "Provider list", + "schema": { + "$ref": "#\/definitions\/providerList" + } + } + }, + "x-appwrite": { + "method": "listProviders", + "group": "providers", + "weight": 334, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-providers.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-providers.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, provider, type, enabled", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + } + }, + "\/messaging\/providers\/apns": { + "post": { + "summary": "Create APNS provider", + "operationId": "messagingCreateApnsProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new Apple Push Notification service provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createApnsProvider", + "group": "providers", + "weight": 333, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-apns-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-apns-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "authKey": { + "type": "string", + "description": "APNS authentication key.", + "default": "", + "x-example": "<AUTH_KEY>" + }, + "authKeyId": { + "type": "string", + "description": "APNS authentication key ID.", + "default": "", + "x-example": "<AUTH_KEY_ID>" + }, + "teamId": { + "type": "string", + "description": "APNS team ID.", + "default": "", + "x-example": "<TEAM_ID>" + }, + "bundleId": { + "type": "string", + "description": "APNS bundle ID.", + "default": "", + "x-example": "<BUNDLE_ID>" + }, + "sandbox": { + "type": "boolean", + "description": "Use APNS sandbox environment.", + "default": false, + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/providers\/apns\/{providerId}": { + "patch": { + "summary": "Update APNS provider", + "operationId": "messagingUpdateApnsProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a Apple Push Notification service provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateApnsProvider", + "group": "providers", + "weight": 346, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-apns-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-apns-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + }, + "authKey": { + "type": "string", + "description": "APNS authentication key.", + "default": "", + "x-example": "<AUTH_KEY>" + }, + "authKeyId": { + "type": "string", + "description": "APNS authentication key ID.", + "default": "", + "x-example": "<AUTH_KEY_ID>" + }, + "teamId": { + "type": "string", + "description": "APNS team ID.", + "default": "", + "x-example": "<TEAM_ID>" + }, + "bundleId": { + "type": "string", + "description": "APNS bundle ID.", + "default": "", + "x-example": "<BUNDLE_ID>" + }, + "sandbox": { + "type": "boolean", + "description": "Use APNS sandbox environment.", + "default": null, + "x-example": false + } + } + } + } + ] + } + }, + "\/messaging\/providers\/fcm": { + "post": { + "summary": "Create FCM provider", + "operationId": "messagingCreateFcmProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new Firebase Cloud Messaging provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createFcmProvider", + "group": "providers", + "weight": 332, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-fcm-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-fcm-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "serviceAccountJSON": { + "type": "object", + "description": "FCM service account JSON.", + "default": {}, + "x-example": "{}" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/providers\/fcm\/{providerId}": { + "patch": { + "summary": "Update FCM provider", + "operationId": "messagingUpdateFcmProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a Firebase Cloud Messaging provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateFcmProvider", + "group": "providers", + "weight": 345, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-fcm-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-fcm-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + }, + "serviceAccountJSON": { + "type": "object", + "description": "FCM service account JSON.", + "default": {}, + "x-example": "{}" + } + } + } + } + ] + } + }, + "\/messaging\/providers\/mailgun": { + "post": { + "summary": "Create Mailgun provider", + "operationId": "messagingCreateMailgunProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new Mailgun provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createMailgunProvider", + "group": "providers", + "weight": 324, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-mailgun-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-mailgun-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "apiKey": { + "type": "string", + "description": "Mailgun API Key.", + "default": "", + "x-example": "<API_KEY>" + }, + "domain": { + "type": "string", + "description": "Mailgun Domain.", + "default": "", + "x-example": "<DOMAIN>" + }, + "isEuRegion": { + "type": "boolean", + "description": "Set as EU region.", + "default": null, + "x-example": false + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "default": "", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "default": "", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the reply to field for the mail. Default value is sender name. Reply to name must have reply to email as well.", + "default": "", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the reply to field for the mail. Default value is sender email. Reply to email must have reply to name as well.", + "default": "", + "x-example": "email@example.com" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/providers\/mailgun\/{providerId}": { + "patch": { + "summary": "Update Mailgun provider", + "operationId": "messagingUpdateMailgunProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a Mailgun provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateMailgunProvider", + "group": "providers", + "weight": 337, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-mailgun-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-mailgun-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "apiKey": { + "type": "string", + "description": "Mailgun API Key.", + "default": "", + "x-example": "<API_KEY>" + }, + "domain": { + "type": "string", + "description": "Mailgun Domain.", + "default": "", + "x-example": "<DOMAIN>" + }, + "isEuRegion": { + "type": "boolean", + "description": "Set as EU region.", + "default": null, + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "default": "", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "default": "", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the reply to field for the mail. Default value is sender name.", + "default": "", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the reply to field for the mail. Default value is sender email.", + "default": "", + "x-example": "<REPLY_TO_EMAIL>" + } + } + } + } + ] + } + }, + "\/messaging\/providers\/msg91": { + "post": { + "summary": "Create Msg91 provider", + "operationId": "messagingCreateMsg91Provider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new MSG91 provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createMsg91Provider", + "group": "providers", + "weight": 327, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-msg91provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-msg91-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "templateId": { + "type": "string", + "description": "Msg91 template ID", + "default": "", + "x-example": "<TEMPLATE_ID>" + }, + "senderId": { + "type": "string", + "description": "Msg91 sender ID.", + "default": "", + "x-example": "<SENDER_ID>" + }, + "authKey": { + "type": "string", + "description": "Msg91 auth key.", + "default": "", + "x-example": "<AUTH_KEY>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/providers\/msg91\/{providerId}": { + "patch": { + "summary": "Update Msg91 provider", + "operationId": "messagingUpdateMsg91Provider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a MSG91 provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateMsg91Provider", + "group": "providers", + "weight": 340, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-msg91provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-msg91-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + }, + "templateId": { + "type": "string", + "description": "Msg91 template ID.", + "default": "", + "x-example": "<TEMPLATE_ID>" + }, + "senderId": { + "type": "string", + "description": "Msg91 sender ID.", + "default": "", + "x-example": "<SENDER_ID>" + }, + "authKey": { + "type": "string", + "description": "Msg91 auth key.", + "default": "", + "x-example": "<AUTH_KEY>" + } + } + } + } + ] + } + }, + "\/messaging\/providers\/sendgrid": { + "post": { + "summary": "Create Sendgrid provider", + "operationId": "messagingCreateSendgridProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new Sendgrid provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createSendgridProvider", + "group": "providers", + "weight": 325, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-sendgrid-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-sendgrid-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "apiKey": { + "type": "string", + "description": "Sendgrid API key.", + "default": "", + "x-example": "<API_KEY>" + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "default": "", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "default": "", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the reply to field for the mail. Default value is sender name.", + "default": "", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the reply to field for the mail. Default value is sender email.", + "default": "", + "x-example": "email@example.com" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/providers\/sendgrid\/{providerId}": { + "patch": { + "summary": "Update Sendgrid provider", + "operationId": "messagingUpdateSendgridProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a Sendgrid provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateSendgridProvider", + "group": "providers", + "weight": 338, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-sendgrid-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-sendgrid-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + }, + "apiKey": { + "type": "string", + "description": "Sendgrid API key.", + "default": "", + "x-example": "<API_KEY>" + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "default": "", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "default": "", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the Reply To field for the mail. Default value is Sender Name.", + "default": "", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the Reply To field for the mail. Default value is Sender Email.", + "default": "", + "x-example": "<REPLY_TO_EMAIL>" + } + } + } + } + ] + } + }, + "\/messaging\/providers\/smtp": { + "post": { + "summary": "Create SMTP provider", + "operationId": "messagingCreateSmtpProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new SMTP provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createSmtpProvider", + "group": "providers", + "weight": 326, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-smtp-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-smtp-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "host": { + "type": "string", + "description": "SMTP hosts. Either a single hostname or multiple semicolon-delimited hostnames. You can also specify a different port for each host such as `smtp1.example.com:25;smtp2.example.com`. You can also specify encryption type, for example: `tls:\/\/smtp1.example.com:587;ssl:\/\/smtp2.example.com:465\"`. Hosts will be tried in order.", + "default": null, + "x-example": "<HOST>" + }, + "port": { + "type": "integer", + "description": "The default SMTP server port.", + "default": 587, + "x-example": 1 + }, + "username": { + "type": "string", + "description": "Authentication username.", + "default": "", + "x-example": "<USERNAME>" + }, + "password": { + "type": "string", + "description": "Authentication password.", + "default": "", + "x-example": "<PASSWORD>" + }, + "encryption": { + "type": "string", + "description": "Encryption type. Can be omitted, 'ssl', or 'tls'", + "default": "", + "x-example": "none", + "enum": [ + "none", + "ssl", + "tls" + ], + "x-enum-name": "SmtpEncryption", + "x-enum-keys": [] + }, + "autoTLS": { + "type": "boolean", + "description": "Enable SMTP AutoTLS feature.", + "default": true, + "x-example": false + }, + "mailer": { + "type": "string", + "description": "The value to use for the X-Mailer header.", + "default": "", + "x-example": "<MAILER>" + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "default": "", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "default": "", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the reply to field for the mail. Default value is sender name.", + "default": "", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the reply to field for the mail. Default value is sender email.", + "default": "", + "x-example": "email@example.com" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name", + "host" + ] + } + } + ] + } + }, + "\/messaging\/providers\/smtp\/{providerId}": { + "patch": { + "summary": "Update SMTP provider", + "operationId": "messagingUpdateSmtpProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a SMTP provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateSmtpProvider", + "group": "providers", + "weight": 339, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-smtp-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-smtp-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "host": { + "type": "string", + "description": "SMTP hosts. Either a single hostname or multiple semicolon-delimited hostnames. You can also specify a different port for each host such as `smtp1.example.com:25;smtp2.example.com`. You can also specify encryption type, for example: `tls:\/\/smtp1.example.com:587;ssl:\/\/smtp2.example.com:465\"`. Hosts will be tried in order.", + "default": "", + "x-example": "<HOST>" + }, + "port": { + "type": "integer", + "description": "SMTP port.", + "default": null, + "x-example": 1 + }, + "username": { + "type": "string", + "description": "Authentication username.", + "default": "", + "x-example": "<USERNAME>" + }, + "password": { + "type": "string", + "description": "Authentication password.", + "default": "", + "x-example": "<PASSWORD>" + }, + "encryption": { + "type": "string", + "description": "Encryption type. Can be 'ssl' or 'tls'", + "default": "", + "x-example": "none", + "enum": [ + "none", + "ssl", + "tls" + ], + "x-enum-name": "SmtpEncryption", + "x-enum-keys": [] + }, + "autoTLS": { + "type": "boolean", + "description": "Enable SMTP AutoTLS feature.", + "default": null, + "x-example": false + }, + "mailer": { + "type": "string", + "description": "The value to use for the X-Mailer header.", + "default": "", + "x-example": "<MAILER>" + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "default": "", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "default": "", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the Reply To field for the mail. Default value is Sender Name.", + "default": "", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the Reply To field for the mail. Default value is Sender Email.", + "default": "", + "x-example": "<REPLY_TO_EMAIL>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + } + } + } + ] + } + }, + "\/messaging\/providers\/telesign": { + "post": { + "summary": "Create Telesign provider", + "operationId": "messagingCreateTelesignProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new Telesign provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createTelesignProvider", + "group": "providers", + "weight": 328, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-telesign-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-telesign-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "from": { + "type": "string", + "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "default": "", + "x-example": "+12065550100" + }, + "customerId": { + "type": "string", + "description": "Telesign customer ID.", + "default": "", + "x-example": "<CUSTOMER_ID>" + }, + "apiKey": { + "type": "string", + "description": "Telesign API key.", + "default": "", + "x-example": "<API_KEY>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/providers\/telesign\/{providerId}": { + "patch": { + "summary": "Update Telesign provider", + "operationId": "messagingUpdateTelesignProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a Telesign provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateTelesignProvider", + "group": "providers", + "weight": 341, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-telesign-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-telesign-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + }, + "customerId": { + "type": "string", + "description": "Telesign customer ID.", + "default": "", + "x-example": "<CUSTOMER_ID>" + }, + "apiKey": { + "type": "string", + "description": "Telesign API key.", + "default": "", + "x-example": "<API_KEY>" + }, + "from": { + "type": "string", + "description": "Sender number.", + "default": "", + "x-example": "<FROM>" + } + } + } + } + ] + } + }, + "\/messaging\/providers\/textmagic": { + "post": { + "summary": "Create Textmagic provider", + "operationId": "messagingCreateTextmagicProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new Textmagic provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createTextmagicProvider", + "group": "providers", + "weight": 329, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-textmagic-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-textmagic-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "from": { + "type": "string", + "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "default": "", + "x-example": "+12065550100" + }, + "username": { + "type": "string", + "description": "Textmagic username.", + "default": "", + "x-example": "<USERNAME>" + }, + "apiKey": { + "type": "string", + "description": "Textmagic apiKey.", + "default": "", + "x-example": "<API_KEY>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/providers\/textmagic\/{providerId}": { + "patch": { + "summary": "Update Textmagic provider", + "operationId": "messagingUpdateTextmagicProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a Textmagic provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateTextmagicProvider", + "group": "providers", + "weight": 342, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-textmagic-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-textmagic-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + }, + "username": { + "type": "string", + "description": "Textmagic username.", + "default": "", + "x-example": "<USERNAME>" + }, + "apiKey": { + "type": "string", + "description": "Textmagic apiKey.", + "default": "", + "x-example": "<API_KEY>" + }, + "from": { + "type": "string", + "description": "Sender number.", + "default": "", + "x-example": "<FROM>" + } + } + } + } + ] + } + }, + "\/messaging\/providers\/twilio": { + "post": { + "summary": "Create Twilio provider", + "operationId": "messagingCreateTwilioProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new Twilio provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createTwilioProvider", + "group": "providers", + "weight": 330, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-twilio-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-twilio-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "from": { + "type": "string", + "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "default": "", + "x-example": "+12065550100" + }, + "accountSid": { + "type": "string", + "description": "Twilio account secret ID.", + "default": "", + "x-example": "<ACCOUNT_SID>" + }, + "authToken": { + "type": "string", + "description": "Twilio authentication token.", + "default": "", + "x-example": "<AUTH_TOKEN>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/providers\/twilio\/{providerId}": { + "patch": { + "summary": "Update Twilio provider", + "operationId": "messagingUpdateTwilioProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a Twilio provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateTwilioProvider", + "group": "providers", + "weight": 343, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-twilio-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-twilio-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + }, + "accountSid": { + "type": "string", + "description": "Twilio account secret ID.", + "default": "", + "x-example": "<ACCOUNT_SID>" + }, + "authToken": { + "type": "string", + "description": "Twilio authentication token.", + "default": "", + "x-example": "<AUTH_TOKEN>" + }, + "from": { + "type": "string", + "description": "Sender number.", + "default": "", + "x-example": "<FROM>" + } + } + } + } + ] + } + }, + "\/messaging\/providers\/vonage": { + "post": { + "summary": "Create Vonage provider", + "operationId": "messagingCreateVonageProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new Vonage provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createVonageProvider", + "group": "providers", + "weight": 331, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-vonage-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-vonage-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "from": { + "type": "string", + "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "default": "", + "x-example": "+12065550100" + }, + "apiKey": { + "type": "string", + "description": "Vonage API key.", + "default": "", + "x-example": "<API_KEY>" + }, + "apiSecret": { + "type": "string", + "description": "Vonage API secret.", + "default": "", + "x-example": "<API_SECRET>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/providers\/vonage\/{providerId}": { + "patch": { + "summary": "Update Vonage provider", + "operationId": "messagingUpdateVonageProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a Vonage provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateVonageProvider", + "group": "providers", + "weight": 344, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-vonage-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-vonage-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + }, + "apiKey": { + "type": "string", + "description": "Vonage API key.", + "default": "", + "x-example": "<API_KEY>" + }, + "apiSecret": { + "type": "string", + "description": "Vonage API secret.", + "default": "", + "x-example": "<API_SECRET>" + }, + "from": { + "type": "string", + "description": "Sender number.", + "default": "", + "x-example": "<FROM>" + } + } + } + } + ] + } + }, + "\/messaging\/providers\/{providerId}": { + "get": { + "summary": "Get provider", + "operationId": "messagingGetProvider", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get a provider by its unique ID.\n", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "getProvider", + "group": "providers", + "weight": 336, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/get-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/get-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete provider", + "operationId": "messagingDeleteProvider", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "messaging" + ], + "description": "Delete a provider by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteProvider", + "group": "providers", + "weight": 347, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/delete-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/delete-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + } + ] + } + }, + "\/messaging\/providers\/{providerId}\/logs": { + "get": { + "summary": "List provider logs", + "operationId": "messagingListProviderLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get the provider activity logs listed by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "schema": { + "$ref": "#\/definitions\/logList" + } + } + }, + "x-appwrite": { + "method": "listProviderLogs", + "group": "providers", + "weight": 335, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-provider-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-provider-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/messaging\/subscribers\/{subscriberId}\/logs": { + "get": { + "summary": "List subscriber logs", + "operationId": "messagingListSubscriberLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get the subscriber activity logs listed by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "schema": { + "$ref": "#\/definitions\/logList" + } + } + }, + "x-appwrite": { + "method": "listSubscriberLogs", + "group": "subscribers", + "weight": 356, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-subscriber-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-subscriber-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "subscriberId", + "description": "Subscriber ID.", + "required": true, + "type": "string", + "x-example": "<SUBSCRIBER_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/messaging\/topics": { + "get": { + "summary": "List topics", + "operationId": "messagingListTopics", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get a list of all topics from the current Appwrite project.", + "responses": { + "200": { + "description": "Topic list", + "schema": { + "$ref": "#\/definitions\/topicList" + } + } + }, + "x-appwrite": { + "method": "listTopics", + "group": "topics", + "weight": 349, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-topics.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-topics.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, description, emailTotal, smsTotal, pushTotal", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create topic", + "operationId": "messagingCreateTopic", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new topic.", + "responses": { + "201": { + "description": "Topic", + "schema": { + "$ref": "#\/definitions\/topic" + } + } + }, + "x-appwrite": { + "method": "createTopic", + "group": "topics", + "weight": 348, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-topic.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-topic.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "topicId": { + "type": "string", + "description": "Topic ID. Choose a custom Topic ID or a new Topic ID.", + "default": null, + "x-example": "<TOPIC_ID>" + }, + "name": { + "type": "string", + "description": "Topic Name.", + "default": null, + "x-example": "<NAME>" + }, + "subscribe": { + "type": "array", + "description": "An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https:\/\/appwrite.io\/docs\/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.", + "default": [ + "users" + ], + "x-example": "[\"any\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "topicId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/topics\/{topicId}": { + "get": { + "summary": "Get topic", + "operationId": "messagingGetTopic", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get a topic by its unique ID.\n", + "responses": { + "200": { + "description": "Topic", + "schema": { + "$ref": "#\/definitions\/topic" + } + } + }, + "x-appwrite": { + "method": "getTopic", + "group": "topics", + "weight": 351, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/get-topic.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/get-topic.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID.", + "required": true, + "type": "string", + "x-example": "<TOPIC_ID>", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update topic", + "operationId": "messagingUpdateTopic", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a topic by its unique ID.\n", + "responses": { + "200": { + "description": "Topic", + "schema": { + "$ref": "#\/definitions\/topic" + } + } + }, + "x-appwrite": { + "method": "updateTopic", + "group": "topics", + "weight": 352, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-topic.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-topic.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID.", + "required": true, + "type": "string", + "x-example": "<TOPIC_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Topic Name.", + "default": null, + "x-example": "<NAME>" + }, + "subscribe": { + "type": "array", + "description": "An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https:\/\/appwrite.io\/docs\/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.", + "default": null, + "x-example": "[\"any\"]", + "items": { + "type": "string" + } + } + } + } + } + ] + }, + "delete": { + "summary": "Delete topic", + "operationId": "messagingDeleteTopic", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "messaging" + ], + "description": "Delete a topic by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteTopic", + "group": "topics", + "weight": 353, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/delete-topic.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/delete-topic.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID.", + "required": true, + "type": "string", + "x-example": "<TOPIC_ID>", + "in": "path" + } + ] + } + }, + "\/messaging\/topics\/{topicId}\/logs": { + "get": { + "summary": "List topic logs", + "operationId": "messagingListTopicLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get the topic activity logs listed by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "schema": { + "$ref": "#\/definitions\/logList" + } + } + }, + "x-appwrite": { + "method": "listTopicLogs", + "group": "topics", + "weight": 350, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-topic-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-topic-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID.", + "required": true, + "type": "string", + "x-example": "<TOPIC_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/messaging\/topics\/{topicId}\/subscribers": { + "get": { + "summary": "List subscribers", + "operationId": "messagingListSubscribers", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get a list of all subscribers from the current Appwrite project.", + "responses": { + "200": { + "description": "Subscriber list", + "schema": { + "$ref": "#\/definitions\/subscriberList" + } + } + }, + "x-appwrite": { + "method": "listSubscribers", + "group": "subscribers", + "weight": 355, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-subscribers.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-subscribers.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID subscribed to.", + "required": true, + "type": "string", + "x-example": "<TOPIC_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, provider, type, enabled", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create subscriber", + "operationId": "messagingCreateSubscriber", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new subscriber.", + "responses": { + "201": { + "description": "Subscriber", + "schema": { + "$ref": "#\/definitions\/subscriber" + } + } + }, + "x-appwrite": { + "method": "createSubscriber", + "group": "subscribers", + "weight": 354, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-subscriber.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-subscriber.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.write", + "platforms": [ + "server", + "client", + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID to subscribe to.", + "required": true, + "type": "string", + "x-example": "<TOPIC_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "subscriberId": { + "type": "string", + "description": "Subscriber ID. Choose a custom Subscriber ID or a new Subscriber ID.", + "default": null, + "x-example": "<SUBSCRIBER_ID>" + }, + "targetId": { + "type": "string", + "description": "Target ID. The target ID to link to the specified Topic ID.", + "default": null, + "x-example": "<TARGET_ID>" + } + }, + "required": [ + "subscriberId", + "targetId" + ] + } + } + ] + } + }, + "\/messaging\/topics\/{topicId}\/subscribers\/{subscriberId}": { + "get": { + "summary": "Get subscriber", + "operationId": "messagingGetSubscriber", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get a subscriber by its unique ID.\n", + "responses": { + "200": { + "description": "Subscriber", + "schema": { + "$ref": "#\/definitions\/subscriber" + } + } + }, + "x-appwrite": { + "method": "getSubscriber", + "group": "subscribers", + "weight": 357, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/get-subscriber.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/get-subscriber.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID subscribed to.", + "required": true, + "type": "string", + "x-example": "<TOPIC_ID>", + "in": "path" + }, + { + "name": "subscriberId", + "description": "Subscriber ID.", + "required": true, + "type": "string", + "x-example": "<SUBSCRIBER_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete subscriber", + "operationId": "messagingDeleteSubscriber", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "messaging" + ], + "description": "Delete a subscriber by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSubscriber", + "group": "subscribers", + "weight": 358, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/delete-subscriber.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/delete-subscriber.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.write", + "platforms": [ + "server", + "client", + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID subscribed to.", + "required": true, + "type": "string", + "x-example": "<TOPIC_ID>", + "in": "path" + }, + { + "name": "subscriberId", + "description": "Subscriber ID.", + "required": true, + "type": "string", + "x-example": "<SUBSCRIBER_ID>", + "in": "path" + } + ] + } + }, + "\/migrations": { + "get": { + "summary": "List migrations", + "operationId": "migrationsList", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "migrations" + ], + "description": "List all migrations in the current project. This endpoint returns a list of all migrations including their status, progress, and any errors that occurred during the migration process.", + "responses": { + "200": { + "description": "Migrations List", + "schema": { + "$ref": "#\/definitions\/migrationList" + } + } + }, + "x-appwrite": { + "method": "list", + "group": null, + "weight": 316, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/list-migrations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/databases#querying-documents). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: status, stage, source, destination, resources, statusCounters, resourceData, errors", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + } + }, + "\/migrations\/appwrite": { + "post": { + "summary": "Create Appwrite migration", + "operationId": "migrationsCreateAppwriteMigration", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "migrations" + ], + "description": "Migrate data from another Appwrite project to your current project. This endpoint allows you to migrate resources like databases, collections, documents, users, and files from an existing Appwrite project. ", + "responses": { + "202": { + "description": "Migration", + "schema": { + "$ref": "#\/definitions\/migration" + } + } + }, + "x-appwrite": { + "method": "createAppwriteMigration", + "group": null, + "weight": 311, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/create-appwrite-migration.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-appwrite.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "resources": { + "type": "array", + "description": "List of resources to migrate", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "endpoint": { + "type": "string", + "description": "Source Appwrite endpoint", + "default": null, + "x-example": "https:\/\/example.com" + }, + "projectId": { + "type": "string", + "description": "Source Project ID", + "default": null, + "x-example": "<PROJECT_ID>" + }, + "apiKey": { + "type": "string", + "description": "Source API Key", + "default": null, + "x-example": "<API_KEY>" + } + }, + "required": [ + "resources", + "endpoint", + "projectId", + "apiKey" + ] + } + } + ] + } + }, + "\/migrations\/appwrite\/report": { + "get": { + "summary": "Get Appwrite migration report", + "operationId": "migrationsGetAppwriteReport", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "migrations" + ], + "description": "Generate a report of the data in an Appwrite project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated.", + "responses": { + "200": { + "description": "Migration Report", + "schema": { + "$ref": "#\/definitions\/migrationReport" + } + } + }, + "x-appwrite": { + "method": "getAppwriteReport", + "group": null, + "weight": 318, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/get-appwrite-report.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-appwrite-report.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "resources", + "description": "List of resources to migrate", + "required": true, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "in": "query" + }, + { + "name": "endpoint", + "description": "Source's Appwrite Endpoint", + "required": true, + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "in": "query" + }, + { + "name": "projectID", + "description": "Source's Project ID", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "query" + }, + { + "name": "key", + "description": "Source's API Key", + "required": true, + "type": "string", + "x-example": "<KEY>", + "in": "query" + } + ] + } + }, + "\/migrations\/csv": { + "post": { + "summary": "Import documents from a CSV", + "operationId": "migrationsCreateCsvMigration", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "migrations" + ], + "description": "Import documents from a CSV file into your Appwrite database. This endpoint allows you to import documents from a CSV file uploaded to Appwrite Storage bucket.", + "responses": { + "202": { + "description": "Migration", + "schema": { + "$ref": "#\/definitions\/migration" + } + } + }, + "x-appwrite": { + "method": "createCsvMigration", + "group": null, + "weight": 315, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/create-csv-migration.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-csv.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "bucketId": { + "type": "string", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "default": null, + "x-example": "<BUCKET_ID>" + }, + "fileId": { + "type": "string", + "description": "File ID.", + "default": null, + "x-example": "<FILE_ID>" + }, + "resourceId": { + "type": "string", + "description": "Composite ID in the format {databaseId:collectionId}, identifying a collection within a database.", + "default": null, + "x-example": "[ID1:ID2]" + } + }, + "required": [ + "bucketId", + "fileId", + "resourceId" + ] + } + } + ] + } + }, + "\/migrations\/firebase": { + "post": { + "summary": "Create Firebase migration", + "operationId": "migrationsCreateFirebaseMigration", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "migrations" + ], + "description": "Migrate data from a Firebase project to your Appwrite project. This endpoint allows you to migrate resources like authentication and other supported services from a Firebase project. ", + "responses": { + "202": { + "description": "Migration", + "schema": { + "$ref": "#\/definitions\/migration" + } + } + }, + "x-appwrite": { + "method": "createFirebaseMigration", + "group": null, + "weight": 312, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/create-firebase-migration.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-firebase.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "resources": { + "type": "array", + "description": "List of resources to migrate", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "serviceAccount": { + "type": "string", + "description": "JSON of the Firebase service account credentials", + "default": null, + "x-example": "<SERVICE_ACCOUNT>" + } + }, + "required": [ + "resources", + "serviceAccount" + ] + } + } + ] + } + }, + "\/migrations\/firebase\/report": { + "get": { + "summary": "Get Firebase migration report", + "operationId": "migrationsGetFirebaseReport", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "migrations" + ], + "description": "Generate a report of the data in a Firebase project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated.", + "responses": { + "200": { + "description": "Migration Report", + "schema": { + "$ref": "#\/definitions\/migrationReport" + } + } + }, + "x-appwrite": { + "method": "getFirebaseReport", + "group": null, + "weight": 319, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/get-firebase-report.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-firebase-report.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "resources", + "description": "List of resources to migrate", + "required": true, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "in": "query" + }, + { + "name": "serviceAccount", + "description": "JSON of the Firebase service account credentials", + "required": true, + "type": "string", + "x-example": "<SERVICE_ACCOUNT>", + "in": "query" + } + ] + } + }, + "\/migrations\/nhost": { + "post": { + "summary": "Create NHost migration", + "operationId": "migrationsCreateNHostMigration", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "migrations" + ], + "description": "Migrate data from an NHost project to your Appwrite project. This endpoint allows you to migrate resources like authentication, databases, and other supported services from an NHost project. ", + "responses": { + "202": { + "description": "Migration", + "schema": { + "$ref": "#\/definitions\/migration" + } + } + }, + "x-appwrite": { + "method": "createNHostMigration", + "group": null, + "weight": 314, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/create-n-host-migration.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-nhost.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "resources": { + "type": "array", + "description": "List of resources to migrate", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "subdomain": { + "type": "string", + "description": "Source's Subdomain", + "default": null, + "x-example": "<SUBDOMAIN>" + }, + "region": { + "type": "string", + "description": "Source's Region", + "default": null, + "x-example": "<REGION>" + }, + "adminSecret": { + "type": "string", + "description": "Source's Admin Secret", + "default": null, + "x-example": "<ADMIN_SECRET>" + }, + "database": { + "type": "string", + "description": "Source's Database Name", + "default": null, + "x-example": "<DATABASE>" + }, + "username": { + "type": "string", + "description": "Source's Database Username", + "default": null, + "x-example": "<USERNAME>" + }, + "password": { + "type": "string", + "description": "Source's Database Password", + "default": null, + "x-example": "<PASSWORD>" + }, + "port": { + "type": "integer", + "description": "Source's Database Port", + "default": 5432, + "x-example": null + } + }, + "required": [ + "resources", + "subdomain", + "region", + "adminSecret", + "database", + "username", + "password" + ] + } + } + ] + } + }, + "\/migrations\/nhost\/report": { + "get": { + "summary": "Get NHost migration report", + "operationId": "migrationsGetNHostReport", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "migrations" + ], + "description": "Generate a detailed report of the data in an NHost project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated. ", + "responses": { + "200": { + "description": "Migration Report", + "schema": { + "$ref": "#\/definitions\/migrationReport" + } + } + }, + "x-appwrite": { + "method": "getNHostReport", + "group": null, + "weight": 321, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/get-n-host-report.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-nhost-report.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "resources", + "description": "List of resources to migrate.", + "required": true, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "in": "query" + }, + { + "name": "subdomain", + "description": "Source's Subdomain.", + "required": true, + "type": "string", + "x-example": "<SUBDOMAIN>", + "in": "query" + }, + { + "name": "region", + "description": "Source's Region.", + "required": true, + "type": "string", + "x-example": "<REGION>", + "in": "query" + }, + { + "name": "adminSecret", + "description": "Source's Admin Secret.", + "required": true, + "type": "string", + "x-example": "<ADMIN_SECRET>", + "in": "query" + }, + { + "name": "database", + "description": "Source's Database Name.", + "required": true, + "type": "string", + "x-example": "<DATABASE>", + "in": "query" + }, + { + "name": "username", + "description": "Source's Database Username.", + "required": true, + "type": "string", + "x-example": "<USERNAME>", + "in": "query" + }, + { + "name": "password", + "description": "Source's Database Password.", + "required": true, + "type": "string", + "x-example": "<PASSWORD>", + "in": "query" + }, + { + "name": "port", + "description": "Source's Database Port.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5432, + "in": "query" + } + ] + } + }, + "\/migrations\/supabase": { + "post": { + "summary": "Create Supabase migration", + "operationId": "migrationsCreateSupabaseMigration", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "migrations" + ], + "description": "Migrate data from a Supabase project to your Appwrite project. This endpoint allows you to migrate resources like authentication, databases, and other supported services from a Supabase project. ", + "responses": { + "202": { + "description": "Migration", + "schema": { + "$ref": "#\/definitions\/migration" + } + } + }, + "x-appwrite": { + "method": "createSupabaseMigration", + "group": null, + "weight": 313, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/create-supabase-migration.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-supabase.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "resources": { + "type": "array", + "description": "List of resources to migrate", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "endpoint": { + "type": "string", + "description": "Source's Supabase Endpoint", + "default": null, + "x-example": "https:\/\/example.com" + }, + "apiKey": { + "type": "string", + "description": "Source's API Key", + "default": null, + "x-example": "<API_KEY>" + }, + "databaseHost": { + "type": "string", + "description": "Source's Database Host", + "default": null, + "x-example": "<DATABASE_HOST>" + }, + "username": { + "type": "string", + "description": "Source's Database Username", + "default": null, + "x-example": "<USERNAME>" + }, + "password": { + "type": "string", + "description": "Source's Database Password", + "default": null, + "x-example": "<PASSWORD>" + }, + "port": { + "type": "integer", + "description": "Source's Database Port", + "default": 5432, + "x-example": null + } + }, + "required": [ + "resources", + "endpoint", + "apiKey", + "databaseHost", + "username", + "password" + ] + } + } + ] + } + }, + "\/migrations\/supabase\/report": { + "get": { + "summary": "Get Supabase migration report", + "operationId": "migrationsGetSupabaseReport", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "migrations" + ], + "description": "Generate a report of the data in a Supabase project before migrating. This endpoint analyzes the source project and returns information about the resources that can be migrated. ", + "responses": { + "200": { + "description": "Migration Report", + "schema": { + "$ref": "#\/definitions\/migrationReport" + } + } + }, + "x-appwrite": { + "method": "getSupabaseReport", + "group": null, + "weight": 320, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/get-supabase-report.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/migration-supabase-report.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "resources", + "description": "List of resources to migrate", + "required": true, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "in": "query" + }, + { + "name": "endpoint", + "description": "Source's Supabase Endpoint.", + "required": true, + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "in": "query" + }, + { + "name": "apiKey", + "description": "Source's API Key.", + "required": true, + "type": "string", + "x-example": "<API_KEY>", + "in": "query" + }, + { + "name": "databaseHost", + "description": "Source's Database Host.", + "required": true, + "type": "string", + "x-example": "<DATABASE_HOST>", + "in": "query" + }, + { + "name": "username", + "description": "Source's Database Username.", + "required": true, + "type": "string", + "x-example": "<USERNAME>", + "in": "query" + }, + { + "name": "password", + "description": "Source's Database Password.", + "required": true, + "type": "string", + "x-example": "<PASSWORD>", + "in": "query" + }, + { + "name": "port", + "description": "Source's Database Port.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5432, + "in": "query" + } + ] + } + }, + "\/migrations\/{migrationId}": { + "get": { + "summary": "Get migration", + "operationId": "migrationsGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "migrations" + ], + "description": "Get a migration by its unique ID. This endpoint returns detailed information about a specific migration including its current status, progress, and any errors that occurred during the migration process. ", + "responses": { + "200": { + "description": "Migration", + "schema": { + "$ref": "#\/definitions\/migration" + } + } + }, + "x-appwrite": { + "method": "get", + "group": null, + "weight": 317, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/get-migration.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "migrationId", + "description": "Migration unique ID.", + "required": true, + "type": "string", + "x-example": "<MIGRATION_ID>", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update retry migration", + "operationId": "migrationsRetry", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "migrations" + ], + "description": "Retry a failed migration. This endpoint allows you to retry a migration that has previously failed.", + "responses": { + "202": { + "description": "Migration", + "schema": { + "$ref": "#\/definitions\/migration" + } + } + }, + "x-appwrite": { + "method": "retry", + "group": null, + "weight": 322, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/retry.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/retry-migration.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "migrationId", + "description": "Migration unique ID.", + "required": true, + "type": "string", + "x-example": "<MIGRATION_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete migration", + "operationId": "migrationsDelete", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "migrations" + ], + "description": "Delete a migration by its unique ID. This endpoint allows you to remove a migration from your project's migration history. ", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": null, + "weight": 323, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "migrations\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/migrations\/delete-migration.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "migrations.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "migrationId", + "description": "Migration ID.", + "required": true, + "type": "string", + "x-example": "<MIGRATION_ID>", + "in": "path" + } + ] + } + }, + "\/project\/usage": { + "get": { + "summary": "Get project usage stats", + "operationId": "projectGetUsage", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "project" + ], + "description": "Get comprehensive usage statistics for your project. View metrics including network requests, bandwidth, storage, function executions, database usage, and user activity. Specify a time range with startDate and endDate, and optionally set the data granularity with period (1h or 1d). The response includes both total counts and detailed breakdowns by resource, along with historical data over the specified period.", + "responses": { + "200": { + "description": "UsageProject", + "schema": { + "$ref": "#\/definitions\/usageProject" + } + } + }, + "x-appwrite": { + "method": "getUsage", + "group": null, + "weight": 202, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "project\/get-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/project\/get-usage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "startDate", + "description": "Starting date for the usage", + "required": true, + "type": "string", + "in": "query" + }, + { + "name": "endDate", + "description": "End date for the usage", + "required": true, + "type": "string", + "in": "query" + }, + { + "name": "period", + "description": "Period used", + "required": false, + "type": "string", + "x-example": "1h", + "enum": [ + "1h", + "1d" + ], + "x-enum-name": "ProjectUsageRange", + "x-enum-keys": [ + "One Hour", + "One Day" + ], + "default": "1d", + "in": "query" + } + ] + } + }, + "\/project\/variables": { + "get": { + "summary": "List variables", + "operationId": "projectListVariables", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "project" + ], + "description": "Get a list of all project variables. These variables will be accessible in all Appwrite Functions at runtime.", + "responses": { + "200": { + "description": "Variables List", + "schema": { + "$ref": "#\/definitions\/variableList" + } + } + }, + "x-appwrite": { + "method": "listVariables", + "group": null, + "weight": 204, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "project\/list-variables.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/project\/list-variables.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ] + }, + "post": { + "summary": "Create variable", + "operationId": "projectCreateVariable", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "project" + ], + "description": "Create a new project variable. This variable will be accessible in all Appwrite Functions at runtime.", + "responses": { + "201": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "createVariable", + "group": null, + "weight": 203, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "project\/create-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/project\/create-variable.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "default": null, + "x-example": "<KEY>" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "default": null, + "x-example": "<VALUE>" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only projects can read them during build and runtime.", + "default": true, + "x-example": false + } + }, + "required": [ + "key", + "value" + ] + } + } + ] + } + }, + "\/project\/variables\/{variableId}": { + "get": { + "summary": "Get variable", + "operationId": "projectGetVariable", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "project" + ], + "description": "Get a project variable by its unique ID.", + "responses": { + "200": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "getVariable", + "group": null, + "weight": 205, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "project\/get-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/project\/get-variable.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "type": "string", + "x-example": "<VARIABLE_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update variable", + "operationId": "projectUpdateVariable", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "project" + ], + "description": "Update project variable by its unique ID. This variable will be accessible in all Appwrite Functions at runtime.", + "responses": { + "200": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "updateVariable", + "group": null, + "weight": 206, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "project\/update-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/project\/update-variable.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "type": "string", + "x-example": "<VARIABLE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "default": null, + "x-example": "<KEY>" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "default": null, + "x-example": "<VALUE>" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only projects can read them during build and runtime.", + "default": null, + "x-example": false + } + }, + "required": [ + "key" + ] + } + } + ] + }, + "delete": { + "summary": "Delete variable", + "operationId": "projectDeleteVariable", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "project" + ], + "description": "Delete a project variable by its unique ID. ", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteVariable", + "group": null, + "weight": 207, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "project\/delete-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/project\/delete-variable.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "type": "string", + "x-example": "<VARIABLE_ID>", + "in": "path" + } + ] + } + }, + "\/projects": { + "get": { + "summary": "List projects", + "operationId": "projectsList", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Get a list of all projects. You can use the query params to filter your results. ", + "responses": { + "200": { + "description": "Projects List", + "schema": { + "$ref": "#\/definitions\/projectList" + } + } + }, + "x-appwrite": { + "method": "list", + "group": "projects", + "weight": 157, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/list.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, teamId", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create project", + "operationId": "projectsCreate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Create a new project. You can create a maximum of 100 projects per account. ", + "responses": { + "201": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "create", + "group": "projects", + "weight": 156, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "projectId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, and hyphen. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": null + }, + "name": { + "type": "string", + "description": "Project name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "teamId": { + "type": "string", + "description": "Team unique ID.", + "default": null, + "x-example": "<TEAM_ID>" + }, + "region": { + "type": "string", + "description": "Project Region.", + "default": "default", + "x-example": "default", + "enum": [ + "default" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "description": { + "type": "string", + "description": "Project description. Max length: 256 chars.", + "default": "", + "x-example": "<DESCRIPTION>" + }, + "logo": { + "type": "string", + "description": "Project logo.", + "default": "", + "x-example": "<LOGO>" + }, + "url": { + "type": "string", + "description": "Project URL.", + "default": "", + "x-example": "https:\/\/example.com" + }, + "legalName": { + "type": "string", + "description": "Project legal Name. Max length: 256 chars.", + "default": "", + "x-example": "<LEGAL_NAME>" + }, + "legalCountry": { + "type": "string", + "description": "Project legal Country. Max length: 256 chars.", + "default": "", + "x-example": "<LEGAL_COUNTRY>" + }, + "legalState": { + "type": "string", + "description": "Project legal State. Max length: 256 chars.", + "default": "", + "x-example": "<LEGAL_STATE>" + }, + "legalCity": { + "type": "string", + "description": "Project legal City. Max length: 256 chars.", + "default": "", + "x-example": "<LEGAL_CITY>" + }, + "legalAddress": { + "type": "string", + "description": "Project legal Address. Max length: 256 chars.", + "default": "", + "x-example": "<LEGAL_ADDRESS>" + }, + "legalTaxId": { + "type": "string", + "description": "Project legal Tax ID. Max length: 256 chars.", + "default": "", + "x-example": "<LEGAL_TAX_ID>" + } + }, + "required": [ + "projectId", + "name", + "teamId" + ] + } + } + ] + } + }, + "\/projects\/{projectId}": { + "get": { + "summary": "Get project", + "operationId": "projectsGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Get a project by its unique ID. This endpoint allows you to retrieve the project's details, including its name, description, team, region, and other metadata. ", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "get", + "group": "projects", + "weight": 158, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update project", + "operationId": "projectsUpdate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update a project by its unique ID.", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "update", + "group": "projects", + "weight": 159, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Project name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "description": { + "type": "string", + "description": "Project description. Max length: 256 chars.", + "default": "", + "x-example": "<DESCRIPTION>" + }, + "logo": { + "type": "string", + "description": "Project logo.", + "default": "", + "x-example": "<LOGO>" + }, + "url": { + "type": "string", + "description": "Project URL.", + "default": "", + "x-example": "https:\/\/example.com" + }, + "legalName": { + "type": "string", + "description": "Project legal name. Max length: 256 chars.", + "default": "", + "x-example": "<LEGAL_NAME>" + }, + "legalCountry": { + "type": "string", + "description": "Project legal country. Max length: 256 chars.", + "default": "", + "x-example": "<LEGAL_COUNTRY>" + }, + "legalState": { + "type": "string", + "description": "Project legal state. Max length: 256 chars.", + "default": "", + "x-example": "<LEGAL_STATE>" + }, + "legalCity": { + "type": "string", + "description": "Project legal city. Max length: 256 chars.", + "default": "", + "x-example": "<LEGAL_CITY>" + }, + "legalAddress": { + "type": "string", + "description": "Project legal address. Max length: 256 chars.", + "default": "", + "x-example": "<LEGAL_ADDRESS>" + }, + "legalTaxId": { + "type": "string", + "description": "Project legal tax ID. Max length: 256 chars.", + "default": "", + "x-example": "<LEGAL_TAX_ID>" + } + }, + "required": [ + "name" + ] + } + } + ] + }, + "delete": { + "summary": "Delete project", + "operationId": "projectsDelete", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "projects" + ], + "description": "Delete a project by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "projects", + "weight": 176, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + } + ] + } + }, + "\/projects\/{projectId}\/api": { + "patch": { + "summary": "Update API status", + "operationId": "projectsUpdateApiStatus", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update the status of a specific API type. Use this endpoint to enable or disable API types such as REST, GraphQL and Realtime.", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "updateApiStatus", + "group": "projects", + "weight": 163, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-api-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-api-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "api": { + "type": "string", + "description": "API name.", + "default": null, + "x-example": "rest", + "enum": [ + "rest", + "graphql", + "realtime" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "status": { + "type": "boolean", + "description": "API status.", + "default": null, + "x-example": false + } + }, + "required": [ + "api", + "status" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/api\/all": { + "patch": { + "summary": "Update all API status", + "operationId": "projectsUpdateApiStatusAll", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update the status of all API types. Use this endpoint to enable or disable API types such as REST, GraphQL and Realtime all at once.", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "updateApiStatusAll", + "group": "projects", + "weight": 164, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-api-status-all.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-api-status-all.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "status": { + "type": "boolean", + "description": "API status.", + "default": null, + "x-example": false + } + }, + "required": [ + "status" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/auth\/duration": { + "patch": { + "summary": "Update project authentication duration", + "operationId": "projectsUpdateAuthDuration", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update how long sessions created within a project should stay active for.", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "updateAuthDuration", + "group": "auth", + "weight": 169, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-auth-duration.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-duration.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "duration": { + "type": "integer", + "description": "Project session length in seconds. Max length: 31536000 seconds.", + "default": null, + "x-example": 0 + } + }, + "required": [ + "duration" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/auth\/limit": { + "patch": { + "summary": "Update project users limit", + "operationId": "projectsUpdateAuthLimit", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update the maximum number of users allowed in this project. Set to 0 for unlimited users. ", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "updateAuthLimit", + "group": "auth", + "weight": 168, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-auth-limit.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-limit.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "limit": { + "type": "integer", + "description": "Set the max number of users allowed in this project. Use 0 for unlimited.", + "default": null, + "x-example": 0 + } + }, + "required": [ + "limit" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/auth\/max-sessions": { + "patch": { + "summary": "Update project user sessions limit", + "operationId": "projectsUpdateAuthSessionsLimit", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update the maximum number of sessions allowed per user within the project, if the limit is hit the oldest session will be deleted to make room for new sessions.", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "updateAuthSessionsLimit", + "group": "auth", + "weight": 174, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-auth-sessions-limit.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-sessions-limit.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "limit": { + "type": "integer", + "description": "Set the max number of users allowed in this project. Value allowed is between 1-100. Default is 10", + "default": null, + "x-example": 1 + } + }, + "required": [ + "limit" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/auth\/memberships-privacy": { + "patch": { + "summary": "Update project memberships privacy attributes", + "operationId": "projectsUpdateMembershipsPrivacy", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update project membership privacy settings. Use this endpoint to control what user information is visible to other team members, such as user name, email, and MFA status. ", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "updateMembershipsPrivacy", + "group": "auth", + "weight": 167, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-memberships-privacy.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-memberships-privacy.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userName": { + "type": "boolean", + "description": "Set to true to show userName to members of a team.", + "default": null, + "x-example": false + }, + "userEmail": { + "type": "boolean", + "description": "Set to true to show email to members of a team.", + "default": null, + "x-example": false + }, + "mfa": { + "type": "boolean", + "description": "Set to true to show mfa to members of a team.", + "default": null, + "x-example": false + } + }, + "required": [ + "userName", + "userEmail", + "mfa" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/auth\/mock-numbers": { + "patch": { + "summary": "Update the mock numbers for the project", + "operationId": "projectsUpdateMockNumbers", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update the list of mock phone numbers for testing. Use these numbers to bypass SMS verification in development. ", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "updateMockNumbers", + "group": "auth", + "weight": 175, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-mock-numbers.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-mock-numbers.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "numbers": { + "type": "array", + "description": "An array of mock numbers and their corresponding verification codes (OTPs). Each number should be a valid E.164 formatted phone number. Maximum of 10 numbers are allowed.", + "default": null, + "x-example": null, + "items": { + "type": "object" + } + } + }, + "required": [ + "numbers" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/auth\/password-dictionary": { + "patch": { + "summary": "Update authentication password dictionary status. Use this endpoint to enable or disable the dicitonary check for user password", + "operationId": "projectsUpdateAuthPasswordDictionary", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Enable or disable checking user passwords against common passwords dictionary. This helps ensure users don't use common and insecure passwords. ", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "updateAuthPasswordDictionary", + "group": "auth", + "weight": 172, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-auth-password-dictionary.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-password-dictionary.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Set whether or not to enable checking user's password against most commonly used passwords. Default is false.", + "default": null, + "x-example": false + } + }, + "required": [ + "enabled" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/auth\/password-history": { + "patch": { + "summary": "Update authentication password history. Use this endpoint to set the number of password history to save and 0 to disable password history.", + "operationId": "projectsUpdateAuthPasswordHistory", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update the authentication password history requirement. Use this endpoint to require new passwords to be different than the last X amount of previously used ones.", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "updateAuthPasswordHistory", + "group": "auth", + "weight": 171, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-auth-password-history.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-password-history.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "limit": { + "type": "integer", + "description": "Set the max number of passwords to store in user history. User can't choose a new password that is already stored in the password history list. Max number of passwords allowed in history is20. Default value is 0", + "default": null, + "x-example": 0 + } + }, + "required": [ + "limit" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/auth\/personal-data": { + "patch": { + "summary": "Update personal data check", + "operationId": "projectsUpdatePersonalDataCheck", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Enable or disable checking user passwords against their personal data. This helps prevent users from using personal information in their passwords. ", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "updatePersonalDataCheck", + "group": "auth", + "weight": 173, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-personal-data-check.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-personal-data-check.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Set whether or not to check a password for similarity with personal data. Default is false.", + "default": null, + "x-example": false + } + }, + "required": [ + "enabled" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/auth\/session-alerts": { + "patch": { + "summary": "Update project sessions emails", + "operationId": "projectsUpdateSessionAlerts", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Enable or disable session email alerts. When enabled, users will receive email notifications when new sessions are created.", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "updateSessionAlerts", + "group": "auth", + "weight": 166, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-session-alerts.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-session-alerts.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "alerts": { + "type": "boolean", + "description": "Set to true to enable session emails.", + "default": null, + "x-example": false + } + }, + "required": [ + "alerts" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/auth\/{method}": { + "patch": { + "summary": "Update project auth method status. Use this endpoint to enable or disable a given auth method for this project.", + "operationId": "projectsUpdateAuthStatus", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update the status of a specific authentication method. Use this endpoint to enable or disable different authentication methods such as email, magic urls or sms in your project. ", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "updateAuthStatus", + "group": "auth", + "weight": 170, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-auth-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-auth-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "method", + "description": "Auth Method. Possible values: email-password,magic-url,email-otp,anonymous,invites,jwt,phone", + "required": true, + "type": "string", + "x-example": "email-password", + "enum": [ + "email-password", + "magic-url", + "email-otp", + "anonymous", + "invites", + "jwt", + "phone" + ], + "x-enum-name": "AuthMethod", + "x-enum-keys": [], + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "status": { + "type": "boolean", + "description": "Set the status of this auth method.", + "default": null, + "x-example": false + } + }, + "required": [ + "status" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/dev-keys": { + "get": { + "summary": "List dev keys", + "operationId": "projectsListDevKeys", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "List all the project\\'s dev keys. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development.'", + "responses": { + "200": { + "description": "Dev Keys List", + "schema": { + "$ref": "#\/definitions\/devKeyList" + } + } + }, + "x-appwrite": { + "method": "listDevKeys", + "group": "devKeys", + "weight": 373, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/list-dev-keys.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList all the project\\'s dev keys. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development.'", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: accessedAt, expire", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create dev key", + "operationId": "projectsCreateDevKey", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Create a new project dev key. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development. Strictly meant for development purposes only.", + "responses": { + "201": { + "description": "DevKey", + "schema": { + "$ref": "#\/definitions\/devKey" + } + } + }, + "x-appwrite": { + "method": "createDevKey", + "group": "devKeys", + "weight": 370, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/create-dev-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new project dev key. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development. Strictly meant for development purposes only.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Key name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "expire": { + "type": "string", + "description": "Expiration time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format.", + "default": null, + "x-example": null + } + }, + "required": [ + "name", + "expire" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/dev-keys\/{keyId}": { + "get": { + "summary": "Get dev key", + "operationId": "projectsGetDevKey", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Get a project\\'s dev key by its unique ID. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development.", + "responses": { + "200": { + "description": "DevKey", + "schema": { + "$ref": "#\/definitions\/devKey" + } + } + }, + "x-appwrite": { + "method": "getDevKey", + "group": "devKeys", + "weight": 372, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/get-dev-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a project\\'s dev key by its unique ID. Dev keys are project specific and allow you to bypass rate limits and get better error logging during development.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "keyId", + "description": "Key unique ID.", + "required": true, + "type": "string", + "x-example": "<KEY_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update dev key", + "operationId": "projectsUpdateDevKey", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update a project\\'s dev key by its unique ID. Use this endpoint to update a project\\'s dev key name or expiration time.'", + "responses": { + "200": { + "description": "DevKey", + "schema": { + "$ref": "#\/definitions\/devKey" + } + } + }, + "x-appwrite": { + "method": "updateDevKey", + "group": "devKeys", + "weight": 371, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-dev-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate a project\\'s dev key by its unique ID. Use this endpoint to update a project\\'s dev key name or expiration time.'", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "keyId", + "description": "Key unique ID.", + "required": true, + "type": "string", + "x-example": "<KEY_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Key name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "expire": { + "type": "string", + "description": "Expiration time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format.", + "default": null, + "x-example": null + } + }, + "required": [ + "name", + "expire" + ] + } + } + ] + }, + "delete": { + "summary": "Delete dev key", + "operationId": "projectsDeleteDevKey", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "projects" + ], + "description": "Delete a project\\'s dev key by its unique ID. Once deleted, the key will no longer allow bypassing of rate limits and better logging of errors.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDevKey", + "group": "devKeys", + "weight": 374, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/delete-dev-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a project\\'s dev key by its unique ID. Once deleted, the key will no longer allow bypassing of rate limits and better logging of errors.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "keyId", + "description": "Key unique ID.", + "required": true, + "type": "string", + "x-example": "<KEY_ID>", + "in": "path" + } + ] + } + }, + "\/projects\/{projectId}\/jwts": { + "post": { + "summary": "Create JWT", + "operationId": "projectsCreateJWT", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Create a new JWT token. This token can be used to authenticate users with custom scopes and expiration time. ", + "responses": { + "201": { + "description": "JWT", + "schema": { + "$ref": "#\/definitions\/jwt" + } + } + }, + "x-appwrite": { + "method": "createJWT", + "group": "auth", + "weight": 188, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/create-j-w-t.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-jwt.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "scopes": { + "type": "array", + "description": "List of scopes allowed for JWT key. Maximum of 100 scopes are allowed.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "duration": { + "type": "integer", + "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", + "default": 900, + "x-example": 0 + } + }, + "required": [ + "scopes" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/keys": { + "get": { + "summary": "List keys", + "operationId": "projectsListKeys", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Get a list of all API keys from the current project. ", + "responses": { + "200": { + "description": "API Keys List", + "schema": { + "$ref": "#\/definitions\/keyList" + } + } + }, + "x-appwrite": { + "method": "listKeys", + "group": "keys", + "weight": 184, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/list-keys.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/list-keys.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "keys.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + } + ] + }, + "post": { + "summary": "Create key", + "operationId": "projectsCreateKey", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Create a new API key. It's recommended to have multiple API keys with strict scopes for separate functions within your project.", + "responses": { + "201": { + "description": "Key", + "schema": { + "$ref": "#\/definitions\/key" + } + } + }, + "x-appwrite": { + "method": "createKey", + "group": "keys", + "weight": 183, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/create-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-key.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "keys.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Key name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "scopes": { + "type": "array", + "description": "Key scopes list. Maximum of 100 scopes are allowed.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "expire": { + "type": "string", + "description": "Expiration time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Use null for unlimited expiration.", + "default": null, + "x-example": null + } + }, + "required": [ + "name", + "scopes" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/keys\/{keyId}": { + "get": { + "summary": "Get key", + "operationId": "projectsGetKey", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Get a key by its unique ID. This endpoint returns details about a specific API key in your project including it's scopes.", + "responses": { + "200": { + "description": "Key", + "schema": { + "$ref": "#\/definitions\/key" + } + } + }, + "x-appwrite": { + "method": "getKey", + "group": "keys", + "weight": 185, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/get-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-key.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "keys.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "keyId", + "description": "Key unique ID.", + "required": true, + "type": "string", + "x-example": "<KEY_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update key", + "operationId": "projectsUpdateKey", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update a key by its unique ID. Use this endpoint to update the name, scopes, or expiration time of an API key. ", + "responses": { + "200": { + "description": "Key", + "schema": { + "$ref": "#\/definitions\/key" + } + } + }, + "x-appwrite": { + "method": "updateKey", + "group": "keys", + "weight": 186, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-key.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "keys.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "keyId", + "description": "Key unique ID.", + "required": true, + "type": "string", + "x-example": "<KEY_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Key name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "scopes": { + "type": "array", + "description": "Key scopes list. Maximum of 100 events are allowed.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "expire": { + "type": "string", + "description": "Expiration time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Use null for unlimited expiration.", + "default": null, + "x-example": null + } + }, + "required": [ + "name", + "scopes" + ] + } + } + ] + }, + "delete": { + "summary": "Delete key", + "operationId": "projectsDeleteKey", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "projects" + ], + "description": "Delete a key by its unique ID. Once deleted, the key can no longer be used to authenticate API calls. ", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteKey", + "group": "keys", + "weight": 187, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/delete-key.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-key.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "keys.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "keyId", + "description": "Key unique ID.", + "required": true, + "type": "string", + "x-example": "<KEY_ID>", + "in": "path" + } + ] + } + }, + "\/projects\/{projectId}\/oauth2": { + "patch": { + "summary": "Update project OAuth2", + "operationId": "projectsUpdateOAuth2", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update the OAuth2 provider configurations. Use this endpoint to set up or update the OAuth2 provider credentials or enable\/disable providers. ", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "updateOAuth2", + "group": "auth", + "weight": 165, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-o-auth2.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-oauth2.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "provider": { + "type": "string", + "description": "Provider Name", + "default": null, + "x-example": "amazon", + "enum": [ + "amazon", + "apple", + "auth0", + "authentik", + "autodesk", + "bitbucket", + "bitly", + "box", + "dailymotion", + "discord", + "disqus", + "dropbox", + "etsy", + "facebook", + "figma", + "github", + "gitlab", + "google", + "linkedin", + "microsoft", + "notion", + "oidc", + "okta", + "paypal", + "paypalSandbox", + "podio", + "salesforce", + "slack", + "spotify", + "stripe", + "tradeshift", + "tradeshiftBox", + "twitch", + "wordpress", + "yahoo", + "yammer", + "yandex", + "zoho", + "zoom", + "mock" + ], + "x-enum-name": "OAuthProvider", + "x-enum-keys": [] + }, + "appId": { + "type": "string", + "description": "Provider app ID. Max length: 256 chars.", + "default": null, + "x-example": "<APP_ID>" + }, + "secret": { + "type": "string", + "description": "Provider secret key. Max length: 512 chars.", + "default": null, + "x-example": "<SECRET>" + }, + "enabled": { + "type": "boolean", + "description": "Provider status. Set to 'false' to disable new session creation.", + "default": null, + "x-example": false + } + }, + "required": [ + "provider" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/platforms": { + "get": { + "summary": "List platforms", + "operationId": "projectsListPlatforms", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Get a list of all platforms in the project. This endpoint returns an array of all platforms and their configurations. ", + "responses": { + "200": { + "description": "Platforms List", + "schema": { + "$ref": "#\/definitions\/platformList" + } + } + }, + "x-appwrite": { + "method": "listPlatforms", + "group": "platforms", + "weight": 190, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/list-platforms.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/list-platforms.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "platforms.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + } + ] + }, + "post": { + "summary": "Create platform", + "operationId": "projectsCreatePlatform", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Create a new platform for your project. Use this endpoint to register a new platform where your users will run your application which will interact with the Appwrite API.", + "responses": { + "201": { + "description": "Platform", + "schema": { + "$ref": "#\/definitions\/platform" + } + } + }, + "x-appwrite": { + "method": "createPlatform", + "group": "platforms", + "weight": 189, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/create-platform.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-platform.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "platforms.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Platform type.", + "default": null, + "x-example": "web", + "enum": [ + "web", + "flutter-web", + "flutter-ios", + "flutter-android", + "flutter-linux", + "flutter-macos", + "flutter-windows", + "apple-ios", + "apple-macos", + "apple-watchos", + "apple-tvos", + "android", + "unity", + "react-native-ios", + "react-native-android" + ], + "x-enum-name": "PlatformType", + "x-enum-keys": [] + }, + "name": { + "type": "string", + "description": "Platform name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "key": { + "type": "string", + "description": "Package name for Android or bundle ID for iOS or macOS. Max length: 256 chars.", + "default": "", + "x-example": "<KEY>" + }, + "store": { + "type": "string", + "description": "App store or Google Play store ID. Max length: 256 chars.", + "default": "", + "x-example": "<STORE>" + }, + "hostname": { + "type": "string", + "description": "Platform client hostname. Max length: 256 chars.", + "default": "", + "x-example": null + } + }, + "required": [ + "type", + "name" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/platforms\/{platformId}": { + "get": { + "summary": "Get platform", + "operationId": "projectsGetPlatform", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Get a platform by its unique ID. This endpoint returns the platform's details, including its name, type, and key configurations. ", + "responses": { + "200": { + "description": "Platform", + "schema": { + "$ref": "#\/definitions\/platform" + } + } + }, + "x-appwrite": { + "method": "getPlatform", + "group": "platforms", + "weight": 191, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/get-platform.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-platform.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "platforms.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "platformId", + "description": "Platform unique ID.", + "required": true, + "type": "string", + "x-example": "<PLATFORM_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update platform", + "operationId": "projectsUpdatePlatform", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update a platform by its unique ID. Use this endpoint to update the platform's name, key, platform store ID, or hostname. ", + "responses": { + "200": { + "description": "Platform", + "schema": { + "$ref": "#\/definitions\/platform" + } + } + }, + "x-appwrite": { + "method": "updatePlatform", + "group": "platforms", + "weight": 192, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-platform.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-platform.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "platforms.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "platformId", + "description": "Platform unique ID.", + "required": true, + "type": "string", + "x-example": "<PLATFORM_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Platform name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "key": { + "type": "string", + "description": "Package name for android or bundle ID for iOS. Max length: 256 chars.", + "default": "", + "x-example": "<KEY>" + }, + "store": { + "type": "string", + "description": "App store or Google Play store ID. Max length: 256 chars.", + "default": "", + "x-example": "<STORE>" + }, + "hostname": { + "type": "string", + "description": "Platform client URL. Max length: 256 chars.", + "default": "", + "x-example": null + } + }, + "required": [ + "name" + ] + } + } + ] + }, + "delete": { + "summary": "Delete platform", + "operationId": "projectsDeletePlatform", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "projects" + ], + "description": "Delete a platform by its unique ID. This endpoint removes the platform and all its configurations from the project. ", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deletePlatform", + "group": "platforms", + "weight": 193, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/delete-platform.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-platform.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "platforms.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "platformId", + "description": "Platform unique ID.", + "required": true, + "type": "string", + "x-example": "<PLATFORM_ID>", + "in": "path" + } + ] + } + }, + "\/projects\/{projectId}\/service": { + "patch": { + "summary": "Update service status", + "operationId": "projectsUpdateServiceStatus", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update the status of a specific service. Use this endpoint to enable or disable a service in your project. ", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "updateServiceStatus", + "group": "projects", + "weight": 161, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-service-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-service-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "service": { + "type": "string", + "description": "Service name.", + "default": null, + "x-example": "account", + "enum": [ + "account", + "avatars", + "databases", + "locale", + "health", + "storage", + "teams", + "users", + "sites", + "functions", + "graphql", + "messaging" + ], + "x-enum-name": "ApiService", + "x-enum-keys": [] + }, + "status": { + "type": "boolean", + "description": "Service status.", + "default": null, + "x-example": false + } + }, + "required": [ + "service", + "status" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/service\/all": { + "patch": { + "summary": "Update all service status", + "operationId": "projectsUpdateServiceStatusAll", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update the status of all services. Use this endpoint to enable or disable all optional services at once. ", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "updateServiceStatusAll", + "group": "projects", + "weight": 162, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-service-status-all.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-service-status-all.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "status": { + "type": "boolean", + "description": "Service status.", + "default": null, + "x-example": false + } + }, + "required": [ + "status" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/smtp": { + "patch": { + "summary": "Update SMTP", + "operationId": "projectsUpdateSmtp", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update the SMTP configuration for your project. Use this endpoint to configure your project's SMTP provider with your custom settings for sending transactional emails. ", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "updateSmtp", + "group": "templates", + "weight": 194, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-smtp.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-smtp.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "enabled": { + "type": "boolean", + "description": "Enable custom SMTP service", + "default": null, + "x-example": false + }, + "senderName": { + "type": "string", + "description": "Name of the email sender", + "default": "", + "x-example": "<SENDER_NAME>" + }, + "senderEmail": { + "type": "string", + "description": "Email of the sender", + "default": "", + "x-example": "email@example.com" + }, + "replyTo": { + "type": "string", + "description": "Reply to email", + "default": "", + "x-example": "email@example.com" + }, + "host": { + "type": "string", + "description": "SMTP server host name", + "default": "", + "x-example": null + }, + "port": { + "type": "integer", + "description": "SMTP server port", + "default": 587, + "x-example": null + }, + "username": { + "type": "string", + "description": "SMTP server username", + "default": "", + "x-example": "<USERNAME>" + }, + "password": { + "type": "string", + "description": "SMTP server password", + "default": "", + "x-example": "<PASSWORD>" + }, + "secure": { + "type": "string", + "description": "Does SMTP server use secure connection", + "default": "", + "x-example": "tls", + "enum": [ + "tls", + "ssl" + ], + "x-enum-name": "SMTPSecure", + "x-enum-keys": [] + } + }, + "required": [ + "enabled" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/smtp\/tests": { + "post": { + "summary": "Create SMTP test", + "operationId": "projectsCreateSmtpTest", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Send a test email to verify SMTP configuration. ", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "createSmtpTest", + "group": "templates", + "weight": 195, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/create-smtp-test.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-smtp-test.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "emails": { + "type": "array", + "description": "Array of emails to send test email to. Maximum of 10 emails are allowed.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "senderName": { + "type": "string", + "description": "Name of the email sender", + "default": null, + "x-example": "<SENDER_NAME>" + }, + "senderEmail": { + "type": "string", + "description": "Email of the sender", + "default": null, + "x-example": "email@example.com" + }, + "replyTo": { + "type": "string", + "description": "Reply to email", + "default": "", + "x-example": "email@example.com" + }, + "host": { + "type": "string", + "description": "SMTP server host name", + "default": null, + "x-example": null + }, + "port": { + "type": "integer", + "description": "SMTP server port", + "default": 587, + "x-example": null + }, + "username": { + "type": "string", + "description": "SMTP server username", + "default": "", + "x-example": "<USERNAME>" + }, + "password": { + "type": "string", + "description": "SMTP server password", + "default": "", + "x-example": "<PASSWORD>" + }, + "secure": { + "type": "string", + "description": "Does SMTP server use secure connection", + "default": "", + "x-example": "tls", + "enum": [ + "tls", + "ssl" + ], + "x-enum-name": "SMTPSecure", + "x-enum-keys": [] + } + }, + "required": [ + "emails", + "senderName", + "senderEmail", + "host" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/team": { + "patch": { + "summary": "Update project team", + "operationId": "projectsUpdateTeam", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update the team ID of a project allowing for it to be transferred to another team.", + "responses": { + "200": { + "description": "Project", + "schema": { + "$ref": "#\/definitions\/project" + } + } + }, + "x-appwrite": { + "method": "updateTeam", + "group": "projects", + "weight": 160, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-team.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "teamId": { + "type": "string", + "description": "Team ID of the team to transfer project to.", + "default": null, + "x-example": "<TEAM_ID>" + } + }, + "required": [ + "teamId" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/templates\/email\/{type}\/{locale}": { + "get": { + "summary": "Get custom email template", + "operationId": "projectsGetEmailTemplate", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Get a custom email template for the specified locale and type. This endpoint returns the template content, subject, and other configuration details. ", + "responses": { + "200": { + "description": "EmailTemplate", + "schema": { + "$ref": "#\/definitions\/emailTemplate" + } + } + }, + "x-appwrite": { + "method": "getEmailTemplate", + "group": "templates", + "weight": 197, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/get-email-template.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-email-template.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "type", + "description": "Template type", + "required": true, + "type": "string", + "x-example": "verification", + "enum": [ + "verification", + "magicsession", + "recovery", + "invitation", + "mfachallenge", + "sessionalert", + "otpsession" + ], + "x-enum-name": "EmailTemplateType", + "x-enum-keys": [], + "in": "path" + }, + { + "name": "locale", + "description": "Template locale", + "required": true, + "type": "string", + "x-example": "af", + "enum": [ + "af", + "ar-ae", + "ar-bh", + "ar-dz", + "ar-eg", + "ar-iq", + "ar-jo", + "ar-kw", + "ar-lb", + "ar-ly", + "ar-ma", + "ar-om", + "ar-qa", + "ar-sa", + "ar-sy", + "ar-tn", + "ar-ye", + "as", + "az", + "be", + "bg", + "bh", + "bn", + "bs", + "ca", + "cs", + "cy", + "da", + "de", + "de-at", + "de-ch", + "de-li", + "de-lu", + "el", + "en", + "en-au", + "en-bz", + "en-ca", + "en-gb", + "en-ie", + "en-jm", + "en-nz", + "en-tt", + "en-us", + "en-za", + "eo", + "es", + "es-ar", + "es-bo", + "es-cl", + "es-co", + "es-cr", + "es-do", + "es-ec", + "es-gt", + "es-hn", + "es-mx", + "es-ni", + "es-pa", + "es-pe", + "es-pr", + "es-py", + "es-sv", + "es-uy", + "es-ve", + "et", + "eu", + "fa", + "fi", + "fo", + "fr", + "fr-be", + "fr-ca", + "fr-ch", + "fr-lu", + "ga", + "gd", + "he", + "hi", + "hr", + "hu", + "id", + "is", + "it", + "it-ch", + "ja", + "ji", + "ko", + "ku", + "lt", + "lv", + "mk", + "ml", + "ms", + "mt", + "nb", + "ne", + "nl", + "nl-be", + "nn", + "no", + "pa", + "pl", + "pt", + "pt-br", + "rm", + "ro", + "ro-md", + "ru", + "ru-md", + "sb", + "sk", + "sl", + "sq", + "sr", + "sv", + "sv-fi", + "th", + "tn", + "tr", + "ts", + "ua", + "ur", + "ve", + "vi", + "xh", + "zh-cn", + "zh-hk", + "zh-sg", + "zh-tw", + "zu" + ], + "x-enum-name": "EmailTemplateLocale", + "x-enum-keys": [], + "in": "path" + } + ] + }, + "patch": { + "summary": "Update custom email templates", + "operationId": "projectsUpdateEmailTemplate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update a custom email template for the specified locale and type. Use this endpoint to modify the content of your email templates.", + "responses": { + "200": { + "description": "EmailTemplate", + "schema": { + "$ref": "#\/definitions\/emailTemplate" + } + } + }, + "x-appwrite": { + "method": "updateEmailTemplate", + "group": "templates", + "weight": 199, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-email-template.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-email-template.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "type", + "description": "Template type", + "required": true, + "type": "string", + "x-example": "verification", + "enum": [ + "verification", + "magicsession", + "recovery", + "invitation", + "mfachallenge", + "sessionalert", + "otpsession" + ], + "x-enum-name": "EmailTemplateType", + "x-enum-keys": [], + "in": "path" + }, + { + "name": "locale", + "description": "Template locale", + "required": true, + "type": "string", + "x-example": "af", + "enum": [ + "af", + "ar-ae", + "ar-bh", + "ar-dz", + "ar-eg", + "ar-iq", + "ar-jo", + "ar-kw", + "ar-lb", + "ar-ly", + "ar-ma", + "ar-om", + "ar-qa", + "ar-sa", + "ar-sy", + "ar-tn", + "ar-ye", + "as", + "az", + "be", + "bg", + "bh", + "bn", + "bs", + "ca", + "cs", + "cy", + "da", + "de", + "de-at", + "de-ch", + "de-li", + "de-lu", + "el", + "en", + "en-au", + "en-bz", + "en-ca", + "en-gb", + "en-ie", + "en-jm", + "en-nz", + "en-tt", + "en-us", + "en-za", + "eo", + "es", + "es-ar", + "es-bo", + "es-cl", + "es-co", + "es-cr", + "es-do", + "es-ec", + "es-gt", + "es-hn", + "es-mx", + "es-ni", + "es-pa", + "es-pe", + "es-pr", + "es-py", + "es-sv", + "es-uy", + "es-ve", + "et", + "eu", + "fa", + "fi", + "fo", + "fr", + "fr-be", + "fr-ca", + "fr-ch", + "fr-lu", + "ga", + "gd", + "he", + "hi", + "hr", + "hu", + "id", + "is", + "it", + "it-ch", + "ja", + "ji", + "ko", + "ku", + "lt", + "lv", + "mk", + "ml", + "ms", + "mt", + "nb", + "ne", + "nl", + "nl-be", + "nn", + "no", + "pa", + "pl", + "pt", + "pt-br", + "rm", + "ro", + "ro-md", + "ru", + "ru-md", + "sb", + "sk", + "sl", + "sq", + "sr", + "sv", + "sv-fi", + "th", + "tn", + "tr", + "ts", + "ua", + "ur", + "ve", + "vi", + "xh", + "zh-cn", + "zh-hk", + "zh-sg", + "zh-tw", + "zu" + ], + "x-enum-name": "EmailTemplateLocale", + "x-enum-keys": [], + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "subject": { + "type": "string", + "description": "Email Subject", + "default": null, + "x-example": "<SUBJECT>" + }, + "message": { + "type": "string", + "description": "Template message", + "default": null, + "x-example": "<MESSAGE>" + }, + "senderName": { + "type": "string", + "description": "Name of the email sender", + "default": "", + "x-example": "<SENDER_NAME>" + }, + "senderEmail": { + "type": "string", + "description": "Email of the sender", + "default": "", + "x-example": "email@example.com" + }, + "replyTo": { + "type": "string", + "description": "Reply to email", + "default": "", + "x-example": "email@example.com" + } + }, + "required": [ + "subject", + "message" + ] + } + } + ] + }, + "delete": { + "summary": "Delete custom email template", + "operationId": "projectsDeleteEmailTemplate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Reset a custom email template to its default value. This endpoint removes any custom content and restores the template to its original state. ", + "responses": { + "200": { + "description": "EmailTemplate", + "schema": { + "$ref": "#\/definitions\/emailTemplate" + } + } + }, + "x-appwrite": { + "method": "deleteEmailTemplate", + "group": "templates", + "weight": 201, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/delete-email-template.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-email-template.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "type", + "description": "Template type", + "required": true, + "type": "string", + "x-example": "verification", + "enum": [ + "verification", + "magicsession", + "recovery", + "invitation", + "mfachallenge", + "sessionalert", + "otpsession" + ], + "x-enum-name": "EmailTemplateType", + "x-enum-keys": [], + "in": "path" + }, + { + "name": "locale", + "description": "Template locale", + "required": true, + "type": "string", + "x-example": "af", + "enum": [ + "af", + "ar-ae", + "ar-bh", + "ar-dz", + "ar-eg", + "ar-iq", + "ar-jo", + "ar-kw", + "ar-lb", + "ar-ly", + "ar-ma", + "ar-om", + "ar-qa", + "ar-sa", + "ar-sy", + "ar-tn", + "ar-ye", + "as", + "az", + "be", + "bg", + "bh", + "bn", + "bs", + "ca", + "cs", + "cy", + "da", + "de", + "de-at", + "de-ch", + "de-li", + "de-lu", + "el", + "en", + "en-au", + "en-bz", + "en-ca", + "en-gb", + "en-ie", + "en-jm", + "en-nz", + "en-tt", + "en-us", + "en-za", + "eo", + "es", + "es-ar", + "es-bo", + "es-cl", + "es-co", + "es-cr", + "es-do", + "es-ec", + "es-gt", + "es-hn", + "es-mx", + "es-ni", + "es-pa", + "es-pe", + "es-pr", + "es-py", + "es-sv", + "es-uy", + "es-ve", + "et", + "eu", + "fa", + "fi", + "fo", + "fr", + "fr-be", + "fr-ca", + "fr-ch", + "fr-lu", + "ga", + "gd", + "he", + "hi", + "hr", + "hu", + "id", + "is", + "it", + "it-ch", + "ja", + "ji", + "ko", + "ku", + "lt", + "lv", + "mk", + "ml", + "ms", + "mt", + "nb", + "ne", + "nl", + "nl-be", + "nn", + "no", + "pa", + "pl", + "pt", + "pt-br", + "rm", + "ro", + "ro-md", + "ru", + "ru-md", + "sb", + "sk", + "sl", + "sq", + "sr", + "sv", + "sv-fi", + "th", + "tn", + "tr", + "ts", + "ua", + "ur", + "ve", + "vi", + "xh", + "zh-cn", + "zh-hk", + "zh-sg", + "zh-tw", + "zu" + ], + "x-enum-name": "EmailTemplateLocale", + "x-enum-keys": [], + "in": "path" + } + ] + } + }, + "\/projects\/{projectId}\/templates\/sms\/{type}\/{locale}": { + "get": { + "summary": "Get custom SMS template", + "operationId": "projectsGetSmsTemplate", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Get a custom SMS template for the specified locale and type returning it's contents.", + "responses": { + "200": { + "description": "SmsTemplate", + "schema": { + "$ref": "#\/definitions\/smsTemplate" + } + } + }, + "x-appwrite": { + "method": "getSmsTemplate", + "group": "templates", + "weight": 196, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/get-sms-template.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-sms-template.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "type", + "description": "Template type", + "required": true, + "type": "string", + "x-example": "verification", + "enum": [ + "verification", + "login", + "invitation", + "mfachallenge" + ], + "x-enum-name": "SmsTemplateType", + "x-enum-keys": [], + "in": "path" + }, + { + "name": "locale", + "description": "Template locale", + "required": true, + "type": "string", + "x-example": "af", + "enum": [ + "af", + "ar-ae", + "ar-bh", + "ar-dz", + "ar-eg", + "ar-iq", + "ar-jo", + "ar-kw", + "ar-lb", + "ar-ly", + "ar-ma", + "ar-om", + "ar-qa", + "ar-sa", + "ar-sy", + "ar-tn", + "ar-ye", + "as", + "az", + "be", + "bg", + "bh", + "bn", + "bs", + "ca", + "cs", + "cy", + "da", + "de", + "de-at", + "de-ch", + "de-li", + "de-lu", + "el", + "en", + "en-au", + "en-bz", + "en-ca", + "en-gb", + "en-ie", + "en-jm", + "en-nz", + "en-tt", + "en-us", + "en-za", + "eo", + "es", + "es-ar", + "es-bo", + "es-cl", + "es-co", + "es-cr", + "es-do", + "es-ec", + "es-gt", + "es-hn", + "es-mx", + "es-ni", + "es-pa", + "es-pe", + "es-pr", + "es-py", + "es-sv", + "es-uy", + "es-ve", + "et", + "eu", + "fa", + "fi", + "fo", + "fr", + "fr-be", + "fr-ca", + "fr-ch", + "fr-lu", + "ga", + "gd", + "he", + "hi", + "hr", + "hu", + "id", + "is", + "it", + "it-ch", + "ja", + "ji", + "ko", + "ku", + "lt", + "lv", + "mk", + "ml", + "ms", + "mt", + "nb", + "ne", + "nl", + "nl-be", + "nn", + "no", + "pa", + "pl", + "pt", + "pt-br", + "rm", + "ro", + "ro-md", + "ru", + "ru-md", + "sb", + "sk", + "sl", + "sq", + "sr", + "sv", + "sv-fi", + "th", + "tn", + "tr", + "ts", + "ua", + "ur", + "ve", + "vi", + "xh", + "zh-cn", + "zh-hk", + "zh-sg", + "zh-tw", + "zu" + ], + "x-enum-name": "SmsTemplateLocale", + "x-enum-keys": [], + "in": "path" + } + ] + }, + "patch": { + "summary": "Update custom SMS template", + "operationId": "projectsUpdateSmsTemplate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update a custom SMS template for the specified locale and type. Use this endpoint to modify the content of your SMS templates. ", + "responses": { + "200": { + "description": "SmsTemplate", + "schema": { + "$ref": "#\/definitions\/smsTemplate" + } + } + }, + "x-appwrite": { + "method": "updateSmsTemplate", + "group": "templates", + "weight": 198, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-sms-template.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-sms-template.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "type", + "description": "Template type", + "required": true, + "type": "string", + "x-example": "verification", + "enum": [ + "verification", + "login", + "invitation", + "mfachallenge" + ], + "x-enum-name": "SmsTemplateType", + "x-enum-keys": [], + "in": "path" + }, + { + "name": "locale", + "description": "Template locale", + "required": true, + "type": "string", + "x-example": "af", + "enum": [ + "af", + "ar-ae", + "ar-bh", + "ar-dz", + "ar-eg", + "ar-iq", + "ar-jo", + "ar-kw", + "ar-lb", + "ar-ly", + "ar-ma", + "ar-om", + "ar-qa", + "ar-sa", + "ar-sy", + "ar-tn", + "ar-ye", + "as", + "az", + "be", + "bg", + "bh", + "bn", + "bs", + "ca", + "cs", + "cy", + "da", + "de", + "de-at", + "de-ch", + "de-li", + "de-lu", + "el", + "en", + "en-au", + "en-bz", + "en-ca", + "en-gb", + "en-ie", + "en-jm", + "en-nz", + "en-tt", + "en-us", + "en-za", + "eo", + "es", + "es-ar", + "es-bo", + "es-cl", + "es-co", + "es-cr", + "es-do", + "es-ec", + "es-gt", + "es-hn", + "es-mx", + "es-ni", + "es-pa", + "es-pe", + "es-pr", + "es-py", + "es-sv", + "es-uy", + "es-ve", + "et", + "eu", + "fa", + "fi", + "fo", + "fr", + "fr-be", + "fr-ca", + "fr-ch", + "fr-lu", + "ga", + "gd", + "he", + "hi", + "hr", + "hu", + "id", + "is", + "it", + "it-ch", + "ja", + "ji", + "ko", + "ku", + "lt", + "lv", + "mk", + "ml", + "ms", + "mt", + "nb", + "ne", + "nl", + "nl-be", + "nn", + "no", + "pa", + "pl", + "pt", + "pt-br", + "rm", + "ro", + "ro-md", + "ru", + "ru-md", + "sb", + "sk", + "sl", + "sq", + "sr", + "sv", + "sv-fi", + "th", + "tn", + "tr", + "ts", + "ua", + "ur", + "ve", + "vi", + "xh", + "zh-cn", + "zh-hk", + "zh-sg", + "zh-tw", + "zu" + ], + "x-enum-name": "SmsTemplateLocale", + "x-enum-keys": [], + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "message": { + "type": "string", + "description": "Template message", + "default": null, + "x-example": "<MESSAGE>" + } + }, + "required": [ + "message" + ] + } + } + ] + }, + "delete": { + "summary": "Reset custom SMS template", + "operationId": "projectsDeleteSmsTemplate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Reset a custom SMS template to its default value. This endpoint removes any custom message and restores the template to its original state. ", + "responses": { + "200": { + "description": "SmsTemplate", + "schema": { + "$ref": "#\/definitions\/smsTemplate" + } + } + }, + "x-appwrite": { + "method": "deleteSmsTemplate", + "group": "templates", + "weight": 200, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/delete-sms-template.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-sms-template.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "type", + "description": "Template type", + "required": true, + "type": "string", + "x-example": "verification", + "enum": [ + "verification", + "login", + "invitation", + "mfachallenge" + ], + "x-enum-name": "SmsTemplateType", + "x-enum-keys": [], + "in": "path" + }, + { + "name": "locale", + "description": "Template locale", + "required": true, + "type": "string", + "x-example": "af", + "enum": [ + "af", + "ar-ae", + "ar-bh", + "ar-dz", + "ar-eg", + "ar-iq", + "ar-jo", + "ar-kw", + "ar-lb", + "ar-ly", + "ar-ma", + "ar-om", + "ar-qa", + "ar-sa", + "ar-sy", + "ar-tn", + "ar-ye", + "as", + "az", + "be", + "bg", + "bh", + "bn", + "bs", + "ca", + "cs", + "cy", + "da", + "de", + "de-at", + "de-ch", + "de-li", + "de-lu", + "el", + "en", + "en-au", + "en-bz", + "en-ca", + "en-gb", + "en-ie", + "en-jm", + "en-nz", + "en-tt", + "en-us", + "en-za", + "eo", + "es", + "es-ar", + "es-bo", + "es-cl", + "es-co", + "es-cr", + "es-do", + "es-ec", + "es-gt", + "es-hn", + "es-mx", + "es-ni", + "es-pa", + "es-pe", + "es-pr", + "es-py", + "es-sv", + "es-uy", + "es-ve", + "et", + "eu", + "fa", + "fi", + "fo", + "fr", + "fr-be", + "fr-ca", + "fr-ch", + "fr-lu", + "ga", + "gd", + "he", + "hi", + "hr", + "hu", + "id", + "is", + "it", + "it-ch", + "ja", + "ji", + "ko", + "ku", + "lt", + "lv", + "mk", + "ml", + "ms", + "mt", + "nb", + "ne", + "nl", + "nl-be", + "nn", + "no", + "pa", + "pl", + "pt", + "pt-br", + "rm", + "ro", + "ro-md", + "ru", + "ru-md", + "sb", + "sk", + "sl", + "sq", + "sr", + "sv", + "sv-fi", + "th", + "tn", + "tr", + "ts", + "ua", + "ur", + "ve", + "vi", + "xh", + "zh-cn", + "zh-hk", + "zh-sg", + "zh-tw", + "zu" + ], + "x-enum-name": "SmsTemplateLocale", + "x-enum-keys": [], + "in": "path" + } + ] + } + }, + "\/projects\/{projectId}\/webhooks": { + "get": { + "summary": "List webhooks", + "operationId": "projectsListWebhooks", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Get a list of all webhooks belonging to the project. You can use the query params to filter your results. ", + "responses": { + "200": { + "description": "Webhooks List", + "schema": { + "$ref": "#\/definitions\/webhookList" + } + } + }, + "x-appwrite": { + "method": "listWebhooks", + "group": "webhooks", + "weight": 178, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/list-webhooks.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/list-webhooks.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + } + ] + }, + "post": { + "summary": "Create webhook", + "operationId": "projectsCreateWebhook", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Create a new webhook. Use this endpoint to configure a URL that will receive events from Appwrite when specific events occur. ", + "responses": { + "201": { + "description": "Webhook", + "schema": { + "$ref": "#\/definitions\/webhook" + } + } + }, + "x-appwrite": { + "method": "createWebhook", + "group": "webhooks", + "weight": 177, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/create-webhook.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/create-webhook.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Webhook name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Enable or disable a webhook.", + "default": true, + "x-example": false + }, + "events": { + "type": "array", + "description": "Events list. Maximum of 100 events are allowed.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "url": { + "type": "string", + "description": "Webhook URL.", + "default": null, + "x-example": null + }, + "security": { + "type": "boolean", + "description": "Certificate verification, false for disabled or true for enabled.", + "default": null, + "x-example": false + }, + "httpUser": { + "type": "string", + "description": "Webhook HTTP user. Max length: 256 chars.", + "default": "", + "x-example": "<HTTP_USER>" + }, + "httpPass": { + "type": "string", + "description": "Webhook HTTP password. Max length: 256 chars.", + "default": "", + "x-example": "<HTTP_PASS>" + } + }, + "required": [ + "name", + "events", + "url", + "security" + ] + } + } + ] + } + }, + "\/projects\/{projectId}\/webhooks\/{webhookId}": { + "get": { + "summary": "Get webhook", + "operationId": "projectsGetWebhook", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Get a webhook by its unique ID. This endpoint returns details about a specific webhook configured for a project. ", + "responses": { + "200": { + "description": "Webhook", + "schema": { + "$ref": "#\/definitions\/webhook" + } + } + }, + "x-appwrite": { + "method": "getWebhook", + "group": "webhooks", + "weight": 179, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/get-webhook.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/get-webhook.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "webhookId", + "description": "Webhook unique ID.", + "required": true, + "type": "string", + "x-example": "<WEBHOOK_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update webhook", + "operationId": "projectsUpdateWebhook", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update a webhook by its unique ID. Use this endpoint to update the URL, events, or status of an existing webhook. ", + "responses": { + "200": { + "description": "Webhook", + "schema": { + "$ref": "#\/definitions\/webhook" + } + } + }, + "x-appwrite": { + "method": "updateWebhook", + "group": "webhooks", + "weight": 180, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-webhook.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-webhook.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "webhookId", + "description": "Webhook unique ID.", + "required": true, + "type": "string", + "x-example": "<WEBHOOK_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Webhook name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Enable or disable a webhook.", + "default": true, + "x-example": false + }, + "events": { + "type": "array", + "description": "Events list. Maximum of 100 events are allowed.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "url": { + "type": "string", + "description": "Webhook URL.", + "default": null, + "x-example": null + }, + "security": { + "type": "boolean", + "description": "Certificate verification, false for disabled or true for enabled.", + "default": null, + "x-example": false + }, + "httpUser": { + "type": "string", + "description": "Webhook HTTP user. Max length: 256 chars.", + "default": "", + "x-example": "<HTTP_USER>" + }, + "httpPass": { + "type": "string", + "description": "Webhook HTTP password. Max length: 256 chars.", + "default": "", + "x-example": "<HTTP_PASS>" + } + }, + "required": [ + "name", + "events", + "url", + "security" + ] + } + } + ] + }, + "delete": { + "summary": "Delete webhook", + "operationId": "projectsDeleteWebhook", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "projects" + ], + "description": "Delete a webhook by its unique ID. Once deleted, the webhook will no longer receive project events. ", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteWebhook", + "group": "webhooks", + "weight": 182, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/delete-webhook.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/delete-webhook.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "webhookId", + "description": "Webhook unique ID.", + "required": true, + "type": "string", + "x-example": "<WEBHOOK_ID>", + "in": "path" + } + ] + } + }, + "\/projects\/{projectId}\/webhooks\/{webhookId}\/signature": { + "patch": { + "summary": "Update webhook signature key", + "operationId": "projectsUpdateWebhookSignature", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "projects" + ], + "description": "Update the webhook signature key. This endpoint can be used to regenerate the signature key used to sign and validate payload deliveries for a specific webhook. ", + "responses": { + "200": { + "description": "Webhook", + "schema": { + "$ref": "#\/definitions\/webhook" + } + } + }, + "x-appwrite": { + "method": "updateWebhookSignature", + "group": "webhooks", + "weight": 181, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "projects\/update-webhook-signature.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/projects\/update-webhook-signature.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "projects.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "projectId", + "description": "Project unique ID.", + "required": true, + "type": "string", + "x-example": "<PROJECT_ID>", + "in": "path" + }, + { + "name": "webhookId", + "description": "Webhook unique ID.", + "required": true, + "type": "string", + "x-example": "<WEBHOOK_ID>", + "in": "path" + } + ] + } + }, + "\/proxy\/rules": { + "get": { + "summary": "List rules", + "operationId": "proxyListRules", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "proxy" + ], + "description": "Get a list of all the proxy rules. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Rule List", + "schema": { + "$ref": "#\/definitions\/proxyRuleList" + } + } + }, + "x-appwrite": { + "method": "listRules", + "group": null, + "weight": 294, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "proxy\/list-rules.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/proxy\/list-rules.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rules.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/databases#querying-documents). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: domain, type, trigger, deploymentResourceType, deploymentResourceId, deploymentId, deploymentVcsProviderBranch", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + } + }, + "\/proxy\/rules\/api": { + "post": { + "summary": "Create API rule", + "operationId": "proxyCreateAPIRule", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "proxy" + ], + "description": "Create a new proxy rule for serving Appwrite's API on custom domain.", + "responses": { + "201": { + "description": "Rule", + "schema": { + "$ref": "#\/definitions\/proxyRule" + } + } + }, + "x-appwrite": { + "method": "createAPIRule", + "group": null, + "weight": 435, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "proxy\/create-a-p-i-rule.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new proxy rule for serving Appwrite's API on custom domain.", + "rate-limit": 10, + "rate-time": 60, + "rate-key": "userId:{userId}, url:{url}", + "scope": "rules.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "domain": { + "type": "string", + "description": "Domain name.", + "default": null, + "x-example": null + } + }, + "required": [ + "domain" + ] + } + } + ] + } + }, + "\/proxy\/rules\/function": { + "post": { + "summary": "Create function rule", + "operationId": "proxyCreateFunctionRule", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "proxy" + ], + "description": "Create a new proxy rule for executing Appwrite Function on custom domain.", + "responses": { + "201": { + "description": "Rule", + "schema": { + "$ref": "#\/definitions\/proxyRule" + } + } + }, + "x-appwrite": { + "method": "createFunctionRule", + "group": null, + "weight": 437, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "proxy\/create-function-rule.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new proxy rule for executing Appwrite Function on custom domain.", + "rate-limit": 10, + "rate-time": 60, + "rate-key": "userId:{userId}, url:{url}", + "scope": "rules.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "domain": { + "type": "string", + "description": "Domain name.", + "default": null, + "x-example": null + }, + "functionId": { + "type": "string", + "description": "ID of function to be executed.", + "default": null, + "x-example": "<FUNCTION_ID>" + }, + "branch": { + "type": "string", + "description": "Name of VCS branch to deploy changes automatically", + "default": "", + "x-example": "<BRANCH>" + } + }, + "required": [ + "domain", + "functionId" + ] + } + } + ] + } + }, + "\/proxy\/rules\/redirect": { + "post": { + "summary": "Create Redirect rule", + "operationId": "proxyCreateRedirectRule", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "proxy" + ], + "description": "Create a new proxy rule for to redirect from custom domain to another domain.", + "responses": { + "201": { + "description": "Rule", + "schema": { + "$ref": "#\/definitions\/proxyRule" + } + } + }, + "x-appwrite": { + "method": "createRedirectRule", + "group": null, + "weight": 438, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "proxy\/create-redirect-rule.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new proxy rule for to redirect from custom domain to another domain.", + "rate-limit": 10, + "rate-time": 60, + "rate-key": "userId:{userId}, url:{url}", + "scope": "rules.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "domain": { + "type": "string", + "description": "Domain name.", + "default": null, + "x-example": null + }, + "url": { + "type": "string", + "description": "Target URL of redirection", + "default": null, + "x-example": "https:\/\/example.com" + }, + "statusCode": { + "type": "string", + "description": "Status code of redirection", + "default": null, + "x-example": "301", + "enum": [ + "301", + "302", + "307", + "308" + ], + "x-enum-name": null, + "x-enum-keys": [ + "Moved Permanently 301", + "Found 302", + "Temporary Redirect 307", + "Permanent Redirect 308" + ] + }, + "resourceId": { + "type": "string", + "description": "ID of parent resource.", + "default": null, + "x-example": "<RESOURCE_ID>" + }, + "resourceType": { + "type": "string", + "description": "Type of parent resource.", + "default": null, + "x-example": "site", + "enum": [ + "site", + "function" + ], + "x-enum-name": "ProxyResourceType", + "x-enum-keys": [ + "Site", + "Function" + ] + } + }, + "required": [ + "domain", + "url", + "statusCode", + "resourceId", + "resourceType" + ] + } + } + ] + } + }, + "\/proxy\/rules\/site": { + "post": { + "summary": "Create site rule", + "operationId": "proxyCreateSiteRule", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "proxy" + ], + "description": "Create a new proxy rule for serving Appwrite Site on custom domain.", + "responses": { + "201": { + "description": "Rule", + "schema": { + "$ref": "#\/definitions\/proxyRule" + } + } + }, + "x-appwrite": { + "method": "createSiteRule", + "group": null, + "weight": 436, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "proxy\/create-site-rule.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new proxy rule for serving Appwrite Site on custom domain.", + "rate-limit": 10, + "rate-time": 60, + "rate-key": "userId:{userId}, url:{url}", + "scope": "rules.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "domain": { + "type": "string", + "description": "Domain name.", + "default": null, + "x-example": null + }, + "siteId": { + "type": "string", + "description": "ID of site to be executed.", + "default": null, + "x-example": "<SITE_ID>" + }, + "branch": { + "type": "string", + "description": "Name of VCS branch to deploy changes automatically", + "default": "", + "x-example": "<BRANCH>" + } + }, + "required": [ + "domain", + "siteId" + ] + } + } + ] + } + }, + "\/proxy\/rules\/{ruleId}": { + "get": { + "summary": "Get rule", + "operationId": "proxyGetRule", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "proxy" + ], + "description": "Get a proxy rule by its unique ID.", + "responses": { + "200": { + "description": "Rule", + "schema": { + "$ref": "#\/definitions\/proxyRule" + } + } + }, + "x-appwrite": { + "method": "getRule", + "group": null, + "weight": 295, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "proxy\/get-rule.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/proxy\/get-rule.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rules.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "ruleId", + "description": "Rule ID.", + "required": true, + "type": "string", + "x-example": "<RULE_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete rule", + "operationId": "proxyDeleteRule", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "proxy" + ], + "description": "Delete a proxy rule by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteRule", + "group": null, + "weight": 296, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "proxy\/delete-rule.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/proxy\/delete-rule.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rules.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "ruleId", + "description": "Rule ID.", + "required": true, + "type": "string", + "x-example": "<RULE_ID>", + "in": "path" + } + ] + } + }, + "\/proxy\/rules\/{ruleId}\/verification": { + "patch": { + "summary": "Update rule verification status", + "operationId": "proxyUpdateRuleVerification", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "proxy" + ], + "description": "Retry getting verification process of a proxy rule. This endpoint triggers domain verification by checking DNS records (CNAME) against the configured target domain. If verification is successful, a TLS certificate will be automatically provisioned for the domain.", + "responses": { + "200": { + "description": "Rule", + "schema": { + "$ref": "#\/definitions\/proxyRule" + } + } + }, + "x-appwrite": { + "method": "updateRuleVerification", + "group": null, + "weight": 297, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "proxy\/update-rule-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/proxy\/update-rule-verification.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "rules.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "ruleId", + "description": "Rule ID.", + "required": true, + "type": "string", + "x-example": "<RULE_ID>", + "in": "path" + } + ] + } + }, + "\/sites": { + "get": { + "summary": "List sites", + "operationId": "sitesList", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get a list of all the project's sites. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Sites List", + "schema": { + "$ref": "#\/definitions\/siteList" + } + } + }, + "x-appwrite": { + "method": "list", + "group": "sites", + "weight": 407, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the project's sites. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, enabled, framework, deploymentId, buildCommand, installCommand, outputDirectory, installationId", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create site", + "operationId": "sitesCreate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Create a new site.", + "responses": { + "201": { + "description": "Site", + "schema": { + "$ref": "#\/definitions\/site" + } + } + }, + "x-appwrite": { + "method": "create", + "group": "sites", + "weight": 405, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new site.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "siteId": { + "type": "string", + "description": "Site ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<SITE_ID>" + }, + "name": { + "type": "string", + "description": "Site name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "framework": { + "type": "string", + "description": "Sites framework.", + "default": null, + "x-example": "analog", + "enum": [ + "analog", + "angular", + "nextjs", + "react", + "nuxt", + "vue", + "sveltekit", + "astro", + "remix", + "lynx", + "flutter", + "react-native", + "vite", + "other" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "enabled": { + "type": "boolean", + "description": "Is site enabled? When set to 'disabled', users cannot access the site but Server SDKs with and API key can still access the site. No data is lost when this is toggled.", + "default": true, + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.", + "default": true, + "x-example": false + }, + "timeout": { + "type": "integer", + "description": "Maximum request time in seconds.", + "default": 30, + "x-example": 1 + }, + "installCommand": { + "type": "string", + "description": "Install Command.", + "default": "", + "x-example": "<INSTALL_COMMAND>" + }, + "buildCommand": { + "type": "string", + "description": "Build Command.", + "default": "", + "x-example": "<BUILD_COMMAND>" + }, + "outputDirectory": { + "type": "string", + "description": "Output Directory for site.", + "default": "", + "x-example": "<OUTPUT_DIRECTORY>" + }, + "buildRuntime": { + "type": "string", + "description": "Runtime to use during build step.", + "default": null, + "x-example": "node-14.5", + "enum": [ + "node-14.5", + "node-16.0", + "node-18.0", + "node-19.0", + "node-20.0", + "node-21.0", + "node-22", + "php-8.0", + "php-8.1", + "php-8.2", + "php-8.3", + "ruby-3.0", + "ruby-3.1", + "ruby-3.2", + "ruby-3.3", + "python-3.8", + "python-3.9", + "python-3.10", + "python-3.11", + "python-3.12", + "python-ml-3.11", + "python-ml-3.12", + "deno-1.21", + "deno-1.24", + "deno-1.35", + "deno-1.40", + "deno-1.46", + "deno-2.0", + "dart-2.15", + "dart-2.16", + "dart-2.17", + "dart-2.18", + "dart-2.19", + "dart-3.0", + "dart-3.1", + "dart-3.3", + "dart-3.5", + "dart-3.8", + "dotnet-6.0", + "dotnet-7.0", + "dotnet-8.0", + "java-8.0", + "java-11.0", + "java-17.0", + "java-18.0", + "java-21.0", + "java-22", + "swift-5.5", + "swift-5.8", + "swift-5.9", + "swift-5.10", + "kotlin-1.6", + "kotlin-1.8", + "kotlin-1.9", + "kotlin-2.0", + "cpp-17", + "cpp-20", + "bun-1.0", + "bun-1.1", + "go-1.23", + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29", + "flutter-3.32" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "adapter": { + "type": "string", + "description": "Framework adapter defining rendering strategy. Allowed values are: static, ssr", + "default": "", + "x-example": "static", + "enum": [ + "static", + "ssr" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "installationId": { + "type": "string", + "description": "Appwrite Installation ID for VCS (Version Control System) deployment.", + "default": "", + "x-example": "<INSTALLATION_ID>" + }, + "fallbackFile": { + "type": "string", + "description": "Fallback file for single page application sites.", + "default": "", + "x-example": "<FALLBACK_FILE>" + }, + "providerRepositoryId": { + "type": "string", + "description": "Repository ID of the repo linked to the site.", + "default": "", + "x-example": "<PROVIDER_REPOSITORY_ID>" + }, + "providerBranch": { + "type": "string", + "description": "Production branch for the repo linked to the site.", + "default": "", + "x-example": "<PROVIDER_BRANCH>" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is the VCS (Version Control System) connection in silent mode for the repo linked to the site? In silent mode, comments will not be made on commits and pull requests.", + "default": false, + "x-example": false + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to site code in the linked repo.", + "default": "", + "x-example": "<PROVIDER_ROOT_DIRECTORY>" + }, + "specification": { + "type": "string", + "description": "Framework specification for the site and builds.", + "default": "s-1vcpu-512mb", + "x-example": null + } + }, + "required": [ + "siteId", + "name", + "framework", + "buildRuntime" + ] + } + } + ] + } + }, + "\/sites\/frameworks": { + "get": { + "summary": "List frameworks", + "operationId": "sitesListFrameworks", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get a list of all frameworks that are currently available on the server instance.", + "responses": { + "200": { + "description": "Frameworks List", + "schema": { + "$ref": "#\/definitions\/frameworkList" + } + } + }, + "x-appwrite": { + "method": "listFrameworks", + "group": "frameworks", + "weight": 410, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-frameworks.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all frameworks that are currently available on the server instance.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/sites\/specifications": { + "get": { + "summary": "List specifications", + "operationId": "sitesListSpecifications", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "List allowed site specifications for this instance.", + "responses": { + "200": { + "description": "Specifications List", + "schema": { + "$ref": "#\/definitions\/specificationList" + } + } + }, + "x-appwrite": { + "method": "listSpecifications", + "group": "frameworks", + "weight": 433, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-specifications.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList allowed site specifications for this instance.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/sites\/templates": { + "get": { + "summary": "List templates", + "operationId": "sitesListTemplates", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "List available site templates. You can use template details in [createSite](\/docs\/references\/cloud\/server-nodejs\/sites#create) method.", + "responses": { + "200": { + "description": "Site Templates List", + "schema": { + "$ref": "#\/definitions\/templateSiteList" + } + } + }, + "x-appwrite": { + "method": "listTemplates", + "group": "templates", + "weight": 429, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-templates.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList available site templates. You can use template details in [createSite](\/docs\/references\/cloud\/server-nodejs\/sites#create) method.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "frameworks", + "description": "List of frameworks allowed for filtering site templates. Maximum of 100 frameworks are allowed.", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "useCases", + "description": "List of use cases allowed for filtering site templates. Maximum of 100 use cases are allowed.", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "limit", + "description": "Limit the number of templates returned in the response. Default limit is 25, and maximum limit is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 1, + "default": 25, + "in": "query" + }, + { + "name": "offset", + "description": "Offset the list of returned templates. Maximum offset is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0, + "in": "query" + } + ] + } + }, + "\/sites\/templates\/{templateId}": { + "get": { + "summary": "Get site template", + "operationId": "sitesGetTemplate", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get a site template using ID. You can use template details in [createSite](\/docs\/references\/cloud\/server-nodejs\/sites#create) method.", + "responses": { + "200": { + "description": "Template Site", + "schema": { + "$ref": "#\/definitions\/templateSite" + } + } + }, + "x-appwrite": { + "method": "getTemplate", + "group": "templates", + "weight": 430, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get-template.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a site template using ID. You can use template details in [createSite](\/docs\/references\/cloud\/server-nodejs\/sites#create) method.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "templateId", + "description": "Template ID.", + "required": true, + "type": "string", + "x-example": "<TEMPLATE_ID>", + "in": "path" + } + ] + } + }, + "\/sites\/usage": { + "get": { + "summary": "Get sites usage", + "operationId": "sitesListUsage", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get usage metrics and statistics for all sites in the project. View statistics including total deployments, builds, logs, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", + "responses": { + "200": { + "description": "UsageSites", + "schema": { + "$ref": "#\/definitions\/usageSites" + } + } + }, + "x-appwrite": { + "method": "listUsage", + "group": null, + "weight": 431, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet usage metrics and statistics for all sites in the project. View statistics including total deployments, builds, logs, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "range", + "description": "Date range.", + "required": false, + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "SiteUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d", + "in": "query" + } + ] + } + }, + "\/sites\/{siteId}": { + "get": { + "summary": "Get site", + "operationId": "sitesGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get a site by its unique ID.", + "responses": { + "200": { + "description": "Site", + "schema": { + "$ref": "#\/definitions\/site" + } + } + }, + "x-appwrite": { + "method": "get", + "group": "sites", + "weight": 406, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a site by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update site", + "operationId": "sitesUpdate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Update site by its unique ID.", + "responses": { + "200": { + "description": "Site", + "schema": { + "$ref": "#\/definitions\/site" + } + } + }, + "x-appwrite": { + "method": "update", + "group": "sites", + "weight": 408, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/update.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate site by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Site name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "framework": { + "type": "string", + "description": "Sites framework.", + "default": null, + "x-example": "analog", + "enum": [ + "analog", + "angular", + "nextjs", + "react", + "nuxt", + "vue", + "sveltekit", + "astro", + "remix", + "lynx", + "flutter", + "react-native", + "vite", + "other" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "enabled": { + "type": "boolean", + "description": "Is site enabled? When set to 'disabled', users cannot access the site but Server SDKs with and API key can still access the site. No data is lost when this is toggled.", + "default": true, + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.", + "default": true, + "x-example": false + }, + "timeout": { + "type": "integer", + "description": "Maximum request time in seconds.", + "default": 30, + "x-example": 1 + }, + "installCommand": { + "type": "string", + "description": "Install Command.", + "default": "", + "x-example": "<INSTALL_COMMAND>" + }, + "buildCommand": { + "type": "string", + "description": "Build Command.", + "default": "", + "x-example": "<BUILD_COMMAND>" + }, + "outputDirectory": { + "type": "string", + "description": "Output Directory for site.", + "default": "", + "x-example": "<OUTPUT_DIRECTORY>" + }, + "buildRuntime": { + "type": "string", + "description": "Runtime to use during build step.", + "default": "", + "x-example": "node-14.5", + "enum": [ + "node-14.5", + "node-16.0", + "node-18.0", + "node-19.0", + "node-20.0", + "node-21.0", + "node-22", + "php-8.0", + "php-8.1", + "php-8.2", + "php-8.3", + "ruby-3.0", + "ruby-3.1", + "ruby-3.2", + "ruby-3.3", + "python-3.8", + "python-3.9", + "python-3.10", + "python-3.11", + "python-3.12", + "python-ml-3.11", + "python-ml-3.12", + "deno-1.21", + "deno-1.24", + "deno-1.35", + "deno-1.40", + "deno-1.46", + "deno-2.0", + "dart-2.15", + "dart-2.16", + "dart-2.17", + "dart-2.18", + "dart-2.19", + "dart-3.0", + "dart-3.1", + "dart-3.3", + "dart-3.5", + "dart-3.8", + "dotnet-6.0", + "dotnet-7.0", + "dotnet-8.0", + "java-8.0", + "java-11.0", + "java-17.0", + "java-18.0", + "java-21.0", + "java-22", + "swift-5.5", + "swift-5.8", + "swift-5.9", + "swift-5.10", + "kotlin-1.6", + "kotlin-1.8", + "kotlin-1.9", + "kotlin-2.0", + "cpp-17", + "cpp-20", + "bun-1.0", + "bun-1.1", + "go-1.23", + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29", + "flutter-3.32" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "adapter": { + "type": "string", + "description": "Framework adapter defining rendering strategy. Allowed values are: static, ssr", + "default": "", + "x-example": "static", + "enum": [ + "static", + "ssr" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "fallbackFile": { + "type": "string", + "description": "Fallback file for single page application sites.", + "default": "", + "x-example": "<FALLBACK_FILE>" + }, + "installationId": { + "type": "string", + "description": "Appwrite Installation ID for VCS (Version Control System) deployment.", + "default": "", + "x-example": "<INSTALLATION_ID>" + }, + "providerRepositoryId": { + "type": "string", + "description": "Repository ID of the repo linked to the site.", + "default": "", + "x-example": "<PROVIDER_REPOSITORY_ID>" + }, + "providerBranch": { + "type": "string", + "description": "Production branch for the repo linked to the site.", + "default": "", + "x-example": "<PROVIDER_BRANCH>" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is the VCS (Version Control System) connection in silent mode for the repo linked to the site? In silent mode, comments will not be made on commits and pull requests.", + "default": false, + "x-example": false + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to site code in the linked repo.", + "default": "", + "x-example": "<PROVIDER_ROOT_DIRECTORY>" + }, + "specification": { + "type": "string", + "description": "Framework specification for the site and builds.", + "default": "s-1vcpu-512mb", + "x-example": null + } + }, + "required": [ + "name", + "framework" + ] + } + } + ] + }, + "delete": { + "summary": "Delete site", + "operationId": "sitesDelete", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "sites" + ], + "description": "Delete a site by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "sites", + "weight": 409, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a site by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + } + ] + } + }, + "\/sites\/{siteId}\/deployment": { + "patch": { + "summary": "Update site's deployment", + "operationId": "sitesUpdateSiteDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Update the site active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your site.", + "responses": { + "200": { + "description": "Site", + "schema": { + "$ref": "#\/definitions\/site" + } + } + }, + "x-appwrite": { + "method": "updateSiteDeployment", + "group": "sites", + "weight": 416, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/update-site-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate the site active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your site.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "deploymentId": { + "type": "string", + "description": "Deployment ID.", + "default": null, + "x-example": "<DEPLOYMENT_ID>" + } + }, + "required": [ + "deploymentId" + ] + } + } + ] + } + }, + "\/sites\/{siteId}\/deployments": { + "get": { + "summary": "List deployments", + "operationId": "sitesListDeployments", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get a list of all the site's code deployments. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Deployments List", + "schema": { + "$ref": "#\/definitions\/deploymentList" + } + } + }, + "x-appwrite": { + "method": "listDeployments", + "group": "deployments", + "weight": 415, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-deployments.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the site's code deployments. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create deployment", + "operationId": "sitesCreateDeployment", + "consumes": [ + "multipart\/form-data" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Create a new site code deployment. Use this endpoint to upload a new version of your site code. To activate your newly uploaded code, you'll need to update the function's deployment to use your new deployment ID.", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createDeployment", + "group": "deployments", + "weight": 411, + "cookies": false, + "type": "upload", + "deprecated": false, + "demo": "sites\/create-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new site code deployment. Use this endpoint to upload a new version of your site code. To activate your newly uploaded code, you'll need to update the function's deployment to use your new deployment ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": true, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "installCommand", + "description": "Install Commands.", + "required": false, + "type": "string", + "x-example": "<INSTALL_COMMAND>", + "in": "formData" + }, + { + "name": "buildCommand", + "description": "Build Commands.", + "required": false, + "type": "string", + "x-example": "<BUILD_COMMAND>", + "in": "formData" + }, + { + "name": "outputDirectory", + "description": "Output Directory.", + "required": false, + "type": "string", + "x-example": "<OUTPUT_DIRECTORY>", + "in": "formData" + }, + { + "name": "code", + "description": "Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.", + "required": true, + "type": "file", + "in": "formData" + }, + { + "name": "activate", + "description": "Automatically activate the deployment when it is finished building.", + "required": true, + "type": "boolean", + "x-example": false, + "in": "formData" + } + ] + } + }, + "\/sites\/{siteId}\/deployments\/duplicate": { + "post": { + "summary": "Create duplicate deployment", + "operationId": "sitesCreateDuplicateDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Create a new build for an existing site deployment. This endpoint allows you to rebuild a deployment with the updated site configuration, including its commands and output directory if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createDuplicateDeployment", + "group": "deployments", + "weight": 419, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create-duplicate-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new build for an existing site deployment. This endpoint allows you to rebuild a deployment with the updated site configuration, including its commands and output directory if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "deploymentId": { + "type": "string", + "description": "Deployment ID.", + "default": null, + "x-example": "<DEPLOYMENT_ID>" + } + }, + "required": [ + "deploymentId" + ] + } + } + ] + } + }, + "\/sites\/{siteId}\/deployments\/template": { + "post": { + "summary": "Create template deployment", + "operationId": "sitesCreateTemplateDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Create a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/sites#listTemplates) to find the template details.", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createTemplateDeployment", + "group": "deployments", + "weight": 412, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create-template-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/sites#listTemplates) to find the template details.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "repository": { + "type": "string", + "description": "Repository name of the template.", + "default": null, + "x-example": "<REPOSITORY>" + }, + "owner": { + "type": "string", + "description": "The name of the owner of the template.", + "default": null, + "x-example": "<OWNER>" + }, + "rootDirectory": { + "type": "string", + "description": "Path to site code in the template repo.", + "default": null, + "x-example": "<ROOT_DIRECTORY>" + }, + "version": { + "type": "string", + "description": "Version (tag) for the repo linked to the site template.", + "default": null, + "x-example": "<VERSION>" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "default": false, + "x-example": false + } + }, + "required": [ + "repository", + "owner", + "rootDirectory", + "version" + ] + } + } + ] + } + }, + "\/sites\/{siteId}\/deployments\/vcs": { + "post": { + "summary": "Create VCS deployment", + "operationId": "sitesCreateVcsDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Create a deployment when a site is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createVcsDeployment", + "group": "deployments", + "weight": 413, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create-vcs-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment when a site is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Type of reference passed. Allowed values are: branch, commit", + "default": null, + "x-example": "branch", + "enum": [ + "branch", + "commit", + "tag" + ], + "x-enum-name": "VCSDeploymentType", + "x-enum-keys": [] + }, + "reference": { + "type": "string", + "description": "VCS reference to create deployment from. Depending on type this can be: branch name, commit hash", + "default": null, + "x-example": "<REFERENCE>" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "default": false, + "x-example": false + } + }, + "required": [ + "type", + "reference" + ] + } + } + ] + } + }, + "\/sites\/{siteId}\/deployments\/{deploymentId}": { + "get": { + "summary": "Get deployment", + "operationId": "sitesGetDeployment", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get a site deployment by its unique ID.", + "responses": { + "200": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "getDeployment", + "group": "deployments", + "weight": 414, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a site deployment by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "type": "string", + "x-example": "<DEPLOYMENT_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete deployment", + "operationId": "sitesDeleteDeployment", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "sites" + ], + "description": "Delete a site deployment by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDeployment", + "group": "deployments", + "weight": 417, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/delete-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a site deployment by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "type": "string", + "x-example": "<DEPLOYMENT_ID>", + "in": "path" + } + ] + } + }, + "\/sites\/{siteId}\/deployments\/{deploymentId}\/download": { + "get": { + "summary": "Get deployment download", + "operationId": "sitesGetDeploymentDownload", + "consumes": [], + "produces": [ + "*\/*" + ], + "tags": [ + "sites" + ], + "description": "Get a site deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "responses": { + "200": { + "description": "File", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getDeploymentDownload", + "group": "deployments", + "weight": 418, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "sites\/get-deployment-download.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a site deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "type": "string", + "x-example": "<DEPLOYMENT_ID>", + "in": "path" + }, + { + "name": "type", + "description": "Deployment file to download. Can be: \"source\", \"output\".", + "required": false, + "type": "string", + "x-example": "source", + "enum": [ + "source", + "output" + ], + "x-enum-name": "DeploymentDownloadType", + "x-enum-keys": [], + "default": "source", + "in": "query" + } + ] + } + }, + "\/sites\/{siteId}\/deployments\/{deploymentId}\/status": { + "patch": { + "summary": "Update deployment status", + "operationId": "sitesUpdateDeploymentStatus", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Cancel an ongoing site deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", + "responses": { + "200": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "updateDeploymentStatus", + "group": "deployments", + "weight": 420, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/update-deployment-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCancel an ongoing site deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "type": "string", + "x-example": "<DEPLOYMENT_ID>", + "in": "path" + } + ] + } + }, + "\/sites\/{siteId}\/logs": { + "get": { + "summary": "List logs", + "operationId": "sitesListLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get a list of all site logs. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Executions List", + "schema": { + "$ref": "#\/definitions\/executionList" + } + } + }, + "x-appwrite": { + "method": "listLogs", + "group": "logs", + "weight": 422, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all site logs. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "log.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: trigger, status, responseStatusCode, duration, requestMethod, requestPath, deploymentId", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/sites\/{siteId}\/logs\/{logId}": { + "get": { + "summary": "Get log", + "operationId": "sitesGetLog", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get a site request log by its unique ID.", + "responses": { + "200": { + "description": "Execution", + "schema": { + "$ref": "#\/definitions\/execution" + } + } + }, + "x-appwrite": { + "method": "getLog", + "group": "logs", + "weight": 421, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get-log.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a site request log by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "log.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "logId", + "description": "Log ID.", + "required": true, + "type": "string", + "x-example": "<LOG_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete log", + "operationId": "sitesDeleteLog", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Delete a site log by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteLog", + "group": "logs", + "weight": 423, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/delete-log.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a site log by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "log.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "logId", + "description": "Log ID.", + "required": true, + "type": "string", + "x-example": "<LOG_ID>", + "in": "path" + } + ] + } + }, + "\/sites\/{siteId}\/usage": { + "get": { + "summary": "Get site usage", + "operationId": "sitesGetUsage", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get usage metrics and statistics for a for a specific site. View statistics including total deployments, builds, executions, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", + "responses": { + "200": { + "description": "UsageSite", + "schema": { + "$ref": "#\/definitions\/usageSite" + } + } + }, + "x-appwrite": { + "method": "getUsage", + "group": null, + "weight": 432, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet usage metrics and statistics for a for a specific site. View statistics including total deployments, builds, executions, storage usage, and compute time. The response includes both current totals and historical data for each metric. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, defaults to 30 days.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "range", + "description": "Date range.", + "required": false, + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "SiteUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d", + "in": "query" + } + ] + } + }, + "\/sites\/{siteId}\/variables": { + "get": { + "summary": "List variables", + "operationId": "sitesListVariables", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get a list of all variables of a specific site.", + "responses": { + "200": { + "description": "Variables List", + "schema": { + "$ref": "#\/definitions\/variableList" + } + } + }, + "x-appwrite": { + "method": "listVariables", + "group": "variables", + "weight": 426, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-variables.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all variables of a specific site.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + } + ] + }, + "post": { + "summary": "Create variable", + "operationId": "sitesCreateVariable", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Create a new site variable. These variables can be accessed during build and runtime (server-side rendering) as environment variables.", + "responses": { + "201": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "createVariable", + "group": "variables", + "weight": 424, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new site variable. These variables can be accessed during build and runtime (server-side rendering) as environment variables.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "default": null, + "x-example": "<KEY>" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "default": null, + "x-example": "<VALUE>" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only sites can read them during build and runtime.", + "default": true, + "x-example": false + } + }, + "required": [ + "key", + "value" + ] + } + } + ] + } + }, + "\/sites\/{siteId}\/variables\/{variableId}": { + "get": { + "summary": "Get variable", + "operationId": "sitesGetVariable", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get a variable by its unique ID.", + "responses": { + "200": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "getVariable", + "group": "variables", + "weight": 425, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "type": "string", + "x-example": "<VARIABLE_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update variable", + "operationId": "sitesUpdateVariable", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Update variable by its unique ID.", + "responses": { + "200": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "updateVariable", + "group": "variables", + "weight": 427, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/update-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "type": "string", + "x-example": "<VARIABLE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "default": null, + "x-example": "<KEY>" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "default": null, + "x-example": "<VALUE>" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only sites can read them during build and runtime.", + "default": null, + "x-example": false + } + }, + "required": [ + "key" + ] + } + } + ] + }, + "delete": { + "summary": "Delete variable", + "operationId": "sitesDeleteVariable", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "sites" + ], + "description": "Delete a variable by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteVariable", + "group": "variables", + "weight": 428, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/delete-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "type": "string", + "x-example": "<VARIABLE_ID>", + "in": "path" + } + ] + } + }, + "\/storage\/buckets": { + "get": { + "summary": "List buckets", + "operationId": "storageListBuckets", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Get a list of all the storage buckets. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Buckets List", + "schema": { + "$ref": "#\/definitions\/bucketList" + } + } + }, + "x-appwrite": { + "method": "listBuckets", + "group": "buckets", + "weight": 209, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/list-buckets.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/list-buckets.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create bucket", + "operationId": "storageCreateBucket", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Create a new storage bucket.", + "responses": { + "201": { + "description": "Bucket", + "schema": { + "$ref": "#\/definitions\/bucket" + } + } + }, + "x-appwrite": { + "method": "createBucket", + "group": "buckets", + "weight": 208, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/create-bucket.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/create-bucket.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "bucketId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<BUCKET_ID>" + }, + "name": { + "type": "string", + "description": "Bucket name", + "default": null, + "x-example": "<NAME>" + }, + "permissions": { + "type": "array", + "description": "An array of permission strings. By default, no user is granted with any permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "fileSecurity": { + "type": "boolean", + "description": "Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": false, + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Is bucket enabled? When set to 'disabled', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.", + "default": true, + "x-example": false + }, + "maximumFileSize": { + "type": "integer", + "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", + "default": {}, + "x-example": 1 + }, + "allowedFileExtensions": { + "type": "array", + "description": "Allowed file extensions. Maximum of 100 extensions are allowed, each 64 characters long.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "compression": { + "type": "string", + "description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", + "default": "none", + "x-example": "none", + "enum": [ + "none", + "gzip", + "zstd" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "encryption": { + "type": "boolean", + "description": "Is encryption enabled? For file size above 20MB encryption is skipped even if it's enabled", + "default": true, + "x-example": false + }, + "antivirus": { + "type": "boolean", + "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", + "default": true, + "x-example": false + } + }, + "required": [ + "bucketId", + "name" + ] + } + } + ] + } + }, + "\/storage\/buckets\/{bucketId}": { + "get": { + "summary": "Get bucket", + "operationId": "storageGetBucket", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Get a storage bucket by its unique ID. This endpoint response returns a JSON object with the storage bucket metadata.", + "responses": { + "200": { + "description": "Bucket", + "schema": { + "$ref": "#\/definitions\/bucket" + } + } + }, + "x-appwrite": { + "method": "getBucket", + "group": "buckets", + "weight": 210, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/get-bucket.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-bucket.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Bucket unique ID.", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update bucket", + "operationId": "storageUpdateBucket", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Update a storage bucket by its unique ID.", + "responses": { + "200": { + "description": "Bucket", + "schema": { + "$ref": "#\/definitions\/bucket" + } + } + }, + "x-appwrite": { + "method": "updateBucket", + "group": "buckets", + "weight": 211, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/update-bucket.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/update-bucket.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Bucket unique ID.", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Bucket name", + "default": null, + "x-example": "<NAME>" + }, + "permissions": { + "type": "array", + "description": "An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "fileSecurity": { + "type": "boolean", + "description": "Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": false, + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Is bucket enabled? When set to 'disabled', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.", + "default": true, + "x-example": false + }, + "maximumFileSize": { + "type": "integer", + "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", + "default": {}, + "x-example": 1 + }, + "allowedFileExtensions": { + "type": "array", + "description": "Allowed file extensions. Maximum of 100 extensions are allowed, each 64 characters long.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "compression": { + "type": "string", + "description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", + "default": "none", + "x-example": "none", + "enum": [ + "none", + "gzip", + "zstd" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "encryption": { + "type": "boolean", + "description": "Is encryption enabled? For file size above 20MB encryption is skipped even if it's enabled", + "default": true, + "x-example": false + }, + "antivirus": { + "type": "boolean", + "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", + "default": true, + "x-example": false + } + }, + "required": [ + "name" + ] + } + } + ] + }, + "delete": { + "summary": "Delete bucket", + "operationId": "storageDeleteBucket", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "storage" + ], + "description": "Delete a storage bucket by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteBucket", + "group": "buckets", + "weight": 212, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/delete-bucket.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/delete-bucket.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Bucket unique ID.", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files": { + "get": { + "summary": "List files", + "operationId": "storageListFiles", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Get a list of all the user files. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Files List", + "schema": { + "$ref": "#\/definitions\/fileList" + } + } + }, + "x-appwrite": { + "method": "listFiles", + "group": "files", + "weight": 214, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/list-files.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/list-files.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, signature, mimeType, sizeOriginal, chunksTotal, chunksUploaded", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create file", + "operationId": "storageCreateFile", + "consumes": [ + "multipart\/form-data" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Create a new file. Before using this route, you should create a new bucket resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/storage#storageCreateBucket) API or directly from your Appwrite console.\n\nLarger files should be uploaded using multiple requests with the [content-range](https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Headers\/Content-Range) header to send a partial request with a maximum supported chunk of `5MB`. The `content-range` header values should always be in bytes.\n\nWhen the first request is sent, the server will return the **File** object, and the subsequent part request must include the file's **id** in `x-appwrite-id` header to allow the server to know that the partial upload is for the existing file and not for a new one.\n\nIf you're creating a new file using one of the Appwrite SDKs, all the chunking logic will be managed by the SDK internally.\n", + "responses": { + "201": { + "description": "File", + "schema": { + "$ref": "#\/definitions\/file" + } + } + }, + "x-appwrite": { + "method": "createFile", + "group": "files", + "weight": 213, + "cookies": false, + "type": "upload", + "deprecated": false, + "demo": "storage\/create-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/create-file.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId},chunkId:{chunkId}", + "scope": "files.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "required": true, + "x-upload-id": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "formData" + }, + { + "name": "file", + "description": "Binary file. Appwrite SDKs provide helpers to handle file input. [Learn about file input](https:\/\/appwrite.io\/docs\/products\/storage\/upload-download#input-file).", + "required": true, + "type": "file", + "in": "formData" + }, + { + "name": "permissions", + "description": "An array of permission strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "x-example": "[\"read(\"any\")\"]", + "in": "formData" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}": { + "get": { + "summary": "Get file", + "operationId": "storageGetFile", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Get a file by its unique ID. This endpoint response returns a JSON object with the file metadata.", + "responses": { + "200": { + "description": "File", + "schema": { + "$ref": "#\/definitions\/file" + } + } + }, + "x-appwrite": { + "method": "getFile", + "group": "files", + "weight": 215, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/get-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update file", + "operationId": "storageUpdateFile", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Update a file by its unique ID. Only users with write permissions have access to update this resource.", + "responses": { + "200": { + "description": "File", + "schema": { + "$ref": "#\/definitions\/file" + } + } + }, + "x-appwrite": { + "method": "updateFile", + "group": "files", + "weight": 220, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/update-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/update-file.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "files.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the file", + "default": null, + "x-example": "<NAME>" + }, + "permissions": { + "type": "array", + "description": "An array of permission string. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + } + } + } + ] + }, + "delete": { + "summary": "Delete file", + "operationId": "storageDeleteFile", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "storage" + ], + "description": "Delete a file by its unique ID. Only users with write permissions have access to delete this resource.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteFile", + "group": "files", + "weight": 221, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/delete-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/delete-file.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "files.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/download": { + "get": { + "summary": "Get file for download", + "operationId": "storageGetFileDownload", + "consumes": [], + "produces": [ + "*\/*" + ], + "tags": [ + "storage" + ], + "description": "Get a file content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "responses": { + "200": { + "description": "File", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getFileDownload", + "group": "files", + "weight": 217, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "storage\/get-file-download.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file-download.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + }, + { + "name": "token", + "description": "File token for accessing this file.", + "required": false, + "type": "string", + "x-example": "<TOKEN>", + "default": "", + "in": "query" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/preview": { + "get": { + "summary": "Get file preview", + "operationId": "storageGetFilePreview", + "consumes": [], + "produces": [ + "image\/*" + ], + "tags": [ + "storage" + ], + "description": "Get a file preview image. Currently, this method supports preview for image files (jpg, png, and gif), other supported formats, like pdf, docs, slides, and spreadsheets, will return the file icon image. You can also pass query string arguments for cutting and resizing your preview image. Preview is supported only for image files smaller than 10MB.", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getFilePreview", + "group": "files", + "weight": 216, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "storage\/get-file-preview.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file-preview.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File ID", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + }, + { + "name": "width", + "description": "Resize preview image width, Pass an integer between 0 to 4000.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0, + "in": "query" + }, + { + "name": "height", + "description": "Resize preview image height, Pass an integer between 0 to 4000.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0, + "in": "query" + }, + { + "name": "gravity", + "description": "Image crop gravity. Can be one of center,top-left,top,top-right,left,right,bottom-left,bottom,bottom-right", + "required": false, + "type": "string", + "x-example": "center", + "enum": [ + "center", + "top-left", + "top", + "top-right", + "left", + "right", + "bottom-left", + "bottom", + "bottom-right" + ], + "x-enum-name": "ImageGravity", + "x-enum-keys": [], + "default": "center", + "in": "query" + }, + { + "name": "quality", + "description": "Preview image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1, + "in": "query" + }, + { + "name": "borderWidth", + "description": "Preview image border in pixels. Pass an integer between 0 to 100. Defaults to 0.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0, + "in": "query" + }, + { + "name": "borderColor", + "description": "Preview image border color. Use a valid HEX color, no # is needed for prefix.", + "required": false, + "type": "string", + "default": "", + "in": "query" + }, + { + "name": "borderRadius", + "description": "Preview image border radius in pixels. Pass an integer between 0 to 4000.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0, + "in": "query" + }, + { + "name": "opacity", + "description": "Preview image opacity. Only works with images having an alpha channel (like png). Pass a number between 0 to 1.", + "required": false, + "type": "number", + "format": "float", + "x-example": 0, + "default": 1, + "in": "query" + }, + { + "name": "rotation", + "description": "Preview image rotation in degrees. Pass an integer between -360 and 360.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": -360, + "default": 0, + "in": "query" + }, + { + "name": "background", + "description": "Preview image background color. Only works with transparent images (png). Use a valid HEX color, no # is needed for prefix.", + "required": false, + "type": "string", + "default": "", + "in": "query" + }, + { + "name": "output", + "description": "Output format type (jpeg, jpg, png, gif and webp).", + "required": false, + "type": "string", + "x-example": "jpg", + "enum": [ + "jpg", + "jpeg", + "png", + "webp", + "heic", + "avif", + "gif" + ], + "x-enum-name": "ImageFormat", + "x-enum-keys": [], + "default": "", + "in": "query" + }, + { + "name": "token", + "description": "File token for accessing this file.", + "required": false, + "type": "string", + "x-example": "<TOKEN>", + "default": "", + "in": "query" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/view": { + "get": { + "summary": "Get file for view", + "operationId": "storageGetFileView", + "consumes": [], + "produces": [ + "*\/*" + ], + "tags": [ + "storage" + ], + "description": "Get a file content by its unique ID. This endpoint is similar to the download method but returns with no 'Content-Disposition: attachment' header.", + "responses": { + "200": { + "description": "File", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getFileView", + "group": "files", + "weight": 218, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "storage\/get-file-view.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file-view.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + }, + { + "name": "token", + "description": "File token for accessing this file.", + "required": false, + "type": "string", + "x-example": "<TOKEN>", + "default": "", + "in": "query" + } + ] + } + }, + "\/storage\/usage": { + "get": { + "summary": "Get storage usage stats", + "operationId": "storageGetUsage", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Get usage metrics and statistics for all buckets in the project. You can view the total number of buckets, files, storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.\n", + "responses": { + "200": { + "description": "StorageUsage", + "schema": { + "$ref": "#\/definitions\/usageStorage" + } + } + }, + "x-appwrite": { + "method": "getUsage", + "group": null, + "weight": 222, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/get-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-usage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "range", + "description": "Date range.", + "required": false, + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "StorageUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d", + "in": "query" + } + ] + } + }, + "\/storage\/{bucketId}\/usage": { + "get": { + "summary": "Get bucket usage stats", + "operationId": "storageGetBucketUsage", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Get usage metrics and statistics a specific bucket in the project. You can view the total number of files, storage usage. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.\n", + "responses": { + "200": { + "description": "UsageBuckets", + "schema": { + "$ref": "#\/definitions\/usageBuckets" + } + } + }, + "x-appwrite": { + "method": "getBucketUsage", + "group": null, + "weight": 223, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/get-bucket-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-bucket-usage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Bucket ID.", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "range", + "description": "Date range.", + "required": false, + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "StorageUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d", + "in": "query" + } + ] + } + }, + "\/teams": { + "get": { + "summary": "List teams", + "operationId": "teamsList", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Get a list of all the teams in which the current user is a member. You can use the parameters to filter your results.", + "responses": { + "200": { + "description": "Teams List", + "schema": { + "$ref": "#\/definitions\/teamList" + } + } + }, + "x-appwrite": { + "method": "list", + "group": "teams", + "weight": 225, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/list-teams.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, total, billingPlan", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create team", + "operationId": "teamsCreate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Create a new team. The user who creates the team will automatically be assigned as the owner of the team. Only the users with the owner role can invite new members, add new owners and delete or update the team.", + "responses": { + "201": { + "description": "Team", + "schema": { + "$ref": "#\/definitions\/team" + } + } + }, + "x-appwrite": { + "method": "create", + "group": "teams", + "weight": 224, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/create-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "teamId": { + "type": "string", + "description": "Team ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<TEAM_ID>" + }, + "name": { + "type": "string", + "description": "Team name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "roles": { + "type": "array", + "description": "Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.", + "default": [ + "owner" + ], + "x-example": null, + "items": { + "type": "string" + } + } + }, + "required": [ + "teamId", + "name" + ] + } + } + ] + } + }, + "\/teams\/{teamId}": { + "get": { + "summary": "Get team", + "operationId": "teamsGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Get a team by its ID. All team members have read access for this resource.", + "responses": { + "200": { + "description": "Team", + "schema": { + "$ref": "#\/definitions\/team" + } + } + }, + "x-appwrite": { + "method": "get", + "group": "teams", + "weight": 226, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update name", + "operationId": "teamsUpdateName", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Update the team's name by its unique ID.", + "responses": { + "200": { + "description": "Team", + "schema": { + "$ref": "#\/definitions\/team" + } + } + }, + "x-appwrite": { + "method": "updateName", + "group": "teams", + "weight": 228, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-name.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-name.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "New team name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + } + }, + "required": [ + "name" + ] + } + } + ] + }, + "delete": { + "summary": "Delete team", + "operationId": "teamsDelete", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "teams" + ], + "description": "Delete a team using its ID. Only team members with the owner role can delete the team.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "teams", + "weight": 230, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/delete-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + } + ] + } + }, + "\/teams\/{teamId}\/logs": { + "get": { + "summary": "List team logs", + "operationId": "teamsListLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Get the team activity logs list by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "schema": { + "$ref": "#\/definitions\/logList" + } + } + }, + "x-appwrite": { + "method": "listLogs", + "group": "logs", + "weight": 237, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/list-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/teams\/{teamId}\/memberships": { + "get": { + "summary": "List team memberships", + "operationId": "teamsListMemberships", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Use this endpoint to list a team's members using the team's ID. All team members have read access to this endpoint. Hide sensitive attributes from the response by toggling membership privacy in the Console.", + "responses": { + "200": { + "description": "Memberships List", + "schema": { + "$ref": "#\/definitions\/membershipList" + } + } + }, + "x-appwrite": { + "method": "listMemberships", + "group": "memberships", + "weight": 232, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/list-memberships.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/list-team-members.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create team membership", + "operationId": "teamsCreateMembership", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Invite a new member to join your team. Provide an ID for existing users, or invite unregistered users using an email or phone number. If initiated from a Client SDK, Appwrite will send an email or sms with a link to join the team to the invited user, and an account will be created for them if one doesn't exist. If initiated from a Server SDK, the new member will be added automatically to the team.\n\nYou only need to provide one of a user ID, email, or phone number. Appwrite will prioritize accepting the user ID > email > phone number if you provide more than one of these parameters.\n\nUse the `url` parameter to redirect the user from the invitation email to your app. After the user is redirected, use the [Update Team Membership Status](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/teams#updateMembershipStatus) endpoint to allow the user to accept the invitation to the team. \n\nPlease note that to avoid a [Redirect Attack](https:\/\/github.com\/OWASP\/CheatSheetSeries\/blob\/master\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) Appwrite will accept the only redirect URLs under the domains you have added as a platform on the Appwrite Console.\n", + "responses": { + "201": { + "description": "Membership", + "schema": { + "$ref": "#\/definitions\/membership" + } + } + }, + "x-appwrite": { + "method": "createMembership", + "group": "memberships", + "weight": 231, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/create-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/create-team-membership.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "Email of the new team member.", + "default": "", + "x-example": "email@example.com" + }, + "userId": { + "type": "string", + "description": "ID of the user to be added to a team.", + "default": "", + "x-example": "<USER_ID>" + }, + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "default": "", + "x-example": "+12065550100" + }, + "roles": { + "type": "array", + "description": "Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "default": "", + "x-example": "https:\/\/example.com" + }, + "name": { + "type": "string", + "description": "Name of the new team member. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "roles" + ] + } + } + ] + } + }, + "\/teams\/{teamId}\/memberships\/{membershipId}": { + "get": { + "summary": "Get team membership", + "operationId": "teamsGetMembership", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Get a team member by the membership unique id. All team members have read access for this resource. Hide sensitive attributes from the response by toggling membership privacy in the Console.", + "responses": { + "200": { + "description": "Membership", + "schema": { + "$ref": "#\/definitions\/membership" + } + } + }, + "x-appwrite": { + "method": "getMembership", + "group": "memberships", + "weight": 233, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/get-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team-member.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "type": "string", + "x-example": "<MEMBERSHIP_ID>", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update membership", + "operationId": "teamsUpdateMembership", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Modify the roles of a team member. Only team members with the owner role have access to this endpoint. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions).\n", + "responses": { + "200": { + "description": "Membership", + "schema": { + "$ref": "#\/definitions\/membership" + } + } + }, + "x-appwrite": { + "method": "updateMembership", + "group": "memberships", + "weight": 234, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-membership.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "type": "string", + "x-example": "<MEMBERSHIP_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "roles": { + "type": "array", + "description": "An array of strings. Use this param to set the user's roles in the team. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + } + }, + "required": [ + "roles" + ] + } + } + ] + }, + "delete": { + "summary": "Delete team membership", + "operationId": "teamsDeleteMembership", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "teams" + ], + "description": "This endpoint allows a user to leave a team or for a team owner to delete the membership of any other team member. You can also use this endpoint to delete a user membership even if it is not accepted.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteMembership", + "group": "memberships", + "weight": 236, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/delete-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/delete-team-membership.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "type": "string", + "x-example": "<MEMBERSHIP_ID>", + "in": "path" + } + ] + } + }, + "\/teams\/{teamId}\/memberships\/{membershipId}\/status": { + "patch": { + "summary": "Update team membership status", + "operationId": "teamsUpdateMembershipStatus", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Use this endpoint to allow a user to accept an invitation to join a team after being redirected back to your app from the invitation email received by the user.\n\nIf the request is successful, a session for the user is automatically created.\n", + "responses": { + "200": { + "description": "Membership", + "schema": { + "$ref": "#\/definitions\/membership" + } + } + }, + "x-appwrite": { + "method": "updateMembershipStatus", + "group": "memberships", + "weight": 235, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-membership-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-membership-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "type": "string", + "x-example": "<MEMBERSHIP_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Secret key.", + "default": null, + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + ] + } + }, + "\/teams\/{teamId}\/prefs": { + "get": { + "summary": "Get team preferences", + "operationId": "teamsGetPrefs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Get the team's shared preferences by its unique ID. If a preference doesn't need to be shared by all team members, prefer storing them in [user preferences](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#getPrefs).", + "responses": { + "200": { + "description": "Preferences", + "schema": { + "$ref": "#\/definitions\/preferences" + } + } + }, + "x-appwrite": { + "method": "getPrefs", + "group": "teams", + "weight": 227, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/get-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update preferences", + "operationId": "teamsUpdatePrefs", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Update the team's preferences by its unique ID. The object you pass is stored as is and replaces any previous value. The maximum allowed prefs size is 64kB and throws an error if exceeded.", + "responses": { + "200": { + "description": "Preferences", + "schema": { + "$ref": "#\/definitions\/preferences" + } + } + }, + "x-appwrite": { + "method": "updatePrefs", + "group": "teams", + "weight": 229, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "prefs": { + "type": "object", + "description": "Prefs key-value JSON object.", + "default": {}, + "x-example": "{}" + } + }, + "required": [ + "prefs" + ] + } + } + ] + } + }, + "\/tokens\/buckets\/{bucketId}\/files\/{fileId}": { + "get": { + "summary": "List tokens", + "operationId": "tokensList", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "tokens" + ], + "description": "List all the tokens created for a specific file or bucket. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Resource Tokens List", + "schema": { + "$ref": "#\/definitions\/resourceTokenList" + } + } + }, + "x-appwrite": { + "method": "list", + "group": "files", + "weight": 441, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList all the tokens created for a specific file or bucket. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "tokens.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: expire", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create file token", + "operationId": "tokensCreateFileToken", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tokens" + ], + "description": "Create a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", + "responses": { + "201": { + "description": "ResourceToken", + "schema": { + "$ref": "#\/definitions\/resourceToken" + } + } + }, + "x-appwrite": { + "method": "createFileToken", + "group": "files", + "weight": 439, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/create-file-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "tokens.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "expire": { + "type": "string", + "description": "Token expiry date", + "default": null, + "x-example": null, + "x-nullable": true + } + } + } + } + ] + } + }, + "\/tokens\/{tokenId}": { + "get": { + "summary": "Get token", + "operationId": "tokensGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "tokens" + ], + "description": "Get a token by its unique ID.", + "responses": { + "200": { + "description": "ResourceToken", + "schema": { + "$ref": "#\/definitions\/resourceToken" + } + } + }, + "x-appwrite": { + "method": "get", + "group": "tokens", + "weight": 440, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a token by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "tokens.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "type": "string", + "x-example": "<TOKEN_ID>", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update token", + "operationId": "tokensUpdate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tokens" + ], + "description": "Update a token by its unique ID. Use this endpoint to update a token's expiry date.", + "responses": { + "200": { + "description": "ResourceToken", + "schema": { + "$ref": "#\/definitions\/resourceToken" + } + } + }, + "x-appwrite": { + "method": "update", + "group": "tokens", + "weight": 442, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/update.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate a token by its unique ID. Use this endpoint to update a token's expiry date.", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "tokens.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token unique ID.", + "required": true, + "type": "string", + "x-example": "<TOKEN_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "expire": { + "type": "string", + "description": "File token expiry date", + "default": null, + "x-example": null, + "x-nullable": true + } + } + } + } + ] + }, + "delete": { + "summary": "Delete token", + "operationId": "tokensDelete", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "tokens" + ], + "description": "Delete a token by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "tokens", + "weight": 443, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a token by its unique ID.", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "tokens.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "type": "string", + "x-example": "<TOKEN_ID>", + "in": "path" + } + ] + } + }, + "\/users": { + "get": { + "summary": "List users", + "operationId": "usersList", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get a list of all the project's users. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Users List", + "schema": { + "$ref": "#\/definitions\/userList" + } + } + }, + "x-appwrite": { + "method": "list", + "group": "users", + "weight": 247, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-users.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, email, phone, status, passwordUpdate, registration, emailVerification, phoneVerification, labels", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create user", + "operationId": "usersCreate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Create a new user.", + "responses": { + "201": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "create", + "group": "users", + "weight": 238, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "default": null, + "x-example": "+12065550100" + }, + "password": { + "type": "string", + "description": "Plain text user password. Must be at least 8 chars.", + "default": "", + "x-example": null + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "userId" + ] + } + } + ] + } + }, + "\/users\/argon2": { + "post": { + "summary": "Create user with Argon2 password", + "operationId": "usersCreateArgon2User", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [Argon2](https:\/\/en.wikipedia.org\/wiki\/Argon2) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "createArgon2User", + "group": "users", + "weight": 241, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-argon2user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-argon2-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using Argon2.", + "default": null, + "x-example": "password" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + ] + } + }, + "\/users\/bcrypt": { + "post": { + "summary": "Create user with bcrypt password", + "operationId": "usersCreateBcryptUser", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [Bcrypt](https:\/\/en.wikipedia.org\/wiki\/Bcrypt) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "createBcryptUser", + "group": "users", + "weight": 239, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-bcrypt-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-bcrypt-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using Bcrypt.", + "default": null, + "x-example": "password" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + ] + } + }, + "\/users\/identities": { + "get": { + "summary": "List identities", + "operationId": "usersListIdentities", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get identities for all users.", + "responses": { + "200": { + "description": "Identities List", + "schema": { + "$ref": "#\/definitions\/identityList" + } + } + }, + "x-appwrite": { + "method": "listIdentities", + "group": "identities", + "weight": 255, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-identities.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-identities.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, provider, providerUid, providerEmail, providerAccessTokenExpiry", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + } + }, + "\/users\/identities\/{identityId}": { + "delete": { + "summary": "Delete identity", + "operationId": "usersDeleteIdentity", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "users" + ], + "description": "Delete an identity by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteIdentity", + "group": "identities", + "weight": 278, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-identity.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-identity.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "identityId", + "description": "Identity ID.", + "required": true, + "type": "string", + "x-example": "<IDENTITY_ID>", + "in": "path" + } + ] + } + }, + "\/users\/md5": { + "post": { + "summary": "Create user with MD5 password", + "operationId": "usersCreateMD5User", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [MD5](https:\/\/en.wikipedia.org\/wiki\/MD5) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "createMD5User", + "group": "users", + "weight": 240, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-m-d5user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-md5-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using MD5.", + "default": null, + "x-example": "password" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + ] + } + }, + "\/users\/phpass": { + "post": { + "summary": "Create user with PHPass password", + "operationId": "usersCreatePHPassUser", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [PHPass](https:\/\/www.openwall.com\/phpass\/) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "createPHPassUser", + "group": "users", + "weight": 243, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-p-h-pass-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-phpass-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or pass the string `ID.unique()`to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using PHPass.", + "default": null, + "x-example": "password" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + ] + } + }, + "\/users\/scrypt": { + "post": { + "summary": "Create user with Scrypt password", + "operationId": "usersCreateScryptUser", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [Scrypt](https:\/\/github.com\/Tarsnap\/scrypt) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "createScryptUser", + "group": "users", + "weight": 244, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-scrypt-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-scrypt-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using Scrypt.", + "default": null, + "x-example": "password" + }, + "passwordSalt": { + "type": "string", + "description": "Optional salt used to hash password.", + "default": null, + "x-example": "<PASSWORD_SALT>" + }, + "passwordCpu": { + "type": "integer", + "description": "Optional CPU cost used to hash password.", + "default": null, + "x-example": null + }, + "passwordMemory": { + "type": "integer", + "description": "Optional memory cost used to hash password.", + "default": null, + "x-example": null + }, + "passwordParallel": { + "type": "integer", + "description": "Optional parallelization cost used to hash password.", + "default": null, + "x-example": null + }, + "passwordLength": { + "type": "integer", + "description": "Optional hash length used to hash password.", + "default": null, + "x-example": null + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password", + "passwordSalt", + "passwordCpu", + "passwordMemory", + "passwordParallel", + "passwordLength" + ] + } + } + ] + } + }, + "\/users\/scrypt-modified": { + "post": { + "summary": "Create user with Scrypt modified password", + "operationId": "usersCreateScryptModifiedUser", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [Scrypt Modified](https:\/\/gist.github.com\/Meldiron\/eecf84a0225eccb5a378d45bb27462cc) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "createScryptModifiedUser", + "group": "users", + "weight": 245, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-scrypt-modified-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-scrypt-modified-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using Scrypt Modified.", + "default": null, + "x-example": "password" + }, + "passwordSalt": { + "type": "string", + "description": "Salt used to hash password.", + "default": null, + "x-example": "<PASSWORD_SALT>" + }, + "passwordSaltSeparator": { + "type": "string", + "description": "Salt separator used to hash password.", + "default": null, + "x-example": "<PASSWORD_SALT_SEPARATOR>" + }, + "passwordSignerKey": { + "type": "string", + "description": "Signer key used to hash password.", + "default": null, + "x-example": "<PASSWORD_SIGNER_KEY>" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password", + "passwordSalt", + "passwordSaltSeparator", + "passwordSignerKey" + ] + } + } + ] + } + }, + "\/users\/sha": { + "post": { + "summary": "Create user with SHA password", + "operationId": "usersCreateSHAUser", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [SHA](https:\/\/en.wikipedia.org\/wiki\/Secure_Hash_Algorithm) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "createSHAUser", + "group": "users", + "weight": 242, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-s-h-a-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-sha-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using SHA.", + "default": null, + "x-example": "password" + }, + "passwordVersion": { + "type": "string", + "description": "Optional SHA version used to hash password. Allowed values are: 'sha1', 'sha224', 'sha256', 'sha384', 'sha512\/224', 'sha512\/256', 'sha512', 'sha3-224', 'sha3-256', 'sha3-384', 'sha3-512'", + "default": "", + "x-example": "sha1", + "enum": [ + "sha1", + "sha224", + "sha256", + "sha384", + "sha512\/224", + "sha512\/256", + "sha512", + "sha3-224", + "sha3-256", + "sha3-384", + "sha3-512" + ], + "x-enum-name": "PasswordHash", + "x-enum-keys": [] + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + ] + } + }, + "\/users\/usage": { + "get": { + "summary": "Get users usage stats", + "operationId": "usersGetUsage", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get usage metrics and statistics for all users in the project. You can view the total number of users and sessions. The response includes both current totals and historical data over time. Use the optional range parameter to specify the time window for historical data: 24h (last 24 hours), 30d (last 30 days), or 90d (last 90 days). If not specified, range defaults to 30 days.\n", + "responses": { + "200": { + "description": "UsageUsers", + "schema": { + "$ref": "#\/definitions\/usageUsers" + } + } + }, + "x-appwrite": { + "method": "getUsage", + "group": null, + "weight": 280, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/get-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-usage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "range", + "description": "Date range.", + "required": false, + "type": "string", + "x-example": "24h", + "enum": [ + "24h", + "30d", + "90d" + ], + "x-enum-name": "UserUsageRange", + "x-enum-keys": [ + "Twenty Four Hours", + "Thirty Days", + "Ninety Days" + ], + "default": "30d", + "in": "query" + } + ] + } + }, + "\/users\/{userId}": { + "get": { + "summary": "Get user", + "operationId": "usersGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get a user by its unique ID.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "get", + "group": "users", + "weight": 248, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete user", + "operationId": "usersDelete", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "users" + ], + "description": "Delete a user by its unique ID, thereby releasing it's ID. Since ID is released and can be reused, all user-related resources like documents or storage files should be deleted before user deletion. If you want to keep ID reserved, use the [updateStatus](https:\/\/appwrite.io\/docs\/server\/users#usersUpdateStatus) endpoint instead.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "users", + "weight": 276, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/email": { + "patch": { + "summary": "Update email", + "operationId": "usersUpdateEmail", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update the user email by its unique ID.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateEmail", + "group": "users", + "weight": 261, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-email.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + } + }, + "required": [ + "email" + ] + } + } + ] + } + }, + "\/users\/{userId}\/jwts": { + "post": { + "summary": "Create user JWT", + "operationId": "usersCreateJWT", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Use this endpoint to create a JSON Web Token for user by its unique ID. You can use the resulting JWT to authenticate on behalf of the user. The JWT secret will become invalid if the session it uses gets deleted.", + "responses": { + "201": { + "description": "JWT", + "schema": { + "$ref": "#\/definitions\/jwt" + } + } + }, + "x-appwrite": { + "method": "createJWT", + "group": "sessions", + "weight": 279, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-j-w-t.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-user-jwt.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "description": "Session ID. Use the string 'recent' to use the most recent session. Defaults to the most recent session.", + "default": "", + "x-example": "<SESSION_ID>" + }, + "duration": { + "type": "integer", + "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", + "default": 900, + "x-example": 0 + } + } + } + } + ] + } + }, + "\/users\/{userId}\/labels": { + "put": { + "summary": "Update user labels", + "operationId": "usersUpdateLabels", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update the user labels by its unique ID. \n\nLabels can be used to grant access to resources. While teams are a way for user's to share access to a resource, labels can be defined by the developer to grant access without an invitation. See the [Permissions docs](https:\/\/appwrite.io\/docs\/permissions) for more info.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateLabels", + "group": "users", + "weight": 257, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-labels.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-labels.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "labels": { + "type": "array", + "description": "Array of user labels. Replaces the previous labels. Maximum of 1000 labels are allowed, each up to 36 alphanumeric characters long.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + } + }, + "required": [ + "labels" + ] + } + } + ] + } + }, + "\/users\/{userId}\/logs": { + "get": { + "summary": "List user logs", + "operationId": "usersListLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get the user activity logs list by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "schema": { + "$ref": "#\/definitions\/logList" + } + } + }, + "x-appwrite": { + "method": "listLogs", + "group": "logs", + "weight": 253, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-user-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/users\/{userId}\/memberships": { + "get": { + "summary": "List user memberships", + "operationId": "usersListMemberships", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get the user membership list by its unique ID.", + "responses": { + "200": { + "description": "Memberships List", + "schema": { + "$ref": "#\/definitions\/membershipList" + } + } + }, + "x-appwrite": { + "method": "listMemberships", + "group": "memberships", + "weight": 252, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-memberships.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-user-memberships.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + } + }, + "\/users\/{userId}\/mfa": { + "patch": { + "summary": "Update MFA", + "operationId": "usersUpdateMfa", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Enable or disable MFA on a user account.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateMfa", + "group": "users", + "weight": 266, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-mfa.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-mfa.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "mfa": { + "type": "boolean", + "description": "Enable or disable MFA.", + "default": null, + "x-example": false + } + }, + "required": [ + "mfa" + ] + } + } + ] + } + }, + "\/users\/{userId}\/mfa\/authenticators\/{type}": { + "delete": { + "summary": "Delete authenticator", + "operationId": "usersDeleteMfaAuthenticator", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "users" + ], + "description": "Delete an authenticator app.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteMfaAuthenticator", + "group": "mfa", + "weight": 271, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "type", + "description": "Type of authenticator.", + "required": true, + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [], + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/mfa\/factors": { + "get": { + "summary": "List factors", + "operationId": "usersListMfaFactors", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "List the factors available on the account to be used as a MFA challange.", + "responses": { + "200": { + "description": "MFAFactors", + "schema": { + "$ref": "#\/definitions\/mfaFactors" + } + } + }, + "x-appwrite": { + "method": "listMfaFactors", + "group": "mfa", + "weight": 267, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-mfa-factors.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-mfa-factors.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/mfa\/recovery-codes": { + "get": { + "summary": "Get MFA recovery codes", + "operationId": "usersGetMfaRecoveryCodes", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get recovery codes that can be used as backup for MFA flow by User ID. Before getting codes, they must be generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "schema": { + "$ref": "#\/definitions\/mfaRecoveryCodes" + } + } + }, + "x-appwrite": { + "method": "getMfaRecoveryCodes", + "group": "mfa", + "weight": 268, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/get-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update MFA recovery codes (regenerate)", + "operationId": "usersUpdateMfaRecoveryCodes", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Regenerate recovery codes that can be used as backup for MFA flow by User ID. Before regenerating codes, they must be first generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "schema": { + "$ref": "#\/definitions\/mfaRecoveryCodes" + } + } + }, + "x-appwrite": { + "method": "updateMfaRecoveryCodes", + "group": "mfa", + "weight": 270, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + }, + "patch": { + "summary": "Create MFA recovery codes", + "operationId": "usersCreateMfaRecoveryCodes", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Generate recovery codes used as backup for MFA flow for User ID. Recovery codes can be used as a MFA verification type in [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method by client SDK.", + "responses": { + "201": { + "description": "MFA Recovery Codes", + "schema": { + "$ref": "#\/definitions\/mfaRecoveryCodes" + } + } + }, + "x-appwrite": { + "method": "createMfaRecoveryCodes", + "group": "mfa", + "weight": 269, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/name": { + "patch": { + "summary": "Update name", + "operationId": "usersUpdateName", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update the user name by its unique ID.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateName", + "group": "users", + "weight": 259, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-name.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-name.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + } + }, + "required": [ + "name" + ] + } + } + ] + } + }, + "\/users\/{userId}\/password": { + "patch": { + "summary": "Update password", + "operationId": "usersUpdatePassword", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update the user password by its unique ID.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updatePassword", + "group": "users", + "weight": 260, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-password.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-password.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "password": { + "type": "string", + "description": "New user password. Must be at least 8 chars.", + "default": null, + "x-example": null + } + }, + "required": [ + "password" + ] + } + } + ] + } + }, + "\/users\/{userId}\/phone": { + "patch": { + "summary": "Update phone", + "operationId": "usersUpdatePhone", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update the user phone by its unique ID.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updatePhone", + "group": "users", + "weight": 262, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-phone.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-phone.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "number": { + "type": "string", + "description": "User phone number.", + "default": null, + "x-example": "+12065550100" + } + }, + "required": [ + "number" + ] + } + } + ] + } + }, + "\/users\/{userId}\/prefs": { + "get": { + "summary": "Get user preferences", + "operationId": "usersGetPrefs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get the user preferences by its unique ID.", + "responses": { + "200": { + "description": "Preferences", + "schema": { + "$ref": "#\/definitions\/preferences" + } + } + }, + "x-appwrite": { + "method": "getPrefs", + "group": "users", + "weight": 249, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/get-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-user-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update user preferences", + "operationId": "usersUpdatePrefs", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update the user preferences by its unique ID. The object you pass is stored as is, and replaces any previous value. The maximum allowed prefs size is 64kB and throws error if exceeded.", + "responses": { + "200": { + "description": "Preferences", + "schema": { + "$ref": "#\/definitions\/preferences" + } + } + }, + "x-appwrite": { + "method": "updatePrefs", + "group": "users", + "weight": 264, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "prefs": { + "type": "object", + "description": "Prefs key-value JSON object.", + "default": {}, + "x-example": "{}" + } + }, + "required": [ + "prefs" + ] + } + } + ] + } + }, + "\/users\/{userId}\/sessions": { + "get": { + "summary": "List user sessions", + "operationId": "usersListSessions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get the user sessions list by its unique ID.", + "responses": { + "200": { + "description": "Sessions List", + "schema": { + "$ref": "#\/definitions\/sessionList" + } + } + }, + "x-appwrite": { + "method": "listSessions", + "group": "sessions", + "weight": 251, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-user-sessions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + }, + "post": { + "summary": "Create session", + "operationId": "usersCreateSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Creates a session for a user. Returns an immediately usable session object.\n\nIf you want to generate a token for a custom authentication flow, use the [POST \/users\/{userId}\/tokens](https:\/\/appwrite.io\/docs\/server\/users#createToken) endpoint.", + "responses": { + "201": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "createSession", + "group": "sessions", + "weight": 272, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-session.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete user sessions", + "operationId": "usersDeleteSessions", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "users" + ], + "description": "Delete all user's sessions by using the user's unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSessions", + "group": "sessions", + "weight": 275, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-user-sessions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/sessions\/{sessionId}": { + "delete": { + "summary": "Delete user session", + "operationId": "usersDeleteSession", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "users" + ], + "description": "Delete a user sessions by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSession", + "group": "sessions", + "weight": 274, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-user-session.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "sessionId", + "description": "Session ID.", + "required": true, + "type": "string", + "x-example": "<SESSION_ID>", + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/status": { + "patch": { + "summary": "Update user status", + "operationId": "usersUpdateStatus", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update the user status by its unique ID. Use this endpoint as an alternative to deleting a user if you want to keep user's ID reserved.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateStatus", + "group": "users", + "weight": 256, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "status": { + "type": "boolean", + "description": "User Status. To activate the user pass `true` and to block the user pass `false`.", + "default": null, + "x-example": false + } + }, + "required": [ + "status" + ] + } + } + ] + } + }, + "\/users\/{userId}\/targets": { + "get": { + "summary": "List user targets", + "operationId": "usersListTargets", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "List the messaging targets that are associated with a user.", + "responses": { + "200": { + "description": "Target list", + "schema": { + "$ref": "#\/definitions\/targetList" + } + } + }, + "x-appwrite": { + "method": "listTargets", + "group": "targets", + "weight": 254, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-targets.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-user-targets.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.read", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, providerId, identifier, providerType", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create user target", + "operationId": "usersCreateTarget", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Create a messaging target.", + "responses": { + "201": { + "description": "Target", + "schema": { + "$ref": "#\/definitions\/target" + } + } + }, + "x-appwrite": { + "method": "createTarget", + "group": "targets", + "weight": 246, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "targetId": { + "type": "string", + "description": "Target ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<TARGET_ID>" + }, + "providerType": { + "type": "string", + "description": "The target provider type. Can be one of the following: `email`, `sms` or `push`.", + "default": null, + "x-example": "email", + "enum": [ + "email", + "sms", + "push" + ], + "x-enum-name": "MessagingProviderType", + "x-enum-keys": [] + }, + "identifier": { + "type": "string", + "description": "The target identifier (token, email, phone etc.)", + "default": null, + "x-example": "<IDENTIFIER>" + }, + "providerId": { + "type": "string", + "description": "Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.", + "default": "", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Target name. Max length: 128 chars. For example: My Awesome App Galaxy S23.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "targetId", + "providerType", + "identifier" + ] + } + } + ] + } + }, + "\/users\/{userId}\/targets\/{targetId}": { + "get": { + "summary": "Get user target", + "operationId": "usersGetTarget", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get a user's push notification target by ID.", + "responses": { + "200": { + "description": "Target", + "schema": { + "$ref": "#\/definitions\/target" + } + } + }, + "x-appwrite": { + "method": "getTarget", + "group": "targets", + "weight": 250, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/get-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-user-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.read", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "type": "string", + "x-example": "<TARGET_ID>", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update user target", + "operationId": "usersUpdateTarget", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update a messaging target.", + "responses": { + "200": { + "description": "Target", + "schema": { + "$ref": "#\/definitions\/target" + } + } + }, + "x-appwrite": { + "method": "updateTarget", + "group": "targets", + "weight": 265, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "type": "string", + "x-example": "<TARGET_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "description": "The target identifier (token, email, phone etc.)", + "default": "", + "x-example": "<IDENTIFIER>" + }, + "providerId": { + "type": "string", + "description": "Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.", + "default": "", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Target name. Max length: 128 chars. For example: My Awesome App Galaxy S23.", + "default": "", + "x-example": "<NAME>" + } + } + } + } + ] + }, + "delete": { + "summary": "Delete user target", + "operationId": "usersDeleteTarget", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "users" + ], + "description": "Delete a messaging target.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteTarget", + "group": "targets", + "weight": 277, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "type": "string", + "x-example": "<TARGET_ID>", + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/tokens": { + "post": { + "summary": "Create token", + "operationId": "usersCreateToken", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Returns a token with a secret key for creating a session. Use the user ID and secret and submit a request to the [PUT \/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process.\n", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createToken", + "group": "sessions", + "weight": 273, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-token.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "length": { + "type": "integer", + "description": "Token length in characters. The default length is 6 characters", + "default": 6, + "x-example": 4 + }, + "expire": { + "type": "integer", + "description": "Token expiration period in seconds. The default expiration is 15 minutes.", + "default": 900, + "x-example": 60 + } + } + } + } + ] + } + }, + "\/users\/{userId}\/verification": { + "patch": { + "summary": "Update email verification", + "operationId": "usersUpdateEmailVerification", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update the user email verification status by its unique ID.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateEmailVerification", + "group": "users", + "weight": 263, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-email-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-email-verification.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "emailVerification": { + "type": "boolean", + "description": "User email verification status.", + "default": null, + "x-example": false + } + }, + "required": [ + "emailVerification" + ] + } + } + ] + } + }, + "\/users\/{userId}\/verification\/phone": { + "patch": { + "summary": "Update phone verification", + "operationId": "usersUpdatePhoneVerification", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update the user phone verification status by its unique ID.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updatePhoneVerification", + "group": "users", + "weight": 258, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-phone-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-phone-verification.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "phoneVerification": { + "type": "boolean", + "description": "User phone verification status.", + "default": null, + "x-example": false + } + }, + "required": [ + "phoneVerification" + ] + } + } + ] + } + }, + "\/vcs\/github\/installations\/{installationId}\/detections": { + "post": { + "summary": "Create repository detection", + "operationId": "vcsCreateRepositoryDetection", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "vcs" + ], + "description": "Analyze a GitHub repository to automatically detect the programming language and runtime environment. This endpoint scans the repository's files and language statistics to determine the appropriate runtime settings for your function. The GitHub installation must be properly configured and the repository must be accessible through your installation for this endpoint to work.", + "responses": { + "200": { + "description": "DetectionFramework", + "schema": { + "$ref": "#\/definitions\/detectionFramework" + } + } + }, + "x-appwrite": { + "method": "createRepositoryDetection", + "group": "repositories", + "weight": 284, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/create-repository-detection.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/create-repository-detection.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "installationId", + "description": "Installation Id", + "required": true, + "type": "string", + "x-example": "<INSTALLATION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerRepositoryId": { + "type": "string", + "description": "Repository Id", + "default": null, + "x-example": "<PROVIDER_REPOSITORY_ID>" + }, + "type": { + "type": "string", + "description": "Detector type. Must be one of the following: runtime, framework", + "default": null, + "x-example": "runtime", + "enum": [ + "runtime", + "framework" + ], + "x-enum-name": "VCSDetectionType", + "x-enum-keys": [] + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to Root Directory", + "default": "", + "x-example": "<PROVIDER_ROOT_DIRECTORY>" + } + }, + "required": [ + "providerRepositoryId", + "type" + ] + } + } + ] + } + }, + "\/vcs\/github\/installations\/{installationId}\/providerRepositories": { + "get": { + "summary": "List repositories", + "operationId": "vcsListRepositories", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "vcs" + ], + "description": "Get a list of GitHub repositories available through your installation. This endpoint returns repositories with their basic information, detected runtime environments, and latest push dates. You can optionally filter repositories using a search term. Each repository's runtime is automatically detected based on its contents and language statistics. The GitHub installation must be properly configured for this endpoint to work.", + "responses": { + "200": { + "description": "Framework Provider Repositories List", + "schema": { + "$ref": "#\/definitions\/providerRepositoryFrameworkList" + } + } + }, + "x-appwrite": { + "method": "listRepositories", + "group": "repositories", + "weight": 285, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/list-repositories.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/list-repositories.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "installationId", + "description": "Installation Id", + "required": true, + "type": "string", + "x-example": "<INSTALLATION_ID>", + "in": "path" + }, + { + "name": "type", + "description": "Detector type. Must be one of the following: runtime, framework", + "required": true, + "type": "string", + "x-example": "runtime", + "enum": [ + "runtime", + "framework" + ], + "x-enum-name": "VCSDetectionType", + "x-enum-keys": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create repository", + "operationId": "vcsCreateRepository", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "vcs" + ], + "description": "Create a new GitHub repository through your installation. This endpoint allows you to create either a public or private repository by specifying a name and visibility setting. The repository will be created under your GitHub user account or organization, depending on your installation type. The GitHub installation must be properly configured and have the necessary permissions for repository creation.", + "responses": { + "200": { + "description": "ProviderRepository", + "schema": { + "$ref": "#\/definitions\/providerRepository" + } + } + }, + "x-appwrite": { + "method": "createRepository", + "group": "repositories", + "weight": 286, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/create-repository.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/create-repository.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "installationId", + "description": "Installation Id", + "required": true, + "type": "string", + "x-example": "<INSTALLATION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Repository name (slug)", + "default": null, + "x-example": "<NAME>" + }, + "private": { + "type": "boolean", + "description": "Mark repository public or private", + "default": null, + "x-example": false + } + }, + "required": [ + "name", + "private" + ] + } + } + ] + } + }, + "\/vcs\/github\/installations\/{installationId}\/providerRepositories\/{providerRepositoryId}": { + "get": { + "summary": "Get repository", + "operationId": "vcsGetRepository", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "vcs" + ], + "description": "Get detailed information about a specific GitHub repository from your installation. This endpoint returns repository details including its ID, name, visibility status, organization, and latest push date. The GitHub installation must be properly configured and have access to the requested repository for this endpoint to work.", + "responses": { + "200": { + "description": "ProviderRepository", + "schema": { + "$ref": "#\/definitions\/providerRepository" + } + } + }, + "x-appwrite": { + "method": "getRepository", + "group": "repositories", + "weight": 287, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/get-repository.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/get-repository.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "installationId", + "description": "Installation Id", + "required": true, + "type": "string", + "x-example": "<INSTALLATION_ID>", + "in": "path" + }, + { + "name": "providerRepositoryId", + "description": "Repository Id", + "required": true, + "type": "string", + "x-example": "<PROVIDER_REPOSITORY_ID>", + "in": "path" + } + ] + } + }, + "\/vcs\/github\/installations\/{installationId}\/providerRepositories\/{providerRepositoryId}\/branches": { + "get": { + "summary": "List repository branches", + "operationId": "vcsListRepositoryBranches", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "vcs" + ], + "description": "Get a list of all branches from a GitHub repository in your installation. This endpoint returns the names of all branches in the repository and their total count. The GitHub installation must be properly configured and have access to the requested repository for this endpoint to work.\n", + "responses": { + "200": { + "description": "Branches List", + "schema": { + "$ref": "#\/definitions\/branchList" + } + } + }, + "x-appwrite": { + "method": "listRepositoryBranches", + "group": "repositories", + "weight": 288, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/list-repository-branches.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/list-repository-branches.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "installationId", + "description": "Installation Id", + "required": true, + "type": "string", + "x-example": "<INSTALLATION_ID>", + "in": "path" + }, + { + "name": "providerRepositoryId", + "description": "Repository Id", + "required": true, + "type": "string", + "x-example": "<PROVIDER_REPOSITORY_ID>", + "in": "path" + } + ] + } + }, + "\/vcs\/github\/installations\/{installationId}\/providerRepositories\/{providerRepositoryId}\/contents": { + "get": { + "summary": "Get files and directories of a VCS repository", + "operationId": "vcsGetRepositoryContents", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "vcs" + ], + "description": "Get a list of files and directories from a GitHub repository connected to your project. This endpoint returns the contents of a specified repository path, including file names, sizes, and whether each item is a file or directory. The GitHub installation must be properly configured and the repository must be accessible through your installation for this endpoint to work.\n", + "responses": { + "200": { + "description": "VCS Content List", + "schema": { + "$ref": "#\/definitions\/vcsContentList" + } + } + }, + "x-appwrite": { + "method": "getRepositoryContents", + "group": "repositories", + "weight": 283, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/get-repository-contents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/get-repository-contents.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "installationId", + "description": "Installation Id", + "required": true, + "type": "string", + "x-example": "<INSTALLATION_ID>", + "in": "path" + }, + { + "name": "providerRepositoryId", + "description": "Repository Id", + "required": true, + "type": "string", + "x-example": "<PROVIDER_REPOSITORY_ID>", + "in": "path" + }, + { + "name": "providerRootDirectory", + "description": "Path to get contents of nested directory", + "required": false, + "type": "string", + "x-example": "<PROVIDER_ROOT_DIRECTORY>", + "default": "", + "in": "query" + } + ] + } + }, + "\/vcs\/github\/installations\/{installationId}\/repositories\/{repositoryId}": { + "patch": { + "summary": "Update external deployment (authorize)", + "operationId": "vcsUpdateExternalDeployments", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "vcs" + ], + "description": "Authorize and create deployments for a GitHub pull request in your project. This endpoint allows external contributions by creating deployments from pull requests, enabling preview environments for code review. The pull request must be open and not previously authorized. The GitHub installation must be properly configured and have access to both the repository and pull request for this endpoint to work.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "updateExternalDeployments", + "group": "repositories", + "weight": 293, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/update-external-deployments.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/update-external-deployments.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "installationId", + "description": "Installation Id", + "required": true, + "type": "string", + "x-example": "<INSTALLATION_ID>", + "in": "path" + }, + { + "name": "repositoryId", + "description": "VCS Repository Id", + "required": true, + "type": "string", + "x-example": "<REPOSITORY_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerPullRequestId": { + "type": "string", + "description": "GitHub Pull Request Id", + "default": null, + "x-example": "<PROVIDER_PULL_REQUEST_ID>" + } + }, + "required": [ + "providerPullRequestId" + ] + } + } + ] + } + }, + "\/vcs\/installations": { + "get": { + "summary": "List installations", + "operationId": "vcsListInstallations", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "vcs" + ], + "description": "List all VCS installations configured for the current project. This endpoint returns a list of installations including their provider, organization, and other configuration details.\n", + "responses": { + "200": { + "description": "Installations List", + "schema": { + "$ref": "#\/definitions\/installationList" + } + } + }, + "x-appwrite": { + "method": "listInstallations", + "group": "installations", + "weight": 290, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/list-installations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/list-installations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: provider, organization", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + } + }, + "\/vcs\/installations\/{installationId}": { + "get": { + "summary": "Get installation", + "operationId": "vcsGetInstallation", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "vcs" + ], + "description": "Get a VCS installation by its unique ID. This endpoint returns the installation's details including its provider, organization, and configuration. ", + "responses": { + "200": { + "description": "Installation", + "schema": { + "$ref": "#\/definitions\/installation" + } + } + }, + "x-appwrite": { + "method": "getInstallation", + "group": "installations", + "weight": 291, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/get-installation.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/get-installation.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.read", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "installationId", + "description": "Installation Id", + "required": true, + "type": "string", + "x-example": "<INSTALLATION_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete installation", + "operationId": "vcsDeleteInstallation", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "vcs" + ], + "description": "Delete a VCS installation by its unique ID. This endpoint removes the installation and all its associated repositories from the project.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteInstallation", + "group": "installations", + "weight": 292, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "vcs\/delete-installation.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/vcs\/delete-installation.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "vcs.write", + "platforms": [ + "console" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "installationId", + "description": "Installation Id", + "required": true, + "type": "string", + "x-example": "<INSTALLATION_ID>", + "in": "path" + } + ] + } + } + }, + "tags": [ + { + "name": "account", + "description": "The Account service allows you to authenticate and manage a user account." + }, + { + "name": "avatars", + "description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars." + }, + { + "name": "databases", + "description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents" + }, + { + "name": "locale", + "description": "The Locale service allows you to customize your app based on your users' location." + }, + { + "name": "health", + "description": "The Health service allows you to both validate and monitor your Appwrite server's health." + }, + { + "name": "projects", + "description": "The Project service allows you to manage all the projects in your Appwrite server." + }, + { + "name": "project", + "description": "The Project service allows you to manage all the projects in your Appwrite server." + }, + { + "name": "storage", + "description": "The Storage service allows you to manage your project files." + }, + { + "name": "teams", + "description": "The Teams service allows you to group users of your project and to enable them to share read and write access to your project resources" + }, + { + "name": "users", + "description": "The Users service allows you to manage your project users." + }, + { + "name": "sites", + "description": "The Sites Service allows you view, create and manage your web applications." + }, + { + "name": "functions", + "description": "The Functions Service allows you view, create and manage your Cloud Functions." + }, + { + "name": "proxy", + "description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration." + }, + { + "name": "graphql", + "description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL." + }, + { + "name": "console", + "description": "The Console service allows you to interact with console relevant informations." + }, + { + "name": "migrations", + "description": "The Migrations service allows you to migrate third-party data to your Appwrite project." + }, + { + "name": "messaging", + "description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.)." + } + ], + "definitions": { + "any": { + "description": "Any", + "type": "object", + "additionalProperties": true + }, + "documentList": { + "description": "Documents List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of documents documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "documents": { + "type": "array", + "description": "List of documents.", + "items": { + "type": "object", + "$ref": "#\/definitions\/document" + }, + "x-example": "" + } + }, + "required": [ + "total", + "documents" + ] + }, + "collectionList": { + "description": "Collections List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of collections documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "collections": { + "type": "array", + "description": "List of collections.", + "items": { + "type": "object", + "$ref": "#\/definitions\/collection" + }, + "x-example": "" + } + }, + "required": [ + "total", + "collections" + ] + }, + "databaseList": { + "description": "Databases List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of databases documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "databases": { + "type": "array", + "description": "List of databases.", + "items": { + "type": "object", + "$ref": "#\/definitions\/database" + }, + "x-example": "" + } + }, + "required": [ + "total", + "databases" + ] + }, + "indexList": { + "description": "Indexes List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of indexes documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "indexes": { + "type": "array", + "description": "List of indexes.", + "items": { + "type": "object", + "$ref": "#\/definitions\/index" + }, + "x-example": "" + } + }, + "required": [ + "total", + "indexes" + ] + }, + "userList": { + "description": "Users List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of users documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "users": { + "type": "array", + "description": "List of users.", + "items": { + "type": "object", + "$ref": "#\/definitions\/user" + }, + "x-example": "" + } + }, + "required": [ + "total", + "users" + ] + }, + "sessionList": { + "description": "Sessions List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of sessions documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "sessions": { + "type": "array", + "description": "List of sessions.", + "items": { + "type": "object", + "$ref": "#\/definitions\/session" + }, + "x-example": "" + } + }, + "required": [ + "total", + "sessions" + ] + }, + "identityList": { + "description": "Identities List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of identities documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "identities": { + "type": "array", + "description": "List of identities.", + "items": { + "type": "object", + "$ref": "#\/definitions\/identity" + }, + "x-example": "" + } + }, + "required": [ + "total", + "identities" + ] + }, + "logList": { + "description": "Logs List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of logs documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "logs": { + "type": "array", + "description": "List of logs.", + "items": { + "type": "object", + "$ref": "#\/definitions\/log" + }, + "x-example": "" + } + }, + "required": [ + "total", + "logs" + ] + }, + "fileList": { + "description": "Files List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of files documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "files": { + "type": "array", + "description": "List of files.", + "items": { + "type": "object", + "$ref": "#\/definitions\/file" + }, + "x-example": "" + } + }, + "required": [ + "total", + "files" + ] + }, + "bucketList": { + "description": "Buckets List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of buckets documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "buckets": { + "type": "array", + "description": "List of buckets.", + "items": { + "type": "object", + "$ref": "#\/definitions\/bucket" + }, + "x-example": "" + } + }, + "required": [ + "total", + "buckets" + ] + }, + "resourceTokenList": { + "description": "Resource Tokens List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of tokens documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "tokens": { + "type": "array", + "description": "List of tokens.", + "items": { + "type": "object", + "$ref": "#\/definitions\/resourceToken" + }, + "x-example": "" + } + }, + "required": [ + "total", + "tokens" + ] + }, + "teamList": { + "description": "Teams List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of teams documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "teams": { + "type": "array", + "description": "List of teams.", + "items": { + "type": "object", + "$ref": "#\/definitions\/team" + }, + "x-example": "" + } + }, + "required": [ + "total", + "teams" + ] + }, + "membershipList": { + "description": "Memberships List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of memberships documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "memberships": { + "type": "array", + "description": "List of memberships.", + "items": { + "type": "object", + "$ref": "#\/definitions\/membership" + }, + "x-example": "" + } + }, + "required": [ + "total", + "memberships" + ] + }, + "siteList": { + "description": "Sites List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of sites documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "sites": { + "type": "array", + "description": "List of sites.", + "items": { + "type": "object", + "$ref": "#\/definitions\/site" + }, + "x-example": "" + } + }, + "required": [ + "total", + "sites" + ] + }, + "templateSiteList": { + "description": "Site Templates List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of templates documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "templates": { + "type": "array", + "description": "List of templates.", + "items": { + "type": "object", + "$ref": "#\/definitions\/templateSite" + }, + "x-example": "" + } + }, + "required": [ + "total", + "templates" + ] + }, + "functionList": { + "description": "Functions List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of functions documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "functions": { + "type": "array", + "description": "List of functions.", + "items": { + "type": "object", + "$ref": "#\/definitions\/function" + }, + "x-example": "" + } + }, + "required": [ + "total", + "functions" + ] + }, + "templateFunctionList": { + "description": "Function Templates List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of templates documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "templates": { + "type": "array", + "description": "List of templates.", + "items": { + "type": "object", + "$ref": "#\/definitions\/templateFunction" + }, + "x-example": "" + } + }, + "required": [ + "total", + "templates" + ] + }, + "installationList": { + "description": "Installations List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of installations documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "installations": { + "type": "array", + "description": "List of installations.", + "items": { + "type": "object", + "$ref": "#\/definitions\/installation" + }, + "x-example": "" + } + }, + "required": [ + "total", + "installations" + ] + }, + "providerRepositoryFrameworkList": { + "description": "Framework Provider Repositories List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of frameworkProviderRepositories documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "frameworkProviderRepositories": { + "type": "array", + "description": "List of frameworkProviderRepositories.", + "items": { + "type": "object", + "$ref": "#\/definitions\/providerRepositoryFramework" + }, + "x-example": "" + } + }, + "required": [ + "total", + "frameworkProviderRepositories" + ] + }, + "providerRepositoryRuntimeList": { + "description": "Runtime Provider Repositories List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of runtimeProviderRepositories documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "runtimeProviderRepositories": { + "type": "array", + "description": "List of runtimeProviderRepositories.", + "items": { + "type": "object", + "$ref": "#\/definitions\/providerRepositoryRuntime" + }, + "x-example": "" + } + }, + "required": [ + "total", + "runtimeProviderRepositories" + ] + }, + "branchList": { + "description": "Branches List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of branches documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "branches": { + "type": "array", + "description": "List of branches.", + "items": { + "type": "object", + "$ref": "#\/definitions\/branch" + }, + "x-example": "" + } + }, + "required": [ + "total", + "branches" + ] + }, + "frameworkList": { + "description": "Frameworks List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of frameworks documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "frameworks": { + "type": "array", + "description": "List of frameworks.", + "items": { + "type": "object", + "$ref": "#\/definitions\/framework" + }, + "x-example": "" + } + }, + "required": [ + "total", + "frameworks" + ] + }, + "runtimeList": { + "description": "Runtimes List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of runtimes documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "runtimes": { + "type": "array", + "description": "List of runtimes.", + "items": { + "type": "object", + "$ref": "#\/definitions\/runtime" + }, + "x-example": "" + } + }, + "required": [ + "total", + "runtimes" + ] + }, + "deploymentList": { + "description": "Deployments List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of deployments documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "deployments": { + "type": "array", + "description": "List of deployments.", + "items": { + "type": "object", + "$ref": "#\/definitions\/deployment" + }, + "x-example": "" + } + }, + "required": [ + "total", + "deployments" + ] + }, + "executionList": { + "description": "Executions List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of executions documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "executions": { + "type": "array", + "description": "List of executions.", + "items": { + "type": "object", + "$ref": "#\/definitions\/execution" + }, + "x-example": "" + } + }, + "required": [ + "total", + "executions" + ] + }, + "projectList": { + "description": "Projects List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of projects documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "projects": { + "type": "array", + "description": "List of projects.", + "items": { + "type": "object", + "$ref": "#\/definitions\/project" + }, + "x-example": "" + } + }, + "required": [ + "total", + "projects" + ] + }, + "webhookList": { + "description": "Webhooks List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of webhooks documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "webhooks": { + "type": "array", + "description": "List of webhooks.", + "items": { + "type": "object", + "$ref": "#\/definitions\/webhook" + }, + "x-example": "" + } + }, + "required": [ + "total", + "webhooks" + ] + }, + "keyList": { + "description": "API Keys List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of keys documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "keys": { + "type": "array", + "description": "List of keys.", + "items": { + "type": "object", + "$ref": "#\/definitions\/key" + }, + "x-example": "" + } + }, + "required": [ + "total", + "keys" + ] + }, + "devKeyList": { + "description": "Dev Keys List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of devKeys documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "devKeys": { + "type": "array", + "description": "List of devKeys.", + "items": { + "type": "object", + "$ref": "#\/definitions\/devKey" + }, + "x-example": "" + } + }, + "required": [ + "total", + "devKeys" + ] + }, + "platformList": { + "description": "Platforms List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of platforms documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "platforms": { + "type": "array", + "description": "List of platforms.", + "items": { + "type": "object", + "$ref": "#\/definitions\/platform" + }, + "x-example": "" + } + }, + "required": [ + "total", + "platforms" + ] + }, + "countryList": { + "description": "Countries List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of countries documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "countries": { + "type": "array", + "description": "List of countries.", + "items": { + "type": "object", + "$ref": "#\/definitions\/country" + }, + "x-example": "" + } + }, + "required": [ + "total", + "countries" + ] + }, + "continentList": { + "description": "Continents List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of continents documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "continents": { + "type": "array", + "description": "List of continents.", + "items": { + "type": "object", + "$ref": "#\/definitions\/continent" + }, + "x-example": "" + } + }, + "required": [ + "total", + "continents" + ] + }, + "languageList": { + "description": "Languages List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of languages documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "languages": { + "type": "array", + "description": "List of languages.", + "items": { + "type": "object", + "$ref": "#\/definitions\/language" + }, + "x-example": "" + } + }, + "required": [ + "total", + "languages" + ] + }, + "currencyList": { + "description": "Currencies List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of currencies documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "currencies": { + "type": "array", + "description": "List of currencies.", + "items": { + "type": "object", + "$ref": "#\/definitions\/currency" + }, + "x-example": "" + } + }, + "required": [ + "total", + "currencies" + ] + }, + "phoneList": { + "description": "Phones List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of phones documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "phones": { + "type": "array", + "description": "List of phones.", + "items": { + "type": "object", + "$ref": "#\/definitions\/phone" + }, + "x-example": "" + } + }, + "required": [ + "total", + "phones" + ] + }, + "variableList": { + "description": "Variables List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of variables documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "variables": { + "type": "array", + "description": "List of variables.", + "items": { + "type": "object", + "$ref": "#\/definitions\/variable" + }, + "x-example": "" + } + }, + "required": [ + "total", + "variables" + ] + }, + "proxyRuleList": { + "description": "Rule List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of rules documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "rules": { + "type": "array", + "description": "List of rules.", + "items": { + "type": "object", + "$ref": "#\/definitions\/proxyRule" + }, + "x-example": "" + } + }, + "required": [ + "total", + "rules" + ] + }, + "localeCodeList": { + "description": "Locale codes list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of localeCodes documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "localeCodes": { + "type": "array", + "description": "List of localeCodes.", + "items": { + "type": "object", + "$ref": "#\/definitions\/localeCode" + }, + "x-example": "" + } + }, + "required": [ + "total", + "localeCodes" + ] + }, + "providerList": { + "description": "Provider list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of providers documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "providers": { + "type": "array", + "description": "List of providers.", + "items": { + "type": "object", + "$ref": "#\/definitions\/provider" + }, + "x-example": "" + } + }, + "required": [ + "total", + "providers" + ] + }, + "messageList": { + "description": "Message list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of messages documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "messages": { + "type": "array", + "description": "List of messages.", + "items": { + "type": "object", + "$ref": "#\/definitions\/message" + }, + "x-example": "" + } + }, + "required": [ + "total", + "messages" + ] + }, + "topicList": { + "description": "Topic list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of topics documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "topics": { + "type": "array", + "description": "List of topics.", + "items": { + "type": "object", + "$ref": "#\/definitions\/topic" + }, + "x-example": "" + } + }, + "required": [ + "total", + "topics" + ] + }, + "subscriberList": { + "description": "Subscriber list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of subscribers documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "subscribers": { + "type": "array", + "description": "List of subscribers.", + "items": { + "type": "object", + "$ref": "#\/definitions\/subscriber" + }, + "x-example": "" + } + }, + "required": [ + "total", + "subscribers" + ] + }, + "targetList": { + "description": "Target list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of targets documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "targets": { + "type": "array", + "description": "List of targets.", + "items": { + "type": "object", + "$ref": "#\/definitions\/target" + }, + "x-example": "" + } + }, + "required": [ + "total", + "targets" + ] + }, + "migrationList": { + "description": "Migrations List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of migrations documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "migrations": { + "type": "array", + "description": "List of migrations.", + "items": { + "type": "object", + "$ref": "#\/definitions\/migration" + }, + "x-example": "" + } + }, + "required": [ + "total", + "migrations" + ] + }, + "specificationList": { + "description": "Specifications List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of specifications documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "specifications": { + "type": "array", + "description": "List of specifications.", + "items": { + "type": "object", + "$ref": "#\/definitions\/specification" + }, + "x-example": "" + } + }, + "required": [ + "total", + "specifications" + ] + }, + "vcsContentList": { + "description": "VCS Content List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of contents documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "contents": { + "type": "array", + "description": "List of contents.", + "items": { + "type": "object", + "$ref": "#\/definitions\/vcsContent" + }, + "x-example": "" + } + }, + "required": [ + "total", + "contents" + ] + }, + "database": { + "description": "Database", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Database ID.", + "x-example": "5e5ea5c16897e" + }, + "name": { + "type": "string", + "description": "Database name.", + "x-example": "My Database" + }, + "$createdAt": { + "type": "string", + "description": "Database creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Database update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "enabled": { + "type": "boolean", + "description": "If database is enabled. Can be 'enabled' or 'disabled'. When disabled, the database is inaccessible to users, but remains accessible to Server SDKs using API keys.", + "x-example": false + } + }, + "required": [ + "$id", + "name", + "$createdAt", + "$updatedAt", + "enabled" + ] + }, + "collection": { + "description": "Collection", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Collection ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Collection creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Collection update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Collection permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + }, + "databaseId": { + "type": "string", + "description": "Database ID.", + "x-example": "5e5ea5c16897e" + }, + "name": { + "type": "string", + "description": "Collection name.", + "x-example": "My Collection" + }, + "enabled": { + "type": "boolean", + "description": "Collection enabled. Can be 'enabled' or 'disabled'. When disabled, the collection is inaccessible to users, but remains accessible to Server SDKs using API keys.", + "x-example": false + }, + "documentSecurity": { + "type": "boolean", + "description": "Whether document-level permissions are enabled. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": true + }, + "attributes": { + "type": "array", + "description": "Collection attributes.", + "items": { + "x-anyOf": [ + { + "$ref": "#\/definitions\/attributeBoolean" + }, + { + "$ref": "#\/definitions\/attributeInteger" + }, + { + "$ref": "#\/definitions\/attributeFloat" + }, + { + "$ref": "#\/definitions\/attributeEmail" + }, + { + "$ref": "#\/definitions\/attributeEnum" + }, + { + "$ref": "#\/definitions\/attributeUrl" + }, + { + "$ref": "#\/definitions\/attributeIp" + }, + { + "$ref": "#\/definitions\/attributeDatetime" + }, + { + "$ref": "#\/definitions\/attributeRelationship" + }, + { + "$ref": "#\/definitions\/attributeString" + } + ] + }, + "x-example": {} + }, + "indexes": { + "type": "array", + "description": "Collection indexes.", + "items": { + "type": "object", + "$ref": "#\/definitions\/index" + }, + "x-example": {} + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "$permissions", + "databaseId", + "name", + "enabled", + "documentSecurity", + "attributes", + "indexes" + ] + }, + "attributeList": { + "description": "Attributes List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of attributes in the given collection.", + "x-example": 5, + "format": "int32" + }, + "attributes": { + "type": "array", + "description": "List of attributes.", + "items": { + "x-anyOf": [ + { + "$ref": "#\/definitions\/attributeBoolean" + }, + { + "$ref": "#\/definitions\/attributeInteger" + }, + { + "$ref": "#\/definitions\/attributeFloat" + }, + { + "$ref": "#\/definitions\/attributeEmail" + }, + { + "$ref": "#\/definitions\/attributeEnum" + }, + { + "$ref": "#\/definitions\/attributeUrl" + }, + { + "$ref": "#\/definitions\/attributeIp" + }, + { + "$ref": "#\/definitions\/attributeDatetime" + }, + { + "$ref": "#\/definitions\/attributeRelationship" + }, + { + "$ref": "#\/definitions\/attributeString" + } + ] + }, + "x-example": "" + } + }, + "required": [ + "total", + "attributes" + ] + }, + "attributeString": { + "description": "AttributeString", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "fullName" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "size": { + "type": "integer", + "description": "Attribute size.", + "x-example": 128, + "format": "int32" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "default", + "x-nullable": true + }, + "encrypt": { + "type": "boolean", + "description": "Defines whether this attribute is encrypted or not.", + "x-example": false, + "x-nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "size" + ] + }, + "attributeInteger": { + "description": "AttributeInteger", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "count" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "integer" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "min": { + "type": "integer", + "description": "Minimum value to enforce for new documents.", + "x-example": 1, + "format": "int32", + "x-nullable": true + }, + "max": { + "type": "integer", + "description": "Maximum value to enforce for new documents.", + "x-example": 10, + "format": "int32", + "x-nullable": true + }, + "default": { + "type": "integer", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": 10, + "format": "int32", + "x-nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt" + ] + }, + "attributeFloat": { + "description": "AttributeFloat", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "percentageCompleted" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "double" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "min": { + "type": "number", + "description": "Minimum value to enforce for new documents.", + "x-example": 1.5, + "format": "double", + "x-nullable": true + }, + "max": { + "type": "number", + "description": "Maximum value to enforce for new documents.", + "x-example": 10.5, + "format": "double", + "x-nullable": true + }, + "default": { + "type": "number", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": 2.5, + "format": "double", + "x-nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt" + ] + }, + "attributeBoolean": { + "description": "AttributeBoolean", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "isEnabled" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "boolean" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "default": { + "type": "boolean", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": false, + "x-nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt" + ] + }, + "attributeEmail": { + "description": "AttributeEmail", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "userEmail" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "format": { + "type": "string", + "description": "String format.", + "x-example": "email" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "default@example.com", + "x-nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "format" + ] + }, + "attributeEnum": { + "description": "AttributeEnum", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "status" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "elements": { + "type": "array", + "description": "Array of elements in enumerated type.", + "items": { + "type": "string" + }, + "x-example": "element" + }, + "format": { + "type": "string", + "description": "String format.", + "x-example": "enum" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "element", + "x-nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "elements", + "format" + ] + }, + "attributeIp": { + "description": "AttributeIP", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "ipAddress" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "format": { + "type": "string", + "description": "String format.", + "x-example": "ip" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "192.0.2.0", + "x-nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "format" + ] + }, + "attributeUrl": { + "description": "AttributeURL", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "githubUrl" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "format": { + "type": "string", + "description": "String format.", + "x-example": "url" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "http:\/\/example.com", + "x-nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "format" + ] + }, + "attributeDatetime": { + "description": "AttributeDatetime", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "birthDay" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "datetime" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "format": { + "type": "string", + "description": "ISO 8601 format.", + "x-example": "datetime" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Only null is optional", + "x-example": "2020-10-15T06:38:00.000+00:00", + "x-nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "format" + ] + }, + "attributeRelationship": { + "description": "AttributeRelationship", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "fullName" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "relatedCollection": { + "type": "string", + "description": "The ID of the related collection.", + "x-example": "collection" + }, + "relationType": { + "type": "string", + "description": "The type of the relationship.", + "x-example": "oneToOne|oneToMany|manyToOne|manyToMany" + }, + "twoWay": { + "type": "boolean", + "description": "Is the relationship two-way?", + "x-example": false + }, + "twoWayKey": { + "type": "string", + "description": "The key of the two-way relationship.", + "x-example": "string" + }, + "onDelete": { + "type": "string", + "description": "How deleting the parent document will propagate to child documents.", + "x-example": "restrict|cascade|setNull" + }, + "side": { + "type": "string", + "description": "Whether this is the parent or child side of the relationship", + "x-example": "parent|child" + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "relatedCollection", + "relationType", + "twoWay", + "twoWayKey", + "onDelete", + "side" + ] + }, + "index": { + "description": "Index", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Index Key.", + "x-example": "index1" + }, + "type": { + "type": "string", + "description": "Index type.", + "x-example": "primary" + }, + "status": { + "type": "string", + "description": "Index status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an index.", + "x-example": "string" + }, + "attributes": { + "type": "array", + "description": "Index attributes.", + "items": { + "type": "string" + }, + "x-example": [] + }, + "lengths": { + "type": "array", + "description": "Index attributes length.", + "items": { + "type": "integer", + "format": "int32" + }, + "x-example": [] + }, + "orders": { + "type": "array", + "description": "Index orders.", + "items": { + "type": "string" + }, + "x-example": [], + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Index creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Index update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "key", + "type", + "status", + "error", + "attributes", + "lengths", + "$createdAt", + "$updatedAt" + ] + }, + "document": { + "description": "Document", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Document ID.", + "x-example": "5e5ea5c16897e" + }, + "$sequence": { + "type": "integer", + "description": "Document automatically incrementing ID.", + "x-example": 1, + "format": "int32" + }, + "$collectionId": { + "type": "string", + "description": "Collection ID.", + "x-example": "5e5ea5c15117e" + }, + "$databaseId": { + "type": "string", + "description": "Database ID.", + "x-example": "5e5ea5c15117e" + }, + "$createdAt": { + "type": "string", + "description": "Document creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Document update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Document permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + } + }, + "additionalProperties": true, + "required": [ + "$id", + "$sequence", + "$collectionId", + "$databaseId", + "$createdAt", + "$updatedAt", + "$permissions" + ] + }, + "log": { + "description": "Log", + "type": "object", + "properties": { + "event": { + "type": "string", + "description": "Event name.", + "x-example": "account.sessions.create" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "610fc2f985ee0" + }, + "userEmail": { + "type": "string", + "description": "User Email.", + "x-example": "john@appwrite.io" + }, + "userName": { + "type": "string", + "description": "User Name.", + "x-example": "John Doe" + }, + "mode": { + "type": "string", + "description": "API mode when event triggered.", + "x-example": "admin" + }, + "ip": { + "type": "string", + "description": "IP session in use when the session was created.", + "x-example": "127.0.0.1" + }, + "time": { + "type": "string", + "description": "Log creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "osCode": { + "type": "string", + "description": "Operating system code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/os.json).", + "x-example": "Mac" + }, + "osName": { + "type": "string", + "description": "Operating system name.", + "x-example": "Mac" + }, + "osVersion": { + "type": "string", + "description": "Operating system version.", + "x-example": "Mac" + }, + "clientType": { + "type": "string", + "description": "Client type.", + "x-example": "browser" + }, + "clientCode": { + "type": "string", + "description": "Client code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/clients.json).", + "x-example": "CM" + }, + "clientName": { + "type": "string", + "description": "Client name.", + "x-example": "Chrome Mobile iOS" + }, + "clientVersion": { + "type": "string", + "description": "Client version.", + "x-example": "84.0" + }, + "clientEngine": { + "type": "string", + "description": "Client engine name.", + "x-example": "WebKit" + }, + "clientEngineVersion": { + "type": "string", + "description": "Client engine name.", + "x-example": "605.1.15" + }, + "deviceName": { + "type": "string", + "description": "Device name.", + "x-example": "smartphone" + }, + "deviceBrand": { + "type": "string", + "description": "Device brand name.", + "x-example": "Google" + }, + "deviceModel": { + "type": "string", + "description": "Device model name.", + "x-example": "Nexus 5" + }, + "countryCode": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + }, + "countryName": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + } + }, + "required": [ + "event", + "userId", + "userEmail", + "userName", + "mode", + "ip", + "time", + "osCode", + "osName", + "osVersion", + "clientType", + "clientCode", + "clientName", + "clientVersion", + "clientEngine", + "clientEngineVersion", + "deviceName", + "deviceBrand", + "deviceModel", + "countryCode", + "countryName" + ] + }, + "user": { + "description": "User", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "User creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "User update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "User name.", + "x-example": "John Doe" + }, + "password": { + "type": "string", + "description": "Hashed user password.", + "x-example": "$argon2id$v=19$m=2048,t=4,p=3$aUZjLnliVWRINmFNTWMudg$5S+x+7uA31xFnrHFT47yFwcJeaP0w92L\/4LdgrVRXxE", + "x-nullable": true + }, + "hash": { + "type": "string", + "description": "Password hashing algorithm.", + "x-example": "argon2", + "x-nullable": true + }, + "hashOptions": { + "type": "object", + "description": "Password hashing algorithm configuration.", + "x-example": {}, + "items": { + "x-oneOf": [ + { + "$ref": "#\/definitions\/algoArgon2" + }, + { + "$ref": "#\/definitions\/algoScrypt" + }, + { + "$ref": "#\/definitions\/algoScryptModified" + }, + { + "$ref": "#\/definitions\/algoBcrypt" + }, + { + "$ref": "#\/definitions\/algoPhpass" + }, + { + "$ref": "#\/definitions\/algoSha" + }, + { + "$ref": "#\/definitions\/algoMd5" + } + ] + }, + "x-nullable": true + }, + "registration": { + "type": "string", + "description": "User registration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "boolean", + "description": "User status. Pass `true` for enabled and `false` for disabled.", + "x-example": true + }, + "labels": { + "type": "array", + "description": "Labels for the user.", + "items": { + "type": "string" + }, + "x-example": [ + "vip" + ] + }, + "passwordUpdate": { + "type": "string", + "description": "Password update time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "email": { + "type": "string", + "description": "User email address.", + "x-example": "john@appwrite.io" + }, + "phone": { + "type": "string", + "description": "User phone number in E.164 format.", + "x-example": "+4930901820" + }, + "emailVerification": { + "type": "boolean", + "description": "Email verification status.", + "x-example": true + }, + "phoneVerification": { + "type": "boolean", + "description": "Phone verification status.", + "x-example": true + }, + "mfa": { + "type": "boolean", + "description": "Multi factor authentication status.", + "x-example": true + }, + "prefs": { + "type": "object", + "description": "User preferences as a key-value object", + "x-example": { + "theme": "pink", + "timezone": "UTC" + }, + "items": { + "type": "object", + "$ref": "#\/definitions\/preferences" + } + }, + "targets": { + "type": "array", + "description": "A user-owned message receiver. A single user may have multiple e.g. emails, phones, and a browser. Each target is registered with a single provider.", + "items": { + "type": "object", + "$ref": "#\/definitions\/target" + }, + "x-example": [] + }, + "accessedAt": { + "type": "string", + "description": "Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "registration", + "status", + "labels", + "passwordUpdate", + "email", + "phone", + "emailVerification", + "phoneVerification", + "mfa", + "prefs", + "targets", + "accessedAt" + ] + }, + "algoMd5": { + "description": "AlgoMD5", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "md5" + } + }, + "required": [ + "type" + ] + }, + "algoSha": { + "description": "AlgoSHA", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "sha" + } + }, + "required": [ + "type" + ] + }, + "algoPhpass": { + "description": "AlgoPHPass", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "phpass" + } + }, + "required": [ + "type" + ] + }, + "algoBcrypt": { + "description": "AlgoBcrypt", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "bcrypt" + } + }, + "required": [ + "type" + ] + }, + "algoScrypt": { + "description": "AlgoScrypt", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "scrypt" + }, + "costCpu": { + "type": "integer", + "description": "CPU complexity of computed hash.", + "x-example": 8, + "format": "int32" + }, + "costMemory": { + "type": "integer", + "description": "Memory complexity of computed hash.", + "x-example": 14, + "format": "int32" + }, + "costParallel": { + "type": "integer", + "description": "Parallelization of computed hash.", + "x-example": 1, + "format": "int32" + }, + "length": { + "type": "integer", + "description": "Length used to compute hash.", + "x-example": 64, + "format": "int32" + } + }, + "required": [ + "type", + "costCpu", + "costMemory", + "costParallel", + "length" + ] + }, + "algoScryptModified": { + "description": "AlgoScryptModified", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "scryptMod" + }, + "salt": { + "type": "string", + "description": "Salt used to compute hash.", + "x-example": "UxLMreBr6tYyjQ==" + }, + "saltSeparator": { + "type": "string", + "description": "Separator used to compute hash.", + "x-example": "Bw==" + }, + "signerKey": { + "type": "string", + "description": "Key used to compute hash.", + "x-example": "XyEKE9RcTDeLEsL\/RjwPDBv\/RqDl8fb3gpYEOQaPihbxf1ZAtSOHCjuAAa7Q3oHpCYhXSN9tizHgVOwn6krflQ==" + } + }, + "required": [ + "type", + "salt", + "saltSeparator", + "signerKey" + ] + }, + "algoArgon2": { + "description": "AlgoArgon2", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "argon2" + }, + "memoryCost": { + "type": "integer", + "description": "Memory used to compute hash.", + "x-example": 65536, + "format": "int32" + }, + "timeCost": { + "type": "integer", + "description": "Amount of time consumed to compute hash", + "x-example": 4, + "format": "int32" + }, + "threads": { + "type": "integer", + "description": "Number of threads used to compute hash.", + "x-example": 3, + "format": "int32" + } + }, + "required": [ + "type", + "memoryCost", + "timeCost", + "threads" + ] + }, + "preferences": { + "description": "Preferences", + "type": "object", + "additionalProperties": true + }, + "session": { + "description": "Session", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Session ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Session creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Session update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5bb8c16897e" + }, + "expire": { + "type": "string", + "description": "Session expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "provider": { + "type": "string", + "description": "Session Provider.", + "x-example": "email" + }, + "providerUid": { + "type": "string", + "description": "Session Provider User ID.", + "x-example": "user@example.com" + }, + "providerAccessToken": { + "type": "string", + "description": "Session Provider Access Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + }, + "providerAccessTokenExpiry": { + "type": "string", + "description": "The date of when the access token expires in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "providerRefreshToken": { + "type": "string", + "description": "Session Provider Refresh Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + }, + "ip": { + "type": "string", + "description": "IP in use when the session was created.", + "x-example": "127.0.0.1" + }, + "osCode": { + "type": "string", + "description": "Operating system code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/os.json).", + "x-example": "Mac" + }, + "osName": { + "type": "string", + "description": "Operating system name.", + "x-example": "Mac" + }, + "osVersion": { + "type": "string", + "description": "Operating system version.", + "x-example": "Mac" + }, + "clientType": { + "type": "string", + "description": "Client type.", + "x-example": "browser" + }, + "clientCode": { + "type": "string", + "description": "Client code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/clients.json).", + "x-example": "CM" + }, + "clientName": { + "type": "string", + "description": "Client name.", + "x-example": "Chrome Mobile iOS" + }, + "clientVersion": { + "type": "string", + "description": "Client version.", + "x-example": "84.0" + }, + "clientEngine": { + "type": "string", + "description": "Client engine name.", + "x-example": "WebKit" + }, + "clientEngineVersion": { + "type": "string", + "description": "Client engine name.", + "x-example": "605.1.15" + }, + "deviceName": { + "type": "string", + "description": "Device name.", + "x-example": "smartphone" + }, + "deviceBrand": { + "type": "string", + "description": "Device brand name.", + "x-example": "Google" + }, + "deviceModel": { + "type": "string", + "description": "Device model name.", + "x-example": "Nexus 5" + }, + "countryCode": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + }, + "countryName": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + }, + "current": { + "type": "boolean", + "description": "Returns true if this the current user session.", + "x-example": true + }, + "factors": { + "type": "array", + "description": "Returns a list of active session factors.", + "items": { + "type": "string" + }, + "x-example": [ + "email" + ] + }, + "secret": { + "type": "string", + "description": "Secret used to authenticate the user. Only included if the request was made with an API key", + "x-example": "5e5bb8c16897e" + }, + "mfaUpdatedAt": { + "type": "string", + "description": "Most recent date in ISO 8601 format when the session successfully passed MFA challenge.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "userId", + "expire", + "provider", + "providerUid", + "providerAccessToken", + "providerAccessTokenExpiry", + "providerRefreshToken", + "ip", + "osCode", + "osName", + "osVersion", + "clientType", + "clientCode", + "clientName", + "clientVersion", + "clientEngine", + "clientEngineVersion", + "deviceName", + "deviceBrand", + "deviceModel", + "countryCode", + "countryName", + "current", + "factors", + "secret", + "mfaUpdatedAt" + ] + }, + "identity": { + "description": "Identity", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Identity ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Identity creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Identity update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5bb8c16897e" + }, + "provider": { + "type": "string", + "description": "Identity Provider.", + "x-example": "email" + }, + "providerUid": { + "type": "string", + "description": "ID of the User in the Identity Provider.", + "x-example": "5e5bb8c16897e" + }, + "providerEmail": { + "type": "string", + "description": "Email of the User in the Identity Provider.", + "x-example": "user@example.com" + }, + "providerAccessToken": { + "type": "string", + "description": "Identity Provider Access Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + }, + "providerAccessTokenExpiry": { + "type": "string", + "description": "The date of when the access token expires in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "providerRefreshToken": { + "type": "string", + "description": "Identity Provider Refresh Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "userId", + "provider", + "providerUid", + "providerEmail", + "providerAccessToken", + "providerAccessTokenExpiry", + "providerRefreshToken" + ] + }, + "token": { + "description": "Token", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Token ID.", + "x-example": "bb8ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Token creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c168bb8" + }, + "secret": { + "type": "string", + "description": "Token secret key. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.", + "x-example": "" + }, + "expire": { + "type": "string", + "description": "Token expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "phrase": { + "type": "string", + "description": "Security phrase of a token. Empty if security phrase was not requested when creating a token. It includes randomly generated phrase which is also sent in the external resource such as email.", + "x-example": "Golden Fox" + } + }, + "required": [ + "$id", + "$createdAt", + "userId", + "secret", + "expire", + "phrase" + ] + }, + "jwt": { + "description": "JWT", + "type": "object", + "properties": { + "jwt": { + "type": "string", + "description": "JWT encoded string.", + "x-example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + } + }, + "required": [ + "jwt" + ] + }, + "locale": { + "description": "Locale", + "type": "object", + "properties": { + "ip": { + "type": "string", + "description": "User IP address.", + "x-example": "127.0.0.1" + }, + "countryCode": { + "type": "string", + "description": "Country code in [ISO 3166-1](http:\/\/en.wikipedia.org\/wiki\/ISO_3166-1) two-character format", + "x-example": "US" + }, + "country": { + "type": "string", + "description": "Country name. This field support localization.", + "x-example": "United States" + }, + "continentCode": { + "type": "string", + "description": "Continent code. A two character continent code \"AF\" for Africa, \"AN\" for Antarctica, \"AS\" for Asia, \"EU\" for Europe, \"NA\" for North America, \"OC\" for Oceania, and \"SA\" for South America.", + "x-example": "NA" + }, + "continent": { + "type": "string", + "description": "Continent name. This field support localization.", + "x-example": "North America" + }, + "eu": { + "type": "boolean", + "description": "True if country is part of the European Union.", + "x-example": false + }, + "currency": { + "type": "string", + "description": "Currency code in [ISO 4217-1](http:\/\/en.wikipedia.org\/wiki\/ISO_4217) three-character format", + "x-example": "USD" + } + }, + "required": [ + "ip", + "countryCode", + "country", + "continentCode", + "continent", + "eu", + "currency" + ] + }, + "localeCode": { + "description": "LocaleCode", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Locale codes in [ISO 639-1](https:\/\/en.wikipedia.org\/wiki\/List_of_ISO_639-1_codes)", + "x-example": "en-us" + }, + "name": { + "type": "string", + "description": "Locale name", + "x-example": "US" + } + }, + "required": [ + "code", + "name" + ] + }, + "file": { + "description": "File", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "File ID.", + "x-example": "5e5ea5c16897e" + }, + "bucketId": { + "type": "string", + "description": "Bucket ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "File creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "File update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "File permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + }, + "name": { + "type": "string", + "description": "File name.", + "x-example": "Pink.png" + }, + "signature": { + "type": "string", + "description": "File MD5 signature.", + "x-example": "5d529fd02b544198ae075bd57c1762bb" + }, + "mimeType": { + "type": "string", + "description": "File mime type.", + "x-example": "image\/png" + }, + "sizeOriginal": { + "type": "integer", + "description": "File original size in bytes.", + "x-example": 17890, + "format": "int32" + }, + "chunksTotal": { + "type": "integer", + "description": "Total number of chunks available", + "x-example": 17890, + "format": "int32" + }, + "chunksUploaded": { + "type": "integer", + "description": "Total number of chunks uploaded", + "x-example": 17890, + "format": "int32" + } + }, + "required": [ + "$id", + "bucketId", + "$createdAt", + "$updatedAt", + "$permissions", + "name", + "signature", + "mimeType", + "sizeOriginal", + "chunksTotal", + "chunksUploaded" + ] + }, + "bucket": { + "description": "Bucket", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Bucket ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Bucket creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Bucket update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Bucket permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + }, + "fileSecurity": { + "type": "boolean", + "description": "Whether file-level security is enabled. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": true + }, + "name": { + "type": "string", + "description": "Bucket name.", + "x-example": "Documents" + }, + "enabled": { + "type": "boolean", + "description": "Bucket enabled.", + "x-example": false + }, + "maximumFileSize": { + "type": "integer", + "description": "Maximum file size supported.", + "x-example": 100, + "format": "int32" + }, + "allowedFileExtensions": { + "type": "array", + "description": "Allowed file extensions.", + "items": { + "type": "string" + }, + "x-example": [ + "jpg", + "png" + ] + }, + "compression": { + "type": "string", + "description": "Compression algorithm choosen for compression. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).", + "x-example": "gzip" + }, + "encryption": { + "type": "boolean", + "description": "Bucket is encrypted.", + "x-example": false + }, + "antivirus": { + "type": "boolean", + "description": "Virus scanning is enabled.", + "x-example": false + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "$permissions", + "fileSecurity", + "name", + "enabled", + "maximumFileSize", + "allowedFileExtensions", + "compression", + "encryption", + "antivirus" + ] + }, + "resourceToken": { + "description": "ResourceToken", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Token ID.", + "x-example": "bb8ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Token creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "resourceId": { + "type": "string", + "description": "Resource ID.", + "x-example": "5e5ea5c168bb8:5e5ea5c168bb8" + }, + "resourceType": { + "type": "string", + "description": "Resource type.", + "x-example": "files" + }, + "expire": { + "type": "string", + "description": "Token expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "secret": { + "type": "string", + "description": "JWT encoded string.", + "x-example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + }, + "accessedAt": { + "type": "string", + "description": "Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "resourceId", + "resourceType", + "expire", + "secret", + "accessedAt" + ] + }, + "team": { + "description": "Team", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Team ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Team creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Team update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Team name.", + "x-example": "VIP" + }, + "total": { + "type": "integer", + "description": "Total number of team members.", + "x-example": 7, + "format": "int32" + }, + "prefs": { + "type": "object", + "description": "Team preferences as a key-value object", + "x-example": { + "theme": "pink", + "timezone": "UTC" + }, + "items": { + "type": "object", + "$ref": "#\/definitions\/preferences" + } + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "total", + "prefs" + ] + }, + "membership": { + "description": "Membership", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Membership ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Membership creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Membership update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c16897e" + }, + "userName": { + "type": "string", + "description": "User name. Hide this attribute by toggling membership privacy in the Console.", + "x-example": "John Doe" + }, + "userEmail": { + "type": "string", + "description": "User email address. Hide this attribute by toggling membership privacy in the Console.", + "x-example": "john@appwrite.io" + }, + "teamId": { + "type": "string", + "description": "Team ID.", + "x-example": "5e5ea5c16897e" + }, + "teamName": { + "type": "string", + "description": "Team name.", + "x-example": "VIP" + }, + "invited": { + "type": "string", + "description": "Date, the user has been invited to join the team in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "joined": { + "type": "string", + "description": "Date, the user has accepted the invitation to join the team in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "confirm": { + "type": "boolean", + "description": "User confirmation status, true if the user has joined the team or false otherwise.", + "x-example": false + }, + "mfa": { + "type": "boolean", + "description": "Multi factor authentication status, true if the user has MFA enabled or false otherwise. Hide this attribute by toggling membership privacy in the Console.", + "x-example": false + }, + "roles": { + "type": "array", + "description": "User list of roles", + "items": { + "type": "string" + }, + "x-example": [ + "owner" + ] + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "userId", + "userName", + "userEmail", + "teamId", + "teamName", + "invited", + "joined", + "confirm", + "mfa", + "roles" + ] + }, + "site": { + "description": "Site", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Site ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Site creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Site update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Site name.", + "x-example": "My Site" + }, + "enabled": { + "type": "boolean", + "description": "Site enabled.", + "x-example": false + }, + "live": { + "type": "boolean", + "description": "Is the site deployed with the latest configuration? This is set to false if you've changed an environment variables, entrypoint, commands, or other settings that needs redeploy to be applied. When the value is false, redeploy the site to update it with the latest configuration.", + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.", + "x-example": false + }, + "framework": { + "type": "string", + "description": "Site framework.", + "x-example": "react" + }, + "deploymentId": { + "type": "string", + "description": "Site's active deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "deploymentCreatedAt": { + "type": "string", + "description": "Active deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "deploymentScreenshotLight": { + "type": "string", + "description": "Screenshot of active deployment with light theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "deploymentScreenshotDark": { + "type": "string", + "description": "Screenshot of active deployment with dark theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentId": { + "type": "string", + "description": "Site's latest deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentCreatedAt": { + "type": "string", + "description": "Latest deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentStatus": { + "type": "string", + "description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, + "vars": { + "type": "array", + "description": "Site variables.", + "items": { + "type": "object", + "$ref": "#\/definitions\/variable" + }, + "x-example": [] + }, + "timeout": { + "type": "integer", + "description": "Site request timeout in seconds.", + "x-example": 300, + "format": "int32" + }, + "installCommand": { + "type": "string", + "description": "The install command used to install the site dependencies.", + "x-example": "npm install" + }, + "buildCommand": { + "type": "string", + "description": "The build command used to build the site.", + "x-example": "npm run build" + }, + "outputDirectory": { + "type": "string", + "description": "The directory where the site build output is located.", + "x-example": "build" + }, + "installationId": { + "type": "string", + "description": "Site VCS (Version Control System) installation id.", + "x-example": "6m40at4ejk5h2u9s1hboo" + }, + "providerRepositoryId": { + "type": "string", + "description": "VCS (Version Control System) Repository ID", + "x-example": "appwrite" + }, + "providerBranch": { + "type": "string", + "description": "VCS (Version Control System) branch name", + "x-example": "main" + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to site in VCS (Version Control System) repository", + "x-example": "sites\/helloWorld" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is VCS (Version Control System) connection is in silent mode? When in silence mode, no comments will be posted on the repository pull or merge requests", + "x-example": false + }, + "specification": { + "type": "string", + "description": "Machine specification for builds and executions.", + "x-example": "s-1vcpu-512mb" + }, + "buildRuntime": { + "type": "string", + "description": "Site build runtime.", + "x-example": "node-22" + }, + "adapter": { + "type": "string", + "description": "Site framework adapter.", + "x-example": "static" + }, + "fallbackFile": { + "type": "string", + "description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.", + "x-example": "index.html" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "enabled", + "live", + "logging", + "framework", + "deploymentId", + "deploymentCreatedAt", + "deploymentScreenshotLight", + "deploymentScreenshotDark", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", + "vars", + "timeout", + "installCommand", + "buildCommand", + "outputDirectory", + "installationId", + "providerRepositoryId", + "providerBranch", + "providerRootDirectory", + "providerSilentMode", + "specification", + "buildRuntime", + "adapter", + "fallbackFile" + ] + }, + "templateSite": { + "description": "Template Site", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Site Template ID.", + "x-example": "starter" + }, + "name": { + "type": "string", + "description": "Site Template Name.", + "x-example": "Starter site" + }, + "tagline": { + "type": "string", + "description": "Short description of template", + "x-example": "Minimal web app integrating with Appwrite." + }, + "demoUrl": { + "type": "string", + "description": "URL hosting a template demo.", + "x-example": "https:\/\/nextjs-starter.appwrite.network\/" + }, + "screenshotDark": { + "type": "string", + "description": "File URL with preview screenshot in dark theme preference.", + "x-example": "https:\/\/cloud.appwrite.io\/images\/sites\/templates\/template-for-blog-dark.png" + }, + "screenshotLight": { + "type": "string", + "description": "File URL with preview screenshot in light theme preference.", + "x-example": "https:\/\/cloud.appwrite.io\/images\/sites\/templates\/template-for-blog-light.png" + }, + "useCases": { + "type": "array", + "description": "Site use cases.", + "items": { + "type": "string" + }, + "x-example": "Starter" + }, + "frameworks": { + "type": "array", + "description": "List of frameworks that can be used with this template.", + "items": { + "type": "object", + "$ref": "#\/definitions\/templateFramework" + }, + "x-example": [] + }, + "vcsProvider": { + "type": "string", + "description": "VCS (Version Control System) Provider.", + "x-example": "github" + }, + "providerRepositoryId": { + "type": "string", + "description": "VCS (Version Control System) Repository ID", + "x-example": "templates" + }, + "providerOwner": { + "type": "string", + "description": "VCS (Version Control System) Owner.", + "x-example": "appwrite" + }, + "providerVersion": { + "type": "string", + "description": "VCS (Version Control System) branch version (tag).", + "x-example": "main" + }, + "variables": { + "type": "array", + "description": "Site variables.", + "items": { + "type": "object", + "$ref": "#\/definitions\/templateVariable" + }, + "x-example": [] + } + }, + "required": [ + "key", + "name", + "tagline", + "demoUrl", + "screenshotDark", + "screenshotLight", + "useCases", + "frameworks", + "vcsProvider", + "providerRepositoryId", + "providerOwner", + "providerVersion", + "variables" + ] + }, + "templateFramework": { + "description": "Template Framework", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Parent framework key.", + "x-example": "sveltekit" + }, + "name": { + "type": "string", + "description": "Framework Name.", + "x-example": "SvelteKit" + }, + "installCommand": { + "type": "string", + "description": "The install command used to install the dependencies.", + "x-example": "npm install" + }, + "buildCommand": { + "type": "string", + "description": "The build command used to build the deployment.", + "x-example": "npm run build" + }, + "outputDirectory": { + "type": "string", + "description": "The output directory to store the build output.", + "x-example": ".\/build" + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to site in VCS (Version Control System) repository", + "x-example": ".\/svelte-kit\/starter" + }, + "buildRuntime": { + "type": "string", + "description": "Runtime used during build step of template.", + "x-example": "node-22" + }, + "adapter": { + "type": "string", + "description": "Site framework runtime", + "x-example": "ssr" + }, + "fallbackFile": { + "type": "string", + "description": "Fallback file for SPA. Only relevant for static serve runtime.", + "x-example": "index.html" + } + }, + "required": [ + "key", + "name", + "installCommand", + "buildCommand", + "outputDirectory", + "providerRootDirectory", + "buildRuntime", + "adapter", + "fallbackFile" + ] + }, + "function": { + "description": "Function", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Function ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Function creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Function update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "execute": { + "type": "array", + "description": "Execution permissions.", + "items": { + "type": "string" + }, + "x-example": "users" + }, + "name": { + "type": "string", + "description": "Function name.", + "x-example": "My Function" + }, + "enabled": { + "type": "boolean", + "description": "Function enabled.", + "x-example": false + }, + "live": { + "type": "boolean", + "description": "Is the function deployed with the latest configuration? This is set to false if you've changed an environment variables, entrypoint, commands, or other settings that needs redeploy to be applied. When the value is false, redeploy the function to update it with the latest configuration.", + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", + "x-example": false + }, + "runtime": { + "type": "string", + "description": "Function execution and build runtime.", + "x-example": "python-3.8" + }, + "deploymentId": { + "type": "string", + "description": "Function's active deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "deploymentCreatedAt": { + "type": "string", + "description": "Active deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentId": { + "type": "string", + "description": "Function's latest deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentCreatedAt": { + "type": "string", + "description": "Latest deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentStatus": { + "type": "string", + "description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, + "scopes": { + "type": "array", + "description": "Allowed permission scopes.", + "items": { + "type": "string" + }, + "x-example": "users.read" + }, + "vars": { + "type": "array", + "description": "Function variables.", + "items": { + "type": "object", + "$ref": "#\/definitions\/variable" + }, + "x-example": [] + }, + "events": { + "type": "array", + "description": "Function trigger events.", + "items": { + "type": "string" + }, + "x-example": "account.create" + }, + "schedule": { + "type": "string", + "description": "Function execution schedule in CRON format.", + "x-example": "5 4 * * *" + }, + "timeout": { + "type": "integer", + "description": "Function execution timeout in seconds.", + "x-example": 300, + "format": "int32" + }, + "entrypoint": { + "type": "string", + "description": "The entrypoint file used to execute the deployment.", + "x-example": "index.js" + }, + "commands": { + "type": "string", + "description": "The build command used to build the deployment.", + "x-example": "npm install" + }, + "version": { + "type": "string", + "description": "Version of Open Runtimes used for the function.", + "x-example": "v2" + }, + "installationId": { + "type": "string", + "description": "Function VCS (Version Control System) installation id.", + "x-example": "6m40at4ejk5h2u9s1hboo" + }, + "providerRepositoryId": { + "type": "string", + "description": "VCS (Version Control System) Repository ID", + "x-example": "appwrite" + }, + "providerBranch": { + "type": "string", + "description": "VCS (Version Control System) branch name", + "x-example": "main" + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to function in VCS (Version Control System) repository", + "x-example": "functions\/helloWorld" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is VCS (Version Control System) connection is in silent mode? When in silence mode, no comments will be posted on the repository pull or merge requests", + "x-example": false + }, + "specification": { + "type": "string", + "description": "Machine specification for builds and executions.", + "x-example": "s-1vcpu-512mb" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "execute", + "name", + "enabled", + "live", + "logging", + "runtime", + "deploymentId", + "deploymentCreatedAt", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", + "scopes", + "vars", + "events", + "schedule", + "timeout", + "entrypoint", + "commands", + "version", + "installationId", + "providerRepositoryId", + "providerBranch", + "providerRootDirectory", + "providerSilentMode", + "specification" + ] + }, + "templateFunction": { + "description": "Template Function", + "type": "object", + "properties": { + "icon": { + "type": "string", + "description": "Function Template Icon.", + "x-example": "icon-lightning-bolt" + }, + "id": { + "type": "string", + "description": "Function Template ID.", + "x-example": "starter" + }, + "name": { + "type": "string", + "description": "Function Template Name.", + "x-example": "Starter function" + }, + "tagline": { + "type": "string", + "description": "Function Template Tagline.", + "x-example": "A simple function to get started." + }, + "permissions": { + "type": "array", + "description": "Execution permissions.", + "items": { + "type": "string" + }, + "x-example": "any" + }, + "events": { + "type": "array", + "description": "Function trigger events.", + "items": { + "type": "string" + }, + "x-example": "account.create" + }, + "cron": { + "type": "string", + "description": "Function execution schedult in CRON format.", + "x-example": "0 0 * * *" + }, + "timeout": { + "type": "integer", + "description": "Function execution timeout in seconds.", + "x-example": 300, + "format": "int32" + }, + "useCases": { + "type": "array", + "description": "Function use cases.", + "items": { + "type": "string" + }, + "x-example": "Starter" + }, + "runtimes": { + "type": "array", + "description": "List of runtimes that can be used with this template.", + "items": { + "type": "object", + "$ref": "#\/definitions\/templateRuntime" + }, + "x-example": [] + }, + "instructions": { + "type": "string", + "description": "Function Template Instructions.", + "x-example": "For documentation and instructions check out <link>." + }, + "vcsProvider": { + "type": "string", + "description": "VCS (Version Control System) Provider.", + "x-example": "github" + }, + "providerRepositoryId": { + "type": "string", + "description": "VCS (Version Control System) Repository ID", + "x-example": "templates" + }, + "providerOwner": { + "type": "string", + "description": "VCS (Version Control System) Owner.", + "x-example": "appwrite" + }, + "providerVersion": { + "type": "string", + "description": "VCS (Version Control System) branch version (tag).", + "x-example": "main" + }, + "variables": { + "type": "array", + "description": "Function variables.", + "items": { + "type": "object", + "$ref": "#\/definitions\/templateVariable" + }, + "x-example": [] + }, + "scopes": { + "type": "array", + "description": "Function scopes.", + "items": { + "type": "string" + }, + "x-example": "users.read" + } + }, + "required": [ + "icon", + "id", + "name", + "tagline", + "permissions", + "events", + "cron", + "timeout", + "useCases", + "runtimes", + "instructions", + "vcsProvider", + "providerRepositoryId", + "providerOwner", + "providerVersion", + "variables", + "scopes" + ] + }, + "templateRuntime": { + "description": "Template Runtime", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Runtime Name.", + "x-example": "node-19.0" + }, + "commands": { + "type": "string", + "description": "The build command used to build the deployment.", + "x-example": "npm install" + }, + "entrypoint": { + "type": "string", + "description": "The entrypoint file used to execute the deployment.", + "x-example": "index.js" + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to function in VCS (Version Control System) repository", + "x-example": "node\/starter" + } + }, + "required": [ + "name", + "commands", + "entrypoint", + "providerRootDirectory" + ] + }, + "templateVariable": { + "description": "Template Variable", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Variable Name.", + "x-example": "APPWRITE_DATABASE_ID" + }, + "description": { + "type": "string", + "description": "Variable Description.", + "x-example": "The ID of the Appwrite database that contains the collection to sync." + }, + "value": { + "type": "string", + "description": "Variable Value.", + "x-example": "512" + }, + "secret": { + "type": "boolean", + "description": "Variable secret flag. Secret variables can only be updated or deleted, but never read.", + "x-example": false + }, + "placeholder": { + "type": "string", + "description": "Variable Placeholder.", + "x-example": "64a55...7b912" + }, + "required": { + "type": "boolean", + "description": "Is the variable required?", + "x-example": false + }, + "type": { + "type": "string", + "description": "Variable Type.", + "x-example": "password" + } + }, + "required": [ + "name", + "description", + "value", + "secret", + "placeholder", + "required", + "type" + ] + }, + "installation": { + "description": "Installation", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Function ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Function creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Function update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "provider": { + "type": "string", + "description": "VCS (Version Control System) provider name.", + "x-example": "github" + }, + "organization": { + "type": "string", + "description": "VCS (Version Control System) organization name.", + "x-example": "appwrite" + }, + "providerInstallationId": { + "type": "string", + "description": "VCS (Version Control System) installation ID.", + "x-example": "5322" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "provider", + "organization", + "providerInstallationId" + ] + }, + "providerRepository": { + "description": "ProviderRepository", + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "VCS (Version Control System) repository ID.", + "x-example": "5e5ea5c16897e" + }, + "name": { + "type": "string", + "description": "VCS (Version Control System) repository name.", + "x-example": "appwrite" + }, + "organization": { + "type": "string", + "description": "VCS (Version Control System) organization name", + "x-example": "appwrite" + }, + "provider": { + "type": "string", + "description": "VCS (Version Control System) provider name.", + "x-example": "github" + }, + "private": { + "type": "boolean", + "description": "Is VCS (Version Control System) repository private?", + "x-example": true + }, + "pushedAt": { + "type": "string", + "description": "Last commit date in ISO 8601 format.", + "x-example": "datetime" + } + }, + "required": [ + "id", + "name", + "organization", + "provider", + "private", + "pushedAt" + ] + }, + "providerRepositoryFramework": { + "description": "ProviderRepositoryFramework", + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "VCS (Version Control System) repository ID.", + "x-example": "5e5ea5c16897e" + }, + "name": { + "type": "string", + "description": "VCS (Version Control System) repository name.", + "x-example": "appwrite" + }, + "organization": { + "type": "string", + "description": "VCS (Version Control System) organization name", + "x-example": "appwrite" + }, + "provider": { + "type": "string", + "description": "VCS (Version Control System) provider name.", + "x-example": "github" + }, + "private": { + "type": "boolean", + "description": "Is VCS (Version Control System) repository private?", + "x-example": true + }, + "pushedAt": { + "type": "string", + "description": "Last commit date in ISO 8601 format.", + "x-example": "datetime" + }, + "framework": { + "type": "string", + "description": "Auto-detected framework. Empty if type is not \"framework\".", + "x-example": "nextjs" + } + }, + "required": [ + "id", + "name", + "organization", + "provider", + "private", + "pushedAt", + "framework" + ] + }, + "providerRepositoryRuntime": { + "description": "ProviderRepositoryRuntime", + "type": "object", + "properties": { + "id": { + "type": "string", + "description": "VCS (Version Control System) repository ID.", + "x-example": "5e5ea5c16897e" + }, + "name": { + "type": "string", + "description": "VCS (Version Control System) repository name.", + "x-example": "appwrite" + }, + "organization": { + "type": "string", + "description": "VCS (Version Control System) organization name", + "x-example": "appwrite" + }, + "provider": { + "type": "string", + "description": "VCS (Version Control System) provider name.", + "x-example": "github" + }, + "private": { + "type": "boolean", + "description": "Is VCS (Version Control System) repository private?", + "x-example": true + }, + "pushedAt": { + "type": "string", + "description": "Last commit date in ISO 8601 format.", + "x-example": "datetime" + }, + "runtime": { + "type": "string", + "description": "Auto-detected runtime. Empty if type is not \"runtime\".", + "x-example": "node-22" + } + }, + "required": [ + "id", + "name", + "organization", + "provider", + "private", + "pushedAt", + "runtime" + ] + }, + "detectionFramework": { + "description": "DetectionFramework", + "type": "object", + "properties": { + "framework": { + "type": "string", + "description": "Framework", + "x-example": "nuxt" + }, + "installCommand": { + "type": "string", + "description": "Site Install Command", + "x-example": "npm install" + }, + "buildCommand": { + "type": "string", + "description": "Site Build Command", + "x-example": "npm run build" + }, + "outputDirectory": { + "type": "string", + "description": "Site Output Directory", + "x-example": "dist" + } + }, + "required": [ + "framework", + "installCommand", + "buildCommand", + "outputDirectory" + ] + }, + "detectionRuntime": { + "description": "DetectionRuntime", + "type": "object", + "properties": { + "runtime": { + "type": "string", + "description": "Runtime", + "x-example": "node" + }, + "entrypoint": { + "type": "string", + "description": "Function Entrypoint", + "x-example": "index.js" + }, + "commands": { + "type": "string", + "description": "Function install and build commands", + "x-example": "npm install && npm run build" + } + }, + "required": [ + "runtime", + "entrypoint", + "commands" + ] + }, + "vcsContent": { + "description": "VcsContents", + "type": "object", + "properties": { + "size": { + "type": "integer", + "description": "Content size in bytes. Only files have size, and for directories, 0 is returned.", + "x-example": 1523, + "format": "int32", + "x-nullable": true + }, + "isDirectory": { + "type": "boolean", + "description": "If a content is a directory. Directories can be used to check nested contents.", + "x-example": true, + "x-nullable": true + }, + "name": { + "type": "string", + "description": "Name of directory or file.", + "x-example": "Main.java" + } + }, + "required": [ + "name" + ] + }, + "branch": { + "description": "Branch", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Branch Name.", + "x-example": "main" + } + }, + "required": [ + "name" + ] + }, + "runtime": { + "description": "Runtime", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Runtime ID.", + "x-example": "python-3.8" + }, + "key": { + "type": "string", + "description": "Parent runtime key.", + "x-example": "python" + }, + "name": { + "type": "string", + "description": "Runtime Name.", + "x-example": "Python" + }, + "version": { + "type": "string", + "description": "Runtime version.", + "x-example": "3.8" + }, + "base": { + "type": "string", + "description": "Base Docker image used to build the runtime.", + "x-example": "python:3.8-alpine" + }, + "image": { + "type": "string", + "description": "Image name of Docker Hub.", + "x-example": "appwrite\\\/runtime-for-python:3.8" + }, + "logo": { + "type": "string", + "description": "Name of the logo image.", + "x-example": "python.png" + }, + "supports": { + "type": "array", + "description": "List of supported architectures.", + "items": { + "type": "string" + }, + "x-example": "amd64" + } + }, + "required": [ + "$id", + "key", + "name", + "version", + "base", + "image", + "logo", + "supports" + ] + }, + "framework": { + "description": "Framework", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Framework key.", + "x-example": "sveltekit" + }, + "name": { + "type": "string", + "description": "Framework Name.", + "x-example": "SvelteKit" + }, + "buildRuntime": { + "type": "string", + "description": "Default runtime version.", + "x-example": "node-22" + }, + "runtimes": { + "type": "array", + "description": "List of supported runtime versions.", + "items": { + "type": "string" + }, + "x-example": [ + "static-1", + "node-22" + ] + }, + "adapters": { + "type": "array", + "description": "List of supported adapters.", + "items": { + "type": "object", + "$ref": "#\/definitions\/frameworkAdapter" + }, + "x-example": [ + { + "key": "static", + "buildRuntime": "node-22", + "buildCommand": "npm run build", + "installCommand": "npm install", + "outputDirectory": ".\/dist" + } + ] + } + }, + "required": [ + "key", + "name", + "buildRuntime", + "runtimes", + "adapters" + ] + }, + "frameworkAdapter": { + "description": "Framework Adapter", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Adapter key.", + "x-example": "static" + }, + "installCommand": { + "type": "string", + "description": "Default command to download dependencies.", + "x-example": "npm install" + }, + "buildCommand": { + "type": "string", + "description": "Default command to build site into output directory.", + "x-example": "npm run build" + }, + "outputDirectory": { + "type": "string", + "description": "Default output directory of build.", + "x-example": ".\/dist" + }, + "fallbackFile": { + "type": "string", + "description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.", + "x-example": "index.html" + } + }, + "required": [ + "key", + "installCommand", + "buildCommand", + "outputDirectory", + "fallbackFile" + ] + }, + "deployment": { + "description": "Deployment", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Deployment update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "type": { + "type": "string", + "description": "Type of deployment.", + "x-example": "vcs" + }, + "resourceId": { + "type": "string", + "description": "Resource ID.", + "x-example": "5e5ea6g16897e" + }, + "resourceType": { + "type": "string", + "description": "Resource type.", + "x-example": "functions" + }, + "entrypoint": { + "type": "string", + "description": "The entrypoint file to use to execute the deployment code.", + "x-example": "index.js" + }, + "sourceSize": { + "type": "integer", + "description": "The code size in bytes.", + "x-example": 128, + "format": "int32" + }, + "buildSize": { + "type": "integer", + "description": "The build output size in bytes.", + "x-example": 128, + "format": "int32" + }, + "totalSize": { + "type": "integer", + "description": "The total size in bytes (source and build output).", + "x-example": 128, + "format": "int32" + }, + "buildId": { + "type": "string", + "description": "The current build ID.", + "x-example": "5e5ea5c16897e" + }, + "activate": { + "type": "boolean", + "description": "Whether the deployment should be automatically activated.", + "x-example": true + }, + "screenshotLight": { + "type": "string", + "description": "Screenshot with light theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "screenshotDark": { + "type": "string", + "description": "Screenshot with dark theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "status": { + "type": "string", + "description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, + "buildLogs": { + "type": "string", + "description": "The build logs.", + "x-example": "Compiling source files..." + }, + "buildDuration": { + "type": "integer", + "description": "The current build time in seconds.", + "x-example": 128, + "format": "int32" + }, + "providerRepositoryName": { + "type": "string", + "description": "The name of the vcs provider repository", + "x-example": "database" + }, + "providerRepositoryOwner": { + "type": "string", + "description": "The name of the vcs provider repository owner", + "x-example": "utopia" + }, + "providerRepositoryUrl": { + "type": "string", + "description": "The url of the vcs provider repository", + "x-example": "https:\/\/github.com\/vermakhushboo\/g4-node-function" + }, + "providerBranch": { + "type": "string", + "description": "The branch of the vcs repository", + "x-example": "0.7.x" + }, + "providerCommitHash": { + "type": "string", + "description": "The commit hash of the vcs commit", + "x-example": "7c3f25d" + }, + "providerCommitAuthorUrl": { + "type": "string", + "description": "The url of vcs commit author", + "x-example": "https:\/\/github.com\/vermakhushboo" + }, + "providerCommitAuthor": { + "type": "string", + "description": "The name of vcs commit author", + "x-example": "Khushboo Verma" + }, + "providerCommitMessage": { + "type": "string", + "description": "The commit message", + "x-example": "Update index.js" + }, + "providerCommitUrl": { + "type": "string", + "description": "The url of the vcs commit", + "x-example": "https:\/\/github.com\/vermakhushboo\/g4-node-function\/commit\/60c0416257a9cbcdd96b2d370c38d8f8d150ccfb" + }, + "providerBranchUrl": { + "type": "string", + "description": "The branch of the vcs repository", + "x-example": "https:\/\/github.com\/vermakhushboo\/appwrite\/tree\/0.7.x" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "type", + "resourceId", + "resourceType", + "entrypoint", + "sourceSize", + "buildSize", + "totalSize", + "buildId", + "activate", + "screenshotLight", + "screenshotDark", + "status", + "buildLogs", + "buildDuration", + "providerRepositoryName", + "providerRepositoryOwner", + "providerRepositoryUrl", + "providerBranch", + "providerCommitHash", + "providerCommitAuthorUrl", + "providerCommitAuthor", + "providerCommitMessage", + "providerCommitUrl", + "providerBranchUrl" + ] + }, + "execution": { + "description": "Execution", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Execution ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Execution creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Execution upate date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Execution roles.", + "items": { + "type": "string" + }, + "x-example": [ + "any" + ] + }, + "functionId": { + "type": "string", + "description": "Function ID.", + "x-example": "5e5ea6g16897e" + }, + "trigger": { + "type": "string", + "description": "The trigger that caused the function to execute. Possible values can be: `http`, `schedule`, or `event`.", + "x-example": "http" + }, + "status": { + "type": "string", + "description": "The status of the function execution. Possible values can be: `waiting`, `processing`, `completed`, or `failed`.", + "x-example": "processing" + }, + "requestMethod": { + "type": "string", + "description": "HTTP request method type.", + "x-example": "GET" + }, + "requestPath": { + "type": "string", + "description": "HTTP request path and query.", + "x-example": "\/articles?id=5" + }, + "requestHeaders": { + "type": "array", + "description": "HTTP response headers as a key-value object. This will return only whitelisted headers. All headers are returned if execution is created as synchronous.", + "items": { + "type": "object", + "$ref": "#\/definitions\/headers" + }, + "x-example": [ + { + "Content-Type": "application\/json" + } + ] + }, + "responseStatusCode": { + "type": "integer", + "description": "HTTP response status code.", + "x-example": 200, + "format": "int32" + }, + "responseBody": { + "type": "string", + "description": "HTTP response body. This will return empty unless execution is created as synchronous.", + "x-example": "" + }, + "responseHeaders": { + "type": "array", + "description": "HTTP response headers as a key-value object. This will return only whitelisted headers. All headers are returned if execution is created as synchronous.", + "items": { + "type": "object", + "$ref": "#\/definitions\/headers" + }, + "x-example": [ + { + "Content-Type": "application\/json" + } + ] + }, + "logs": { + "type": "string", + "description": "Function logs. Includes the last 4,000 characters. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.", + "x-example": "" + }, + "errors": { + "type": "string", + "description": "Function errors. Includes the last 4,000 characters. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.", + "x-example": "" + }, + "duration": { + "type": "number", + "description": "Resource(function\/site) execution duration in seconds.", + "x-example": 0.4, + "format": "double" + }, + "scheduledAt": { + "type": "string", + "description": "The scheduled time for execution. If left empty, execution will be queued immediately.", + "x-example": "2020-10-15T06:38:00.000+00:00", + "x-nullable": true + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "$permissions", + "functionId", + "trigger", + "status", + "requestMethod", + "requestPath", + "requestHeaders", + "responseStatusCode", + "responseBody", + "responseHeaders", + "logs", + "errors", + "duration" + ] + }, + "project": { + "description": "Project", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Project ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Project creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Project update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Project name.", + "x-example": "New Project" + }, + "description": { + "type": "string", + "description": "Project description.", + "x-example": "This is a new project." + }, + "teamId": { + "type": "string", + "description": "Project team ID.", + "x-example": "1592981250" + }, + "logo": { + "type": "string", + "description": "Project logo file ID.", + "x-example": "5f5c451b403cb" + }, + "url": { + "type": "string", + "description": "Project website URL.", + "x-example": "5f5c451b403cb" + }, + "legalName": { + "type": "string", + "description": "Company legal name.", + "x-example": "Company LTD." + }, + "legalCountry": { + "type": "string", + "description": "Country code in [ISO 3166-1](http:\/\/en.wikipedia.org\/wiki\/ISO_3166-1) two-character format.", + "x-example": "US" + }, + "legalState": { + "type": "string", + "description": "State name.", + "x-example": "New York" + }, + "legalCity": { + "type": "string", + "description": "City name.", + "x-example": "New York City." + }, + "legalAddress": { + "type": "string", + "description": "Company Address.", + "x-example": "620 Eighth Avenue, New York, NY 10018" + }, + "legalTaxId": { + "type": "string", + "description": "Company Tax ID.", + "x-example": "131102020" + }, + "authDuration": { + "type": "integer", + "description": "Session duration in seconds.", + "x-example": 60, + "format": "int32" + }, + "authLimit": { + "type": "integer", + "description": "Max users allowed. 0 is unlimited.", + "x-example": 100, + "format": "int32" + }, + "authSessionsLimit": { + "type": "integer", + "description": "Max sessions allowed per user. 100 maximum.", + "x-example": 10, + "format": "int32" + }, + "authPasswordHistory": { + "type": "integer", + "description": "Max allowed passwords in the history list per user. Max passwords limit allowed in history is 20. Use 0 for disabling password history.", + "x-example": 5, + "format": "int32" + }, + "authPasswordDictionary": { + "type": "boolean", + "description": "Whether or not to check user's password against most commonly used passwords.", + "x-example": true + }, + "authPersonalDataCheck": { + "type": "boolean", + "description": "Whether or not to check the user password for similarity with their personal data.", + "x-example": true + }, + "authMockNumbers": { + "type": "array", + "description": "An array of mock numbers and their corresponding verification codes (OTPs).", + "items": { + "type": "object", + "$ref": "#\/definitions\/mockNumber" + }, + "x-example": [ + {} + ] + }, + "authSessionAlerts": { + "type": "boolean", + "description": "Whether or not to send session alert emails to users.", + "x-example": true + }, + "authMembershipsUserName": { + "type": "boolean", + "description": "Whether or not to show user names in the teams membership response.", + "x-example": true + }, + "authMembershipsUserEmail": { + "type": "boolean", + "description": "Whether or not to show user emails in the teams membership response.", + "x-example": true + }, + "authMembershipsMfa": { + "type": "boolean", + "description": "Whether or not to show user MFA status in the teams membership response.", + "x-example": true + }, + "oAuthProviders": { + "type": "array", + "description": "List of Auth Providers.", + "items": { + "type": "object", + "$ref": "#\/definitions\/authProvider" + }, + "x-example": [ + {} + ] + }, + "platforms": { + "type": "array", + "description": "List of Platforms.", + "items": { + "type": "object", + "$ref": "#\/definitions\/platform" + }, + "x-example": {} + }, + "webhooks": { + "type": "array", + "description": "List of Webhooks.", + "items": { + "type": "object", + "$ref": "#\/definitions\/webhook" + }, + "x-example": {} + }, + "keys": { + "type": "array", + "description": "List of API Keys.", + "items": { + "type": "object", + "$ref": "#\/definitions\/key" + }, + "x-example": {} + }, + "devKeys": { + "type": "array", + "description": "List of dev keys.", + "items": { + "type": "object", + "$ref": "#\/definitions\/devKey" + }, + "x-example": {} + }, + "smtpEnabled": { + "type": "boolean", + "description": "Status for custom SMTP", + "x-example": false + }, + "smtpSenderName": { + "type": "string", + "description": "SMTP sender name", + "x-example": "John Appwrite" + }, + "smtpSenderEmail": { + "type": "string", + "description": "SMTP sender email", + "x-example": "john@appwrite.io" + }, + "smtpReplyTo": { + "type": "string", + "description": "SMTP reply to email", + "x-example": "support@appwrite.io" + }, + "smtpHost": { + "type": "string", + "description": "SMTP server host name", + "x-example": "mail.appwrite.io" + }, + "smtpPort": { + "type": "integer", + "description": "SMTP server port", + "x-example": 25, + "format": "int32" + }, + "smtpUsername": { + "type": "string", + "description": "SMTP server username", + "x-example": "emailuser" + }, + "smtpPassword": { + "type": "string", + "description": "SMTP server password", + "x-example": "securepassword" + }, + "smtpSecure": { + "type": "string", + "description": "SMTP server secure protocol", + "x-example": "tls" + }, + "pingCount": { + "type": "integer", + "description": "Number of times the ping was received for this project.", + "x-example": 1, + "format": "int32" + }, + "pingedAt": { + "type": "string", + "description": "Last ping datetime in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "authEmailPassword": { + "type": "boolean", + "description": "Email\/Password auth method status", + "x-example": true + }, + "authUsersAuthMagicURL": { + "type": "boolean", + "description": "Magic URL auth method status", + "x-example": true + }, + "authEmailOtp": { + "type": "boolean", + "description": "Email (OTP) auth method status", + "x-example": true + }, + "authAnonymous": { + "type": "boolean", + "description": "Anonymous auth method status", + "x-example": true + }, + "authInvites": { + "type": "boolean", + "description": "Invites auth method status", + "x-example": true + }, + "authJWT": { + "type": "boolean", + "description": "JWT auth method status", + "x-example": true + }, + "authPhone": { + "type": "boolean", + "description": "Phone auth method status", + "x-example": true + }, + "serviceStatusForAccount": { + "type": "boolean", + "description": "Account service status", + "x-example": true + }, + "serviceStatusForAvatars": { + "type": "boolean", + "description": "Avatars service status", + "x-example": true + }, + "serviceStatusForDatabases": { + "type": "boolean", + "description": "Databases service status", + "x-example": true + }, + "serviceStatusForLocale": { + "type": "boolean", + "description": "Locale service status", + "x-example": true + }, + "serviceStatusForHealth": { + "type": "boolean", + "description": "Health service status", + "x-example": true + }, + "serviceStatusForStorage": { + "type": "boolean", + "description": "Storage service status", + "x-example": true + }, + "serviceStatusForTeams": { + "type": "boolean", + "description": "Teams service status", + "x-example": true + }, + "serviceStatusForUsers": { + "type": "boolean", + "description": "Users service status", + "x-example": true + }, + "serviceStatusForSites": { + "type": "boolean", + "description": "Sites service status", + "x-example": true + }, + "serviceStatusForFunctions": { + "type": "boolean", + "description": "Functions service status", + "x-example": true + }, + "serviceStatusForGraphql": { + "type": "boolean", + "description": "GraphQL service status", + "x-example": true + }, + "serviceStatusForMessaging": { + "type": "boolean", + "description": "Messaging service status", + "x-example": true + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "description", + "teamId", + "logo", + "url", + "legalName", + "legalCountry", + "legalState", + "legalCity", + "legalAddress", + "legalTaxId", + "authDuration", + "authLimit", + "authSessionsLimit", + "authPasswordHistory", + "authPasswordDictionary", + "authPersonalDataCheck", + "authMockNumbers", + "authSessionAlerts", + "authMembershipsUserName", + "authMembershipsUserEmail", + "authMembershipsMfa", + "oAuthProviders", + "platforms", + "webhooks", + "keys", + "devKeys", + "smtpEnabled", + "smtpSenderName", + "smtpSenderEmail", + "smtpReplyTo", + "smtpHost", + "smtpPort", + "smtpUsername", + "smtpPassword", + "smtpSecure", + "pingCount", + "pingedAt", + "authEmailPassword", + "authUsersAuthMagicURL", + "authEmailOtp", + "authAnonymous", + "authInvites", + "authJWT", + "authPhone", + "serviceStatusForAccount", + "serviceStatusForAvatars", + "serviceStatusForDatabases", + "serviceStatusForLocale", + "serviceStatusForHealth", + "serviceStatusForStorage", + "serviceStatusForTeams", + "serviceStatusForUsers", + "serviceStatusForSites", + "serviceStatusForFunctions", + "serviceStatusForGraphql", + "serviceStatusForMessaging" + ] + }, + "webhook": { + "description": "Webhook", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Webhook ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Webhook creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Webhook update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Webhook name.", + "x-example": "My Webhook" + }, + "url": { + "type": "string", + "description": "Webhook URL endpoint.", + "x-example": "https:\/\/example.com\/webhook" + }, + "events": { + "type": "array", + "description": "Webhook trigger events.", + "items": { + "type": "string" + }, + "x-example": "database.collections.update" + }, + "security": { + "type": "boolean", + "description": "Indicated if SSL \/ TLS Certificate verification is enabled.", + "x-example": true + }, + "httpUser": { + "type": "string", + "description": "HTTP basic authentication username.", + "x-example": "username" + }, + "httpPass": { + "type": "string", + "description": "HTTP basic authentication password.", + "x-example": "password" + }, + "signatureKey": { + "type": "string", + "description": "Signature key which can be used to validated incoming", + "x-example": "ad3d581ca230e2b7059c545e5a" + }, + "enabled": { + "type": "boolean", + "description": "Indicates if this webhook is enabled.", + "x-example": true + }, + "logs": { + "type": "string", + "description": "Webhook error logs from the most recent failure.", + "x-example": "Failed to connect to remote server." + }, + "attempts": { + "type": "integer", + "description": "Number of consecutive failed webhook attempts.", + "x-example": 10, + "format": "int32" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "url", + "events", + "security", + "httpUser", + "httpPass", + "signatureKey", + "enabled", + "logs", + "attempts" + ] + }, + "key": { + "description": "Key", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Key ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Key creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Key update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Key name.", + "x-example": "My API Key" + }, + "expire": { + "type": "string", + "description": "Key expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "scopes": { + "type": "array", + "description": "Allowed permission scopes.", + "items": { + "type": "string" + }, + "x-example": "users.read" + }, + "secret": { + "type": "string", + "description": "Secret key.", + "x-example": "919c2d18fb5d4...a2ae413da83346ad2" + }, + "accessedAt": { + "type": "string", + "description": "Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "sdks": { + "type": "array", + "description": "List of SDK user agents that used this key.", + "items": { + "type": "string" + }, + "x-example": "appwrite:flutter" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "expire", + "scopes", + "secret", + "accessedAt", + "sdks" + ] + }, + "devKey": { + "description": "DevKey", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Key ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Key creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Key update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Key name.", + "x-example": "Dev API Key" + }, + "expire": { + "type": "string", + "description": "Key expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "secret": { + "type": "string", + "description": "Secret key.", + "x-example": "919c2d18fb5d4...a2ae413da83346ad2" + }, + "accessedAt": { + "type": "string", + "description": "Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "sdks": { + "type": "array", + "description": "List of SDK user agents that used this key.", + "items": { + "type": "string" + }, + "x-example": "appwrite:flutter" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "expire", + "secret", + "accessedAt", + "sdks" + ] + }, + "mockNumber": { + "description": "Mock Number", + "type": "object", + "properties": { + "phone": { + "type": "string", + "description": "Mock phone number for testing phone authentication. Useful for testing phone authentication without sending an SMS.", + "x-example": "+1612842323" + }, + "otp": { + "type": "string", + "description": "Mock OTP for the number. ", + "x-example": "123456" + } + }, + "required": [ + "phone", + "otp" + ] + }, + "authProvider": { + "description": "AuthProvider", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Auth Provider.", + "x-example": "github" + }, + "name": { + "type": "string", + "description": "Auth Provider name.", + "x-example": "GitHub" + }, + "appId": { + "type": "string", + "description": "OAuth 2.0 application ID.", + "x-example": "259125845563242502" + }, + "secret": { + "type": "string", + "description": "OAuth 2.0 application secret. Might be JSON string if provider requires extra configuration.", + "x-example": "Bpw_g9c2TGXxfgLshDbSaL8tsCcqgczQ" + }, + "enabled": { + "type": "boolean", + "description": "Auth Provider is active and can be used to create session.", + "x-example": "" + } + }, + "required": [ + "key", + "name", + "appId", + "secret", + "enabled" + ] + }, + "platform": { + "description": "Platform", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Platform ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Platform creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Platform update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Platform name.", + "x-example": "My Web App" + }, + "type": { + "type": "string", + "description": "Platform type. Possible values are: web, flutter-web, flutter-ios, flutter-android, ios, android, and unity.", + "x-example": "web" + }, + "key": { + "type": "string", + "description": "Platform Key. iOS bundle ID or Android package name. Empty string for other platforms.", + "x-example": "com.company.appname" + }, + "store": { + "type": "string", + "description": "App store or Google Play store ID.", + "x-example": "" + }, + "hostname": { + "type": "string", + "description": "Web app hostname. Empty string for other platforms.", + "x-example": true + }, + "httpUser": { + "type": "string", + "description": "HTTP basic authentication username.", + "x-example": "username" + }, + "httpPass": { + "type": "string", + "description": "HTTP basic authentication password.", + "x-example": "password" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "type", + "key", + "store", + "hostname", + "httpUser", + "httpPass" + ] + }, + "variable": { + "description": "Variable", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Variable ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Variable creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Variable creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "key": { + "type": "string", + "description": "Variable key.", + "x-example": "API_KEY" + }, + "value": { + "type": "string", + "description": "Variable value.", + "x-example": "myPa$$word1" + }, + "secret": { + "type": "boolean", + "description": "Variable secret flag. Secret variables can only be updated or deleted, but never read.", + "x-example": false + }, + "resourceType": { + "type": "string", + "description": "Service to which the variable belongs. Possible values are \"project\", \"function\"", + "x-example": "function" + }, + "resourceId": { + "type": "string", + "description": "ID of resource to which the variable belongs. If resourceType is \"project\", it is empty. If resourceType is \"function\", it is ID of the function.", + "x-example": "myAwesomeFunction" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "key", + "value", + "secret", + "resourceType", + "resourceId" + ] + }, + "country": { + "description": "Country", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + }, + "code": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + } + }, + "required": [ + "name", + "code" + ] + }, + "continent": { + "description": "Continent", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Continent name.", + "x-example": "Europe" + }, + "code": { + "type": "string", + "description": "Continent two letter code.", + "x-example": "EU" + } + }, + "required": [ + "name", + "code" + ] + }, + "language": { + "description": "Language", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Language name.", + "x-example": "Italian" + }, + "code": { + "type": "string", + "description": "Language two-character ISO 639-1 codes.", + "x-example": "it" + }, + "nativeName": { + "type": "string", + "description": "Language native name.", + "x-example": "Italiano" + } + }, + "required": [ + "name", + "code", + "nativeName" + ] + }, + "currency": { + "description": "Currency", + "type": "object", + "properties": { + "symbol": { + "type": "string", + "description": "Currency symbol.", + "x-example": "$" + }, + "name": { + "type": "string", + "description": "Currency name.", + "x-example": "US dollar" + }, + "symbolNative": { + "type": "string", + "description": "Currency native symbol.", + "x-example": "$" + }, + "decimalDigits": { + "type": "integer", + "description": "Number of decimal digits.", + "x-example": 2, + "format": "int32" + }, + "rounding": { + "type": "number", + "description": "Currency digit rounding.", + "x-example": 0, + "format": "double" + }, + "code": { + "type": "string", + "description": "Currency code in [ISO 4217-1](http:\/\/en.wikipedia.org\/wiki\/ISO_4217) three-character format.", + "x-example": "USD" + }, + "namePlural": { + "type": "string", + "description": "Currency plural name", + "x-example": "US dollars" + } + }, + "required": [ + "symbol", + "name", + "symbolNative", + "decimalDigits", + "rounding", + "code", + "namePlural" + ] + }, + "phone": { + "description": "Phone", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Phone code.", + "x-example": "+1" + }, + "countryCode": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + }, + "countryName": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + } + }, + "required": [ + "code", + "countryCode", + "countryName" + ] + }, + "healthAntivirus": { + "description": "Health Antivirus", + "type": "object", + "properties": { + "version": { + "type": "string", + "description": "Antivirus version.", + "x-example": "1.0.0" + }, + "status": { + "type": "string", + "description": "Antivirus status. Possible values can are: `disabled`, `offline`, `online`", + "x-example": "online" + } + }, + "required": [ + "version", + "status" + ] + }, + "healthQueue": { + "description": "Health Queue", + "type": "object", + "properties": { + "size": { + "type": "integer", + "description": "Amount of actions in the queue.", + "x-example": 8, + "format": "int32" + } + }, + "required": [ + "size" + ] + }, + "healthStatus": { + "description": "Health Status", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the service.", + "x-example": "database" + }, + "ping": { + "type": "integer", + "description": "Duration in milliseconds how long the health check took.", + "x-example": 128, + "format": "int32" + }, + "status": { + "type": "string", + "description": "Service status. Possible values can are: `pass`, `fail`", + "x-example": "pass" + } + }, + "required": [ + "name", + "ping", + "status" + ] + }, + "healthCertificate": { + "description": "Health Certificate", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Certificate name", + "x-example": "\/CN=www.google.com" + }, + "subjectSN": { + "type": "string", + "description": "Subject SN", + "x-example": "" + }, + "issuerOrganisation": { + "type": "string", + "description": "Issuer organisation", + "x-example": "" + }, + "validFrom": { + "type": "string", + "description": "Valid from", + "x-example": "1704200998" + }, + "validTo": { + "type": "string", + "description": "Valid to", + "x-example": "1711458597" + }, + "signatureTypeSN": { + "type": "string", + "description": "Signature type SN", + "x-example": "RSA-SHA256" + } + }, + "required": [ + "name", + "subjectSN", + "issuerOrganisation", + "validFrom", + "validTo", + "signatureTypeSN" + ] + }, + "healthTime": { + "description": "Health Time", + "type": "object", + "properties": { + "remoteTime": { + "type": "integer", + "description": "Current unix timestamp on trustful remote server.", + "x-example": 1639490751, + "format": "int32" + }, + "localTime": { + "type": "integer", + "description": "Current unix timestamp of local server where Appwrite runs.", + "x-example": 1639490844, + "format": "int32" + }, + "diff": { + "type": "integer", + "description": "Difference of unix remote and local timestamps in milliseconds.", + "x-example": 93, + "format": "int32" + } + }, + "required": [ + "remoteTime", + "localTime", + "diff" + ] + }, + "metric": { + "description": "Metric", + "type": "object", + "properties": { + "value": { + "type": "integer", + "description": "The value of this metric at the timestamp.", + "x-example": 1, + "format": "int32" + }, + "date": { + "type": "string", + "description": "The date at which this metric was aggregated in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "value", + "date" + ] + }, + "metricBreakdown": { + "description": "Metric Breakdown", + "type": "object", + "properties": { + "resourceId": { + "type": "string", + "description": "Resource ID.", + "x-example": "5e5ea5c16897e", + "x-nullable": true + }, + "name": { + "type": "string", + "description": "Resource name.", + "x-example": "Documents" + }, + "value": { + "type": "integer", + "description": "The value of this metric at the timestamp.", + "x-example": 1, + "format": "int32" + }, + "estimate": { + "type": "number", + "description": "The estimated value of this metric at the end of the period.", + "x-example": 1, + "format": "double", + "x-nullable": true + } + }, + "required": [ + "name", + "value" + ] + }, + "usageDatabases": { + "description": "UsageDatabases", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "databasesTotal": { + "type": "integer", + "description": "Total aggregated number of databases.", + "x-example": 0, + "format": "int32" + }, + "collectionsTotal": { + "type": "integer", + "description": "Total aggregated number of collections.", + "x-example": 0, + "format": "int32" + }, + "documentsTotal": { + "type": "integer", + "description": "Total aggregated number of documents.", + "x-example": 0, + "format": "int32" + }, + "storageTotal": { + "type": "integer", + "description": "Total aggregated number of total databases storage in bytes.", + "x-example": 0, + "format": "int32" + }, + "databasesReadsTotal": { + "type": "integer", + "description": "Total number of databases reads.", + "x-example": 0, + "format": "int32" + }, + "databasesWritesTotal": { + "type": "integer", + "description": "Total number of databases writes.", + "x-example": 0, + "format": "int32" + }, + "databases": { + "type": "array", + "description": "Aggregated number of databases per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "collections": { + "type": "array", + "description": "Aggregated number of collections per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "documents": { + "type": "array", + "description": "Aggregated number of documents per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "storage": { + "type": "array", + "description": "An array of the aggregated number of databases storage in bytes per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "databasesReads": { + "type": "array", + "description": "An array of aggregated number of database reads.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "databasesWrites": { + "type": "array", + "description": "An array of aggregated number of database writes.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "databasesTotal", + "collectionsTotal", + "documentsTotal", + "storageTotal", + "databasesReadsTotal", + "databasesWritesTotal", + "databases", + "collections", + "documents", + "storage", + "databasesReads", + "databasesWrites" + ] + }, + "usageDatabase": { + "description": "UsageDatabase", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "collectionsTotal": { + "type": "integer", + "description": "Total aggregated number of collections.", + "x-example": 0, + "format": "int32" + }, + "documentsTotal": { + "type": "integer", + "description": "Total aggregated number of documents.", + "x-example": 0, + "format": "int32" + }, + "storageTotal": { + "type": "integer", + "description": "Total aggregated number of total storage used in bytes.", + "x-example": 0, + "format": "int32" + }, + "databaseReadsTotal": { + "type": "integer", + "description": "Total number of databases reads.", + "x-example": 0, + "format": "int32" + }, + "databaseWritesTotal": { + "type": "integer", + "description": "Total number of databases writes.", + "x-example": 0, + "format": "int32" + }, + "collections": { + "type": "array", + "description": "Aggregated number of collections per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "documents": { + "type": "array", + "description": "Aggregated number of documents per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "storage": { + "type": "array", + "description": "Aggregated storage used in bytes per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "databaseReads": { + "type": "array", + "description": "An array of aggregated number of database reads.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "databaseWrites": { + "type": "array", + "description": "An array of aggregated number of database writes.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "collectionsTotal", + "documentsTotal", + "storageTotal", + "databaseReadsTotal", + "databaseWritesTotal", + "collections", + "documents", + "storage", + "databaseReads", + "databaseWrites" + ] + }, + "usageCollection": { + "description": "UsageCollection", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "documentsTotal": { + "type": "integer", + "description": "Total aggregated number of of documents.", + "x-example": 0, + "format": "int32" + }, + "documents": { + "type": "array", + "description": "Aggregated number of documents per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "documentsTotal", + "documents" + ] + }, + "usageUsers": { + "description": "UsageUsers", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "usersTotal": { + "type": "integer", + "description": "Total aggregated number of statistics of users.", + "x-example": 0, + "format": "int32" + }, + "sessionsTotal": { + "type": "integer", + "description": "Total aggregated number of active sessions.", + "x-example": 0, + "format": "int32" + }, + "users": { + "type": "array", + "description": "Aggregated number of users per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "sessions": { + "type": "array", + "description": "Aggregated number of active sessions per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "usersTotal", + "sessionsTotal", + "users", + "sessions" + ] + }, + "usageStorage": { + "description": "StorageUsage", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "bucketsTotal": { + "type": "integer", + "description": "Total aggregated number of buckets", + "x-example": 0, + "format": "int32" + }, + "filesTotal": { + "type": "integer", + "description": "Total aggregated number of files.", + "x-example": 0, + "format": "int32" + }, + "filesStorageTotal": { + "type": "integer", + "description": "Total aggregated number of files storage (in bytes).", + "x-example": 0, + "format": "int32" + }, + "buckets": { + "type": "array", + "description": "Aggregated number of buckets per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "files": { + "type": "array", + "description": "Aggregated number of files per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "storage": { + "type": "array", + "description": "Aggregated number of files storage (in bytes) per period .", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "bucketsTotal", + "filesTotal", + "filesStorageTotal", + "buckets", + "files", + "storage" + ] + }, + "usageBuckets": { + "description": "UsageBuckets", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "filesTotal": { + "type": "integer", + "description": "Total aggregated number of bucket files.", + "x-example": 0, + "format": "int32" + }, + "filesStorageTotal": { + "type": "integer", + "description": "Total aggregated number of bucket files storage (in bytes).", + "x-example": 0, + "format": "int32" + }, + "files": { + "type": "array", + "description": "Aggregated number of bucket files per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "storage": { + "type": "array", + "description": "Aggregated number of bucket storage files (in bytes) per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "imageTransformations": { + "type": "array", + "description": "Aggregated number of files transformations per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "imageTransformationsTotal": { + "type": "integer", + "description": "Total aggregated number of files transformations.", + "x-example": 0, + "format": "int32" + } + }, + "required": [ + "range", + "filesTotal", + "filesStorageTotal", + "files", + "storage", + "imageTransformations", + "imageTransformationsTotal" + ] + }, + "usageFunctions": { + "description": "UsageFunctions", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "functionsTotal": { + "type": "integer", + "description": "Total aggregated number of functions.", + "x-example": 0, + "format": "int32" + }, + "deploymentsTotal": { + "type": "integer", + "description": "Total aggregated number of functions deployments.", + "x-example": 0, + "format": "int32" + }, + "deploymentsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of functions deployment storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTotal": { + "type": "integer", + "description": "Total aggregated number of functions build.", + "x-example": 0, + "format": "int32" + }, + "buildsStorageTotal": { + "type": "integer", + "description": "total aggregated sum of functions build storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of functions build compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of functions build mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "executionsTotal": { + "type": "integer", + "description": "Total aggregated number of functions execution.", + "x-example": 0, + "format": "int32" + }, + "executionsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of functions execution compute time.", + "x-example": 0, + "format": "int32" + }, + "executionsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of functions execution mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "functions": { + "type": "array", + "description": "Aggregated number of functions per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": 0 + }, + "deployments": { + "type": "array", + "description": "Aggregated number of functions deployment per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "deploymentsStorage": { + "type": "array", + "description": "Aggregated number of functions deployment storage per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsSuccessTotal": { + "type": "integer", + "description": "Total aggregated number of successful function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsFailedTotal": { + "type": "integer", + "description": "Total aggregated number of failed function builds.", + "x-example": 0, + "format": "int32" + }, + "builds": { + "type": "array", + "description": "Aggregated number of functions build per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsStorage": { + "type": "array", + "description": "Aggregated sum of functions build storage per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsTime": { + "type": "array", + "description": "Aggregated sum of functions build compute time per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsMbSeconds": { + "type": "array", + "description": "Aggregated sum of functions build mbSeconds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executions": { + "type": "array", + "description": "Aggregated number of functions execution per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executionsTime": { + "type": "array", + "description": "Aggregated number of functions execution compute time per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executionsMbSeconds": { + "type": "array", + "description": "Aggregated number of functions mbSeconds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsSuccess": { + "type": "array", + "description": "Aggregated number of successful function builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsFailed": { + "type": "array", + "description": "Aggregated number of failed function builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "functionsTotal", + "deploymentsTotal", + "deploymentsStorageTotal", + "buildsTotal", + "buildsStorageTotal", + "buildsTimeTotal", + "buildsMbSecondsTotal", + "executionsTotal", + "executionsTimeTotal", + "executionsMbSecondsTotal", + "functions", + "deployments", + "deploymentsStorage", + "buildsSuccessTotal", + "buildsFailedTotal", + "builds", + "buildsStorage", + "buildsTime", + "buildsMbSeconds", + "executions", + "executionsTime", + "executionsMbSeconds", + "buildsSuccess", + "buildsFailed" + ] + }, + "usageFunction": { + "description": "UsageFunction", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "The time range of the usage stats.", + "x-example": "30d" + }, + "deploymentsTotal": { + "type": "integer", + "description": "Total aggregated number of function deployments.", + "x-example": 0, + "format": "int32" + }, + "deploymentsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of function deployments storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTotal": { + "type": "integer", + "description": "Total aggregated number of function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsSuccessTotal": { + "type": "integer", + "description": "Total aggregated number of successful function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsFailedTotal": { + "type": "integer", + "description": "Total aggregated number of failed function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsStorageTotal": { + "type": "integer", + "description": "total aggregated sum of function builds storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of function builds compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeAverage": { + "type": "integer", + "description": "Average builds compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of function builds mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "executionsTotal": { + "type": "integer", + "description": "Total aggregated number of function executions.", + "x-example": 0, + "format": "int32" + }, + "executionsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of function executions compute time.", + "x-example": 0, + "format": "int32" + }, + "executionsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of function executions mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "deployments": { + "type": "array", + "description": "Aggregated number of function deployments per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "deploymentsStorage": { + "type": "array", + "description": "Aggregated number of function deployments storage per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "builds": { + "type": "array", + "description": "Aggregated number of function builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsStorage": { + "type": "array", + "description": "Aggregated sum of function builds storage per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsTime": { + "type": "array", + "description": "Aggregated sum of function builds compute time per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsMbSeconds": { + "type": "array", + "description": "Aggregated number of function builds mbSeconds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executions": { + "type": "array", + "description": "Aggregated number of function executions per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executionsTime": { + "type": "array", + "description": "Aggregated number of function executions compute time per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executionsMbSeconds": { + "type": "array", + "description": "Aggregated number of function mbSeconds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsSuccess": { + "type": "array", + "description": "Aggregated number of successful builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsFailed": { + "type": "array", + "description": "Aggregated number of failed builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "deploymentsTotal", + "deploymentsStorageTotal", + "buildsTotal", + "buildsSuccessTotal", + "buildsFailedTotal", + "buildsStorageTotal", + "buildsTimeTotal", + "buildsTimeAverage", + "buildsMbSecondsTotal", + "executionsTotal", + "executionsTimeTotal", + "executionsMbSecondsTotal", + "deployments", + "deploymentsStorage", + "builds", + "buildsStorage", + "buildsTime", + "buildsMbSeconds", + "executions", + "executionsTime", + "executionsMbSeconds", + "buildsSuccess", + "buildsFailed" + ] + }, + "usageSites": { + "description": "UsageSites", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "Time range of the usage stats.", + "x-example": "30d" + }, + "deploymentsTotal": { + "type": "integer", + "description": "Total aggregated number of functions deployments.", + "x-example": 0, + "format": "int32" + }, + "deploymentsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of functions deployment storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTotal": { + "type": "integer", + "description": "Total aggregated number of functions build.", + "x-example": 0, + "format": "int32" + }, + "buildsStorageTotal": { + "type": "integer", + "description": "total aggregated sum of functions build storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of functions build compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of functions build mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "executionsTotal": { + "type": "integer", + "description": "Total aggregated number of functions execution.", + "x-example": 0, + "format": "int32" + }, + "executionsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of functions execution compute time.", + "x-example": 0, + "format": "int32" + }, + "executionsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of functions execution mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "deployments": { + "type": "array", + "description": "Aggregated number of functions deployment per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "deploymentsStorage": { + "type": "array", + "description": "Aggregated number of functions deployment storage per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsSuccessTotal": { + "type": "integer", + "description": "Total aggregated number of successful function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsFailedTotal": { + "type": "integer", + "description": "Total aggregated number of failed function builds.", + "x-example": 0, + "format": "int32" + }, + "builds": { + "type": "array", + "description": "Aggregated number of functions build per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsStorage": { + "type": "array", + "description": "Aggregated sum of functions build storage per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsTime": { + "type": "array", + "description": "Aggregated sum of functions build compute time per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsMbSeconds": { + "type": "array", + "description": "Aggregated sum of functions build mbSeconds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executions": { + "type": "array", + "description": "Aggregated number of functions execution per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executionsTime": { + "type": "array", + "description": "Aggregated number of functions execution compute time per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executionsMbSeconds": { + "type": "array", + "description": "Aggregated number of functions mbSeconds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsSuccess": { + "type": "array", + "description": "Aggregated number of successful function builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsFailed": { + "type": "array", + "description": "Aggregated number of failed function builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "sitesTotal": { + "type": "integer", + "description": "Total aggregated number of sites.", + "x-example": 0, + "format": "int32" + }, + "sites": { + "type": "array", + "description": "Aggregated number of sites per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "requestsTotal": { + "type": "integer", + "description": "Total aggregated number of requests.", + "x-example": 0, + "format": "int32" + }, + "requests": { + "type": "array", + "description": "Aggregated number of requests per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "inboundTotal": { + "type": "integer", + "description": "Total aggregated inbound bandwidth.", + "x-example": 0, + "format": "int32" + }, + "inbound": { + "type": "array", + "description": "Aggregated number of inbound bandwidth per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "outboundTotal": { + "type": "integer", + "description": "Total aggregated outbound bandwidth.", + "x-example": 0, + "format": "int32" + }, + "outbound": { + "type": "array", + "description": "Aggregated number of outbound bandwidth per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "deploymentsTotal", + "deploymentsStorageTotal", + "buildsTotal", + "buildsStorageTotal", + "buildsTimeTotal", + "buildsMbSecondsTotal", + "executionsTotal", + "executionsTimeTotal", + "executionsMbSecondsTotal", + "deployments", + "deploymentsStorage", + "buildsSuccessTotal", + "buildsFailedTotal", + "builds", + "buildsStorage", + "buildsTime", + "buildsMbSeconds", + "executions", + "executionsTime", + "executionsMbSeconds", + "buildsSuccess", + "buildsFailed", + "sitesTotal", + "sites", + "requestsTotal", + "requests", + "inboundTotal", + "inbound", + "outboundTotal", + "outbound" + ] + }, + "usageSite": { + "description": "UsageSite", + "type": "object", + "properties": { + "range": { + "type": "string", + "description": "The time range of the usage stats.", + "x-example": "30d" + }, + "deploymentsTotal": { + "type": "integer", + "description": "Total aggregated number of function deployments.", + "x-example": 0, + "format": "int32" + }, + "deploymentsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of function deployments storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTotal": { + "type": "integer", + "description": "Total aggregated number of function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsSuccessTotal": { + "type": "integer", + "description": "Total aggregated number of successful function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsFailedTotal": { + "type": "integer", + "description": "Total aggregated number of failed function builds.", + "x-example": 0, + "format": "int32" + }, + "buildsStorageTotal": { + "type": "integer", + "description": "total aggregated sum of function builds storage.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of function builds compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsTimeAverage": { + "type": "integer", + "description": "Average builds compute time.", + "x-example": 0, + "format": "int32" + }, + "buildsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of function builds mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "executionsTotal": { + "type": "integer", + "description": "Total aggregated number of function executions.", + "x-example": 0, + "format": "int32" + }, + "executionsTimeTotal": { + "type": "integer", + "description": "Total aggregated sum of function executions compute time.", + "x-example": 0, + "format": "int32" + }, + "executionsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated sum of function executions mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "deployments": { + "type": "array", + "description": "Aggregated number of function deployments per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "deploymentsStorage": { + "type": "array", + "description": "Aggregated number of function deployments storage per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "builds": { + "type": "array", + "description": "Aggregated number of function builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsStorage": { + "type": "array", + "description": "Aggregated sum of function builds storage per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsTime": { + "type": "array", + "description": "Aggregated sum of function builds compute time per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsMbSeconds": { + "type": "array", + "description": "Aggregated number of function builds mbSeconds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executions": { + "type": "array", + "description": "Aggregated number of function executions per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executionsTime": { + "type": "array", + "description": "Aggregated number of function executions compute time per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executionsMbSeconds": { + "type": "array", + "description": "Aggregated number of function mbSeconds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsSuccess": { + "type": "array", + "description": "Aggregated number of successful builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "buildsFailed": { + "type": "array", + "description": "Aggregated number of failed builds per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "requestsTotal": { + "type": "integer", + "description": "Total aggregated number of requests.", + "x-example": 0, + "format": "int32" + }, + "requests": { + "type": "array", + "description": "Aggregated number of requests per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "inboundTotal": { + "type": "integer", + "description": "Total aggregated inbound bandwidth.", + "x-example": 0, + "format": "int32" + }, + "inbound": { + "type": "array", + "description": "Aggregated number of inbound bandwidth per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "outboundTotal": { + "type": "integer", + "description": "Total aggregated outbound bandwidth.", + "x-example": 0, + "format": "int32" + }, + "outbound": { + "type": "array", + "description": "Aggregated number of outbound bandwidth per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + } + }, + "required": [ + "range", + "deploymentsTotal", + "deploymentsStorageTotal", + "buildsTotal", + "buildsSuccessTotal", + "buildsFailedTotal", + "buildsStorageTotal", + "buildsTimeTotal", + "buildsTimeAverage", + "buildsMbSecondsTotal", + "executionsTotal", + "executionsTimeTotal", + "executionsMbSecondsTotal", + "deployments", + "deploymentsStorage", + "builds", + "buildsStorage", + "buildsTime", + "buildsMbSeconds", + "executions", + "executionsTime", + "executionsMbSeconds", + "buildsSuccess", + "buildsFailed", + "requestsTotal", + "requests", + "inboundTotal", + "inbound", + "outboundTotal", + "outbound" + ] + }, + "usageProject": { + "description": "UsageProject", + "type": "object", + "properties": { + "executionsTotal": { + "type": "integer", + "description": "Total aggregated number of function executions.", + "x-example": 0, + "format": "int32" + }, + "documentsTotal": { + "type": "integer", + "description": "Total aggregated number of documents.", + "x-example": 0, + "format": "int32" + }, + "databasesTotal": { + "type": "integer", + "description": "Total aggregated number of databases.", + "x-example": 0, + "format": "int32" + }, + "databasesStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of databases storage size (in bytes).", + "x-example": 0, + "format": "int32" + }, + "usersTotal": { + "type": "integer", + "description": "Total aggregated number of users.", + "x-example": 0, + "format": "int32" + }, + "filesStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of files storage size (in bytes).", + "x-example": 0, + "format": "int32" + }, + "functionsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of functions storage size (in bytes).", + "x-example": 0, + "format": "int32" + }, + "buildsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of builds storage size (in bytes).", + "x-example": 0, + "format": "int32" + }, + "deploymentsStorageTotal": { + "type": "integer", + "description": "Total aggregated sum of deployments storage size (in bytes).", + "x-example": 0, + "format": "int32" + }, + "bucketsTotal": { + "type": "integer", + "description": "Total aggregated number of buckets.", + "x-example": 0, + "format": "int32" + }, + "executionsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated number of function executions mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "buildsMbSecondsTotal": { + "type": "integer", + "description": "Total aggregated number of function builds mbSeconds.", + "x-example": 0, + "format": "int32" + }, + "databasesReadsTotal": { + "type": "integer", + "description": "Total number of databases reads.", + "x-example": 0, + "format": "int32" + }, + "databasesWritesTotal": { + "type": "integer", + "description": "Total number of databases writes.", + "x-example": 0, + "format": "int32" + }, + "requests": { + "type": "array", + "description": "Aggregated number of requests per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "network": { + "type": "array", + "description": "Aggregated number of consumed bandwidth per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "users": { + "type": "array", + "description": "Aggregated number of users per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executions": { + "type": "array", + "description": "Aggregated number of executions per period.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "executionsBreakdown": { + "type": "array", + "description": "Aggregated breakdown in totals of executions by functions.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metricBreakdown" + }, + "x-example": [] + }, + "bucketsBreakdown": { + "type": "array", + "description": "Aggregated breakdown in totals of usage by buckets.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metricBreakdown" + }, + "x-example": [] + }, + "databasesStorageBreakdown": { + "type": "array", + "description": "An array of the aggregated breakdown of storage usage by databases.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metricBreakdown" + }, + "x-example": [] + }, + "executionsMbSecondsBreakdown": { + "type": "array", + "description": "Aggregated breakdown in totals of execution mbSeconds by functions.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metricBreakdown" + }, + "x-example": [] + }, + "buildsMbSecondsBreakdown": { + "type": "array", + "description": "Aggregated breakdown in totals of build mbSeconds by functions.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metricBreakdown" + }, + "x-example": [] + }, + "functionsStorageBreakdown": { + "type": "array", + "description": "Aggregated breakdown in totals of functions storage size (in bytes).", + "items": { + "type": "object", + "$ref": "#\/definitions\/metricBreakdown" + }, + "x-example": [] + }, + "authPhoneTotal": { + "type": "integer", + "description": "Total aggregated number of phone auth.", + "x-example": 0, + "format": "int32" + }, + "authPhoneEstimate": { + "type": "number", + "description": "Estimated total aggregated cost of phone auth.", + "x-example": 0, + "format": "double" + }, + "authPhoneCountryBreakdown": { + "type": "array", + "description": "Aggregated breakdown in totals of phone auth by country.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metricBreakdown" + }, + "x-example": [] + }, + "databasesReads": { + "type": "array", + "description": "An array of aggregated number of database reads.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "databasesWrites": { + "type": "array", + "description": "An array of aggregated number of database writes.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "imageTransformations": { + "type": "array", + "description": "An array of aggregated number of image transformations.", + "items": { + "type": "object", + "$ref": "#\/definitions\/metric" + }, + "x-example": [] + }, + "imageTransformationsTotal": { + "type": "integer", + "description": "Total aggregated number of image transformations.", + "x-example": 0, + "format": "int32" + } + }, + "required": [ + "executionsTotal", + "documentsTotal", + "databasesTotal", + "databasesStorageTotal", + "usersTotal", + "filesStorageTotal", + "functionsStorageTotal", + "buildsStorageTotal", + "deploymentsStorageTotal", + "bucketsTotal", + "executionsMbSecondsTotal", + "buildsMbSecondsTotal", + "databasesReadsTotal", + "databasesWritesTotal", + "requests", + "network", + "users", + "executions", + "executionsBreakdown", + "bucketsBreakdown", + "databasesStorageBreakdown", + "executionsMbSecondsBreakdown", + "buildsMbSecondsBreakdown", + "functionsStorageBreakdown", + "authPhoneTotal", + "authPhoneEstimate", + "authPhoneCountryBreakdown", + "databasesReads", + "databasesWrites", + "imageTransformations", + "imageTransformationsTotal" + ] + }, + "headers": { + "description": "Headers", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Header name.", + "x-example": "Content-Type" + }, + "value": { + "type": "string", + "description": "Header value.", + "x-example": "application\/json" + } + }, + "required": [ + "name", + "value" + ] + }, + "specification": { + "description": "Specification", + "type": "object", + "properties": { + "memory": { + "type": "integer", + "description": "Memory size in MB.", + "x-example": 512, + "format": "int32" + }, + "cpus": { + "type": "number", + "description": "Number of CPUs.", + "x-example": 1, + "format": "double" + }, + "enabled": { + "type": "boolean", + "description": "Is size enabled.", + "x-example": true + }, + "slug": { + "type": "string", + "description": "Size slug.", + "x-example": "s-1vcpu-512mb" + } + }, + "required": [ + "memory", + "cpus", + "enabled", + "slug" + ] + }, + "proxyRule": { + "description": "Rule", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Rule ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Rule creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Rule update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "domain": { + "type": "string", + "description": "Domain name.", + "x-example": "appwrite.company.com" + }, + "type": { + "type": "string", + "description": "Action definition for the rule. Possible values are \"api\", \"deployment\", or \"redirect\"", + "x-example": "deployment" + }, + "trigger": { + "type": "string", + "description": "Defines how the rule was created. Possible values are \"manual\" or \"deployment\"", + "x-example": "manual" + }, + "redirectUrl": { + "type": "string", + "description": "URL to redirect to. Used if type is \"redirect\"", + "x-example": "https:\/\/appwrite.io\/docs" + }, + "redirectStatusCode": { + "type": "integer", + "description": "Status code to apply during redirect. Used if type is \"redirect\"", + "x-example": 301, + "format": "int32" + }, + "deploymentId": { + "type": "string", + "description": "ID of deployment. Used if type is \"deployment\"", + "x-example": "n3u9feiwmf" + }, + "deploymentResourceType": { + "type": "string", + "description": "Type of deployment. Possible values are \"function\", \"site\". Used if rule's type is \"deployment\".", + "x-example": "function" + }, + "deploymentResourceId": { + "type": "string", + "description": "ID deployment's resource. Used if type is \"deployment\"", + "x-example": "n3u9feiwmf" + }, + "deploymentVcsProviderBranch": { + "type": "string", + "description": "Name of Git branch that updates rule. Used if type is \"deployment\"", + "x-example": "function" + }, + "status": { + "type": "string", + "description": "Domain verification status. Possible values are \"created\", \"verifying\", \"verified\" and \"unverified\"", + "x-example": "verified" + }, + "logs": { + "type": "string", + "description": "Certificate generation logs. This will return an empty string if generation did not run, or succeeded.", + "x-example": "HTTP challegne failed." + }, + "renewAt": { + "type": "string", + "description": "Certificate auto-renewal date in ISO 8601 format.", + "x-example": "datetime" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "domain", + "type", + "trigger", + "redirectUrl", + "redirectStatusCode", + "deploymentId", + "deploymentResourceType", + "deploymentResourceId", + "deploymentVcsProviderBranch", + "status", + "logs", + "renewAt" + ] + }, + "smsTemplate": { + "description": "SmsTemplate", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Template type", + "x-example": "verification" + }, + "locale": { + "type": "string", + "description": "Template locale", + "x-example": "en_us" + }, + "message": { + "type": "string", + "description": "Template message", + "x-example": "Click on the link to verify your account." + } + }, + "required": [ + "type", + "locale", + "message" + ] + }, + "emailTemplate": { + "description": "EmailTemplate", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Template type", + "x-example": "verification" + }, + "locale": { + "type": "string", + "description": "Template locale", + "x-example": "en_us" + }, + "message": { + "type": "string", + "description": "Template message", + "x-example": "Click on the link to verify your account." + }, + "senderName": { + "type": "string", + "description": "Name of the sender", + "x-example": "My User" + }, + "senderEmail": { + "type": "string", + "description": "Email of the sender", + "x-example": "mail@appwrite.io" + }, + "replyTo": { + "type": "string", + "description": "Reply to email address", + "x-example": "emails@appwrite.io" + }, + "subject": { + "type": "string", + "description": "Email subject", + "x-example": "Please verify your email address" + } + }, + "required": [ + "type", + "locale", + "message", + "senderName", + "senderEmail", + "replyTo", + "subject" + ] + }, + "consoleVariables": { + "description": "Console Variables", + "type": "object", + "properties": { + "_APP_DOMAIN_TARGET_CNAME": { + "type": "string", + "description": "CNAME target for your Appwrite custom domains.", + "x-example": "appwrite.io" + }, + "_APP_DOMAIN_TARGET_A": { + "type": "string", + "description": "A target for your Appwrite custom domains.", + "x-example": "127.0.0.1" + }, + "_APP_DOMAIN_TARGET_AAAA": { + "type": "string", + "description": "AAAA target for your Appwrite custom domains.", + "x-example": "::1" + }, + "_APP_STORAGE_LIMIT": { + "type": "integer", + "description": "Maximum file size allowed for file upload in bytes.", + "x-example": "30000000", + "format": "int32" + }, + "_APP_COMPUTE_SIZE_LIMIT": { + "type": "integer", + "description": "Maximum file size allowed for deployment in bytes.", + "x-example": "30000000", + "format": "int32" + }, + "_APP_USAGE_STATS": { + "type": "string", + "description": "Defines if usage stats are enabled. This value is set to 'enabled' by default, to disable the usage stats set the value to 'disabled'.", + "x-example": "enabled" + }, + "_APP_VCS_ENABLED": { + "type": "boolean", + "description": "Defines if VCS (Version Control System) is enabled.", + "x-example": true + }, + "_APP_DOMAIN_ENABLED": { + "type": "boolean", + "description": "Defines if main domain is configured. If so, custom domains can be created.", + "x-example": true + }, + "_APP_ASSISTANT_ENABLED": { + "type": "boolean", + "description": "Defines if AI assistant is enabled.", + "x-example": true + }, + "_APP_DOMAIN_SITES": { + "type": "string", + "description": "A domain to use for site URLs.", + "x-example": "sites.localhost" + }, + "_APP_DOMAIN_FUNCTIONS": { + "type": "string", + "description": "A domain to use for function URLs.", + "x-example": "functions.localhost" + }, + "_APP_OPTIONS_FORCE_HTTPS": { + "type": "string", + "description": "Defines if HTTPS is enforced for all requests.", + "x-example": "enabled" + }, + "_APP_DOMAINS_NAMESERVERS": { + "type": "string", + "description": "Comma-separated list of nameservers.", + "x-example": "ns1.example.com,ns2.example.com" + } + }, + "required": [ + "_APP_DOMAIN_TARGET_CNAME", + "_APP_DOMAIN_TARGET_A", + "_APP_DOMAIN_TARGET_AAAA", + "_APP_STORAGE_LIMIT", + "_APP_COMPUTE_SIZE_LIMIT", + "_APP_USAGE_STATS", + "_APP_VCS_ENABLED", + "_APP_DOMAIN_ENABLED", + "_APP_ASSISTANT_ENABLED", + "_APP_DOMAIN_SITES", + "_APP_DOMAIN_FUNCTIONS", + "_APP_OPTIONS_FORCE_HTTPS", + "_APP_DOMAINS_NAMESERVERS" + ] + }, + "mfaChallenge": { + "description": "MFA Challenge", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Token ID.", + "x-example": "bb8ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Token creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c168bb8" + }, + "expire": { + "type": "string", + "description": "Token expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "userId", + "expire" + ] + }, + "mfaRecoveryCodes": { + "description": "MFA Recovery Codes", + "type": "object", + "properties": { + "recoveryCodes": { + "type": "array", + "description": "Recovery codes.", + "items": { + "type": "string" + }, + "x-example": [ + "a3kf0-s0cl2", + "s0co1-as98s" + ] + } + }, + "required": [ + "recoveryCodes" + ] + }, + "mfaType": { + "description": "MFAType", + "type": "object", + "properties": { + "secret": { + "type": "string", + "description": "Secret token used for TOTP factor.", + "x-example": true + }, + "uri": { + "type": "string", + "description": "URI for authenticator apps.", + "x-example": true + } + }, + "required": [ + "secret", + "uri" + ] + }, + "mfaFactors": { + "description": "MFAFactors", + "type": "object", + "properties": { + "totp": { + "type": "boolean", + "description": "Can TOTP be used for MFA challenge for this account.", + "x-example": true + }, + "phone": { + "type": "boolean", + "description": "Can phone (SMS) be used for MFA challenge for this account.", + "x-example": true + }, + "email": { + "type": "boolean", + "description": "Can email be used for MFA challenge for this account.", + "x-example": true + }, + "recoveryCode": { + "type": "boolean", + "description": "Can recovery code be used for MFA challenge for this account.", + "x-example": true + } + }, + "required": [ + "totp", + "phone", + "email", + "recoveryCode" + ] + }, + "provider": { + "description": "Provider", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Provider ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Provider creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Provider update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "The name for the provider instance.", + "x-example": "Mailgun" + }, + "provider": { + "type": "string", + "description": "The name of the provider service.", + "x-example": "mailgun" + }, + "enabled": { + "type": "boolean", + "description": "Is provider enabled?", + "x-example": true + }, + "type": { + "type": "string", + "description": "Type of provider.", + "x-example": "sms" + }, + "credentials": { + "type": "object", + "additionalProperties": true, + "description": "Provider credentials.", + "x-example": { + "key": "123456789" + } + }, + "options": { + "type": "object", + "additionalProperties": true, + "description": "Provider options.", + "x-example": { + "from": "sender-email@mydomain" + } + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "provider", + "enabled", + "type", + "credentials" + ] + }, + "message": { + "description": "Message", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Message ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Message creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Message update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "providerType": { + "type": "string", + "description": "Message provider type.", + "x-example": "email" + }, + "topics": { + "type": "array", + "description": "Topic IDs set as recipients.", + "items": { + "type": "string" + }, + "x-example": [ + "5e5ea5c16897e" + ] + }, + "users": { + "type": "array", + "description": "User IDs set as recipients.", + "items": { + "type": "string" + }, + "x-example": [ + "5e5ea5c16897e" + ] + }, + "targets": { + "type": "array", + "description": "Target IDs set as recipients.", + "items": { + "type": "string" + }, + "x-example": [ + "5e5ea5c16897e" + ] + }, + "scheduledAt": { + "type": "string", + "description": "The scheduled time for message.", + "x-example": "2020-10-15T06:38:00.000+00:00", + "x-nullable": true + }, + "deliveredAt": { + "type": "string", + "description": "The time when the message was delivered.", + "x-example": "2020-10-15T06:38:00.000+00:00", + "x-nullable": true + }, + "deliveryErrors": { + "type": "array", + "description": "Delivery errors if any.", + "items": { + "type": "string" + }, + "x-example": [ + "Failed to send message to target 5e5ea5c16897e: Credentials not valid." + ], + "x-nullable": true + }, + "deliveredTotal": { + "type": "integer", + "description": "Number of recipients the message was delivered to.", + "x-example": 1, + "format": "int32" + }, + "data": { + "type": "object", + "additionalProperties": true, + "description": "Data of the message.", + "x-example": { + "subject": "Welcome to Appwrite", + "content": "Hi there, welcome to Appwrite family." + } + }, + "status": { + "type": "string", + "description": "Status of delivery.", + "x-example": "Message status can be one of the following: draft, processing, scheduled, sent, or failed." + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "providerType", + "topics", + "users", + "targets", + "deliveredTotal", + "data", + "status" + ] + }, + "topic": { + "description": "Topic", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Topic ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Topic creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Topic update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "The name of the topic.", + "x-example": "events" + }, + "emailTotal": { + "type": "integer", + "description": "Total count of email subscribers subscribed to the topic.", + "x-example": 100, + "format": "int32" + }, + "smsTotal": { + "type": "integer", + "description": "Total count of SMS subscribers subscribed to the topic.", + "x-example": 100, + "format": "int32" + }, + "pushTotal": { + "type": "integer", + "description": "Total count of push subscribers subscribed to the topic.", + "x-example": 100, + "format": "int32" + }, + "subscribe": { + "type": "array", + "description": "Subscribe permissions.", + "items": { + "type": "string" + }, + "x-example": "users" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "emailTotal", + "smsTotal", + "pushTotal", + "subscribe" + ] + }, + "subscriber": { + "description": "Subscriber", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Subscriber ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Subscriber creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Subscriber update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "targetId": { + "type": "string", + "description": "Target ID.", + "x-example": "259125845563242502" + }, + "target": { + "type": "object", + "description": "Target.", + "x-example": { + "$id": "259125845563242502", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "providerType": "email", + "providerId": "259125845563242502", + "name": "ageon-app-email", + "identifier": "random-mail@email.org", + "userId": "5e5ea5c16897e" + }, + "items": { + "type": "object", + "$ref": "#\/definitions\/target" + } + }, + "userId": { + "type": "string", + "description": "Topic ID.", + "x-example": "5e5ea5c16897e" + }, + "userName": { + "type": "string", + "description": "User Name.", + "x-example": "Aegon Targaryen" + }, + "topicId": { + "type": "string", + "description": "Topic ID.", + "x-example": "259125845563242502" + }, + "providerType": { + "type": "string", + "description": "The target provider type. Can be one of the following: `email`, `sms` or `push`.", + "x-example": "email" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "targetId", + "target", + "userId", + "userName", + "topicId", + "providerType" + ] + }, + "target": { + "description": "Target", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Target ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Target creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Target update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Target Name.", + "x-example": "Apple iPhone 12" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "259125845563242502" + }, + "providerId": { + "type": "string", + "description": "Provider ID.", + "x-example": "259125845563242502", + "x-nullable": true + }, + "providerType": { + "type": "string", + "description": "The target provider type. Can be one of the following: `email`, `sms` or `push`.", + "x-example": "email" + }, + "identifier": { + "type": "string", + "description": "The target identifier.", + "x-example": "token" + }, + "expired": { + "type": "boolean", + "description": "Is the target expired.", + "x-example": false + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "userId", + "providerType", + "identifier", + "expired" + ] + }, + "migration": { + "description": "Migration", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Migration ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Migration creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Variable creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "string", + "description": "Migration status ( pending, processing, failed, completed ) ", + "x-example": "pending" + }, + "stage": { + "type": "string", + "description": "Migration stage ( init, processing, source-check, destination-check, migrating, finished )", + "x-example": "init" + }, + "source": { + "type": "string", + "description": "A string containing the type of source of the migration.", + "x-example": "Appwrite" + }, + "destination": { + "type": "string", + "description": "A string containing the type of destination of the migration.", + "x-example": "Appwrite" + }, + "resources": { + "type": "array", + "description": "Resources to migrate.", + "items": { + "type": "string" + }, + "x-example": [ + "user" + ] + }, + "resourceId": { + "type": "string", + "description": "Id of the resource to migrate.", + "x-example": "databaseId:collectionId" + }, + "statusCounters": { + "type": "object", + "additionalProperties": true, + "description": "A group of counters that represent the total progress of the migration.", + "x-example": "{\"Database\": {\"PENDING\": 0, \"SUCCESS\": 1, \"ERROR\": 0, \"SKIP\": 0, \"PROCESSING\": 0, \"WARNING\": 0}}" + }, + "resourceData": { + "type": "object", + "additionalProperties": true, + "description": "An array of objects containing the report data of the resources that were migrated.", + "x-example": "[{\"resource\":\"Database\",\"id\":\"public\",\"status\":\"SUCCESS\",\"message\":\"\"}]" + }, + "errors": { + "type": "array", + "description": "All errors that occurred during the migration process.", + "items": { + "type": "string" + }, + "x-example": [] + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "status", + "stage", + "source", + "destination", + "resources", + "resourceId", + "statusCounters", + "resourceData", + "errors" + ] + }, + "migrationReport": { + "description": "Migration Report", + "type": "object", + "properties": { + "user": { + "type": "integer", + "description": "Number of users to be migrated.", + "x-example": 20, + "format": "int32" + }, + "team": { + "type": "integer", + "description": "Number of teams to be migrated.", + "x-example": 20, + "format": "int32" + }, + "database": { + "type": "integer", + "description": "Number of databases to be migrated.", + "x-example": 20, + "format": "int32" + }, + "document": { + "type": "integer", + "description": "Number of documents to be migrated.", + "x-example": 20, + "format": "int32" + }, + "file": { + "type": "integer", + "description": "Number of files to be migrated.", + "x-example": 20, + "format": "int32" + }, + "bucket": { + "type": "integer", + "description": "Number of buckets to be migrated.", + "x-example": 20, + "format": "int32" + }, + "function": { + "type": "integer", + "description": "Number of functions to be migrated.", + "x-example": 20, + "format": "int32" + }, + "size": { + "type": "integer", + "description": "Size of files to be migrated in mb.", + "x-example": 30000, + "format": "int32" + }, + "version": { + "type": "string", + "description": "Version of the Appwrite instance to be migrated.", + "x-example": "1.4.0" + } + }, + "required": [ + "user", + "team", + "database", + "document", + "file", + "bucket", + "function", + "size", + "version" + ] + } + }, + "externalDocs": { + "description": "Full API docs, specs and tutorials", + "url": "https:\/\/appwrite.io\/docs" + } +} \ No newline at end of file diff --git a/app/config/specs/swagger2-1.8.x-server.json b/app/config/specs/swagger2-1.8.x-server.json new file mode 100644 index 0000000000..cdadac68e3 --- /dev/null +++ b/app/config/specs/swagger2-1.8.x-server.json @@ -0,0 +1,30820 @@ +{ + "swagger": "2.0", + "info": { + "version": "1.7.4", + "title": "Appwrite", + "description": "Appwrite backend as a service cuts up to 70% of the time and costs required for building a modern application. We abstract and simplify common development tasks behind a REST APIs, to help you develop your app in a fast and secure way. For full API documentation and tutorials go to [https:\/\/appwrite.io\/docs](https:\/\/appwrite.io\/docs)", + "termsOfService": "https:\/\/appwrite.io\/policy\/terms", + "contact": { + "name": "Appwrite Team", + "url": "https:\/\/appwrite.io\/support", + "email": "team@appwrite.io" + }, + "license": { + "name": "BSD-3-Clause", + "url": "https:\/\/raw.githubusercontent.com\/appwrite\/appwrite\/master\/LICENSE" + } + }, + "host": "cloud.appwrite.io", + "x-host-docs": "<REGION>.cloud.appwrite.io", + "basePath": "\/v1", + "schemes": [ + "https" + ], + "consumes": [ + "application\/json", + "multipart\/form-data" + ], + "produces": [ + "application\/json" + ], + "securityDefinitions": { + "Project": { + "type": "apiKey", + "name": "X-Appwrite-Project", + "description": "Your project ID", + "in": "header", + "x-appwrite": { + "demo": "<YOUR_PROJECT_ID>" + } + }, + "Key": { + "type": "apiKey", + "name": "X-Appwrite-Key", + "description": "Your secret API key", + "in": "header", + "x-appwrite": { + "demo": "<YOUR_API_KEY>" + } + }, + "JWT": { + "type": "apiKey", + "name": "X-Appwrite-JWT", + "description": "Your secret JSON Web Token", + "in": "header", + "x-appwrite": { + "demo": "<YOUR_JWT>" + } + }, + "Locale": { + "type": "apiKey", + "name": "X-Appwrite-Locale", + "description": "", + "in": "header", + "x-appwrite": { + "demo": "en" + } + }, + "Session": { + "type": "apiKey", + "name": "X-Appwrite-Session", + "description": "The user session to authenticate with", + "in": "header" + }, + "ForwardedUserAgent": { + "type": "apiKey", + "name": "X-Forwarded-User-Agent", + "description": "The user agent string of the client that made the request", + "in": "header" + } + }, + "paths": { + "\/account": { + "get": { + "summary": "Get account", + "operationId": "accountGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get the currently logged in user.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "get", + "group": "account", + "weight": 10, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "post": { + "summary": "Create account", + "operationId": "accountCreate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to allow a new user to register a new account in your project. After the user registration completes successfully, you can use the [\/account\/verfication](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createVerification) route to start verifying the user email address. To allow the new user to login to their new account, you need to create a new [account session](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createEmailSession).", + "responses": { + "201": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "create", + "group": "account", + "weight": 9, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "New user password. Must be between 8 and 256 chars.", + "default": null, + "x-example": null + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + ] + } + }, + "\/account\/email": { + "patch": { + "summary": "Update email", + "operationId": "accountUpdateEmail", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Update currently logged in user account email address. After changing user address, the user confirmation status will get reset. A new confirmation email is not sent automatically however you can use the send confirmation email endpoint again to send the confirmation email. For security measures, user password is required to complete this request.\nThis endpoint can also be used to convert an anonymous account to a normal one, by passing an email address and a new password.\n", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateEmail", + "group": "account", + "weight": 35, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-email.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password. Must be at least 8 chars.", + "default": null, + "x-example": "password" + } + }, + "required": [ + "email", + "password" + ] + } + } + ] + } + }, + "\/account\/identities": { + "get": { + "summary": "List identities", + "operationId": "accountListIdentities", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get the list of identities for the currently logged in user.", + "responses": { + "200": { + "description": "Identities List", + "schema": { + "$ref": "#\/definitions\/identityList" + } + } + }, + "x-appwrite": { + "method": "listIdentities", + "group": "identities", + "weight": 58, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-identities.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-identities.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, provider, providerUid, providerEmail, providerAccessTokenExpiry", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/account\/identities\/{identityId}": { + "delete": { + "summary": "Delete identity", + "operationId": "accountDeleteIdentity", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "account" + ], + "description": "Delete an identity by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteIdentity", + "group": "identities", + "weight": 59, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-identity.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-identity.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "identityId", + "description": "Identity ID.", + "required": true, + "type": "string", + "x-example": "<IDENTITY_ID>", + "in": "path" + } + ] + } + }, + "\/account\/jwts": { + "post": { + "summary": "Create JWT", + "operationId": "accountCreateJWT", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to create a JSON Web Token. You can use the resulting JWT to authenticate on behalf of the current user when working with the Appwrite server-side API and SDKs. The JWT secret is valid for 15 minutes from its creation and will be invalid if the user will logout in that time frame.", + "responses": { + "201": { + "description": "JWT", + "schema": { + "$ref": "#\/definitions\/jwt" + } + } + }, + "x-appwrite": { + "method": "createJWT", + "group": "tokens", + "weight": 30, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-j-w-t.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-jwt.md", + "rate-limit": 100, + "rate-time": 3600, + "rate-key": "url:{url},userId:{userId}", + "scope": "account", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ] + } + }, + "\/account\/logs": { + "get": { + "summary": "List logs", + "operationId": "accountListLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get the list of latest security activity logs for the currently logged in user. Each log returns user IP address, location and date and time of log.", + "responses": { + "200": { + "description": "Logs List", + "schema": { + "$ref": "#\/definitions\/logList" + } + } + }, + "x-appwrite": { + "method": "listLogs", + "group": "logs", + "weight": 32, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/account\/mfa": { + "patch": { + "summary": "Update MFA", + "operationId": "accountUpdateMFA", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Enable or disable MFA on an account.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateMFA", + "group": "mfa", + "weight": 45, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-m-f-a.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "mfa": { + "type": "boolean", + "description": "Enable or disable MFA.", + "default": null, + "x-example": false + } + }, + "required": [ + "mfa" + ] + } + } + ] + } + }, + "\/account\/mfa\/authenticators\/{type}": { + "post": { + "summary": "Create authenticator", + "operationId": "accountCreateMfaAuthenticator", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Add an authenticator app to be used as an MFA factor. Verify the authenticator using the [verify authenticator](\/docs\/references\/cloud\/client-web\/account#updateMfaAuthenticator) method.", + "responses": { + "200": { + "description": "MFAType", + "schema": { + "$ref": "#\/definitions\/mfaType" + } + } + }, + "x-appwrite": { + "method": "createMfaAuthenticator", + "group": "mfa", + "weight": 47, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "type", + "description": "Type of authenticator. Must be `totp`", + "required": true, + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [], + "in": "path" + } + ] + }, + "put": { + "summary": "Update authenticator (confirmation)", + "operationId": "accountUpdateMfaAuthenticator", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Verify an authenticator app after adding it using the [add authenticator](\/docs\/references\/cloud\/client-web\/account#createMfaAuthenticator) method.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateMfaAuthenticator", + "group": "mfa", + "weight": 48, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "type", + "description": "Type of authenticator.", + "required": true, + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [], + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "otp": { + "type": "string", + "description": "Valid verification token.", + "default": null, + "x-example": "<OTP>" + } + }, + "required": [ + "otp" + ] + } + } + ] + }, + "delete": { + "summary": "Delete authenticator", + "operationId": "accountDeleteMfaAuthenticator", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "account" + ], + "description": "Delete an authenticator for a user by ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteMfaAuthenticator", + "group": "mfa", + "weight": 52, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "type", + "description": "Type of authenticator.", + "required": true, + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [], + "in": "path" + } + ] + } + }, + "\/account\/mfa\/challenge": { + "post": { + "summary": "Create MFA challenge", + "operationId": "accountCreateMfaChallenge", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Begin the process of MFA verification after sign-in. Finish the flow with [updateMfaChallenge](\/docs\/references\/cloud\/client-web\/account#updateMfaChallenge) method.", + "responses": { + "201": { + "description": "MFA Challenge", + "schema": { + "$ref": "#\/definitions\/mfaChallenge" + } + } + }, + "x-appwrite": { + "method": "createMfaChallenge", + "group": "mfa", + "weight": 53, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-mfa-challenge.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-mfa-challenge.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{userId}", + "scope": "account", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "factor": { + "type": "string", + "description": "Factor used for verification. Must be one of following: `email`, `phone`, `totp`, `recoveryCode`.", + "default": null, + "x-example": "email", + "enum": [ + "email", + "phone", + "totp", + "recoverycode" + ], + "x-enum-name": "AuthenticationFactor", + "x-enum-keys": [] + } + }, + "required": [ + "factor" + ] + } + } + ] + }, + "put": { + "summary": "Update MFA challenge (confirmation)", + "operationId": "accountUpdateMfaChallenge", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Complete the MFA challenge by providing the one-time password. Finish the process of MFA verification by providing the one-time password. To begin the flow, use [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method.", + "responses": { + "200": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "updateMfaChallenge", + "group": "mfa", + "weight": 54, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-mfa-challenge.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa-challenge.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},challengeId:{param-challengeId}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "challengeId": { + "type": "string", + "description": "ID of the challenge.", + "default": null, + "x-example": "<CHALLENGE_ID>" + }, + "otp": { + "type": "string", + "description": "Valid verification token.", + "default": null, + "x-example": "<OTP>" + } + }, + "required": [ + "challengeId", + "otp" + ] + } + } + ] + } + }, + "\/account\/mfa\/factors": { + "get": { + "summary": "List factors", + "operationId": "accountListMfaFactors", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "List the factors available on the account to be used as a MFA challange.", + "responses": { + "200": { + "description": "MFAFactors", + "schema": { + "$ref": "#\/definitions\/mfaFactors" + } + } + }, + "x-appwrite": { + "method": "listMfaFactors", + "group": "mfa", + "weight": 46, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-mfa-factors.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-mfa-factors.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/account\/mfa\/recovery-codes": { + "get": { + "summary": "List MFA recovery codes", + "operationId": "accountGetMfaRecoveryCodes", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get recovery codes that can be used as backup for MFA flow. Before getting codes, they must be generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method. An OTP challenge is required to read recovery codes.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "schema": { + "$ref": "#\/definitions\/mfaRecoveryCodes" + } + } + }, + "x-appwrite": { + "method": "getMfaRecoveryCodes", + "group": "mfa", + "weight": 51, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "post": { + "summary": "Create MFA recovery codes", + "operationId": "accountCreateMfaRecoveryCodes", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Generate recovery codes as backup for MFA flow. It's recommended to generate and show then immediately after user successfully adds their authehticator. Recovery codes can be used as a MFA verification type in [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method.", + "responses": { + "201": { + "description": "MFA Recovery Codes", + "schema": { + "$ref": "#\/definitions\/mfaRecoveryCodes" + } + } + }, + "x-appwrite": { + "method": "createMfaRecoveryCodes", + "group": "mfa", + "weight": 49, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "patch": { + "summary": "Update MFA recovery codes (regenerate)", + "operationId": "accountUpdateMfaRecoveryCodes", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Regenerate recovery codes that can be used as backup for MFA flow. Before regenerating codes, they must be first generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method. An OTP challenge is required to regenreate recovery codes.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "schema": { + "$ref": "#\/definitions\/mfaRecoveryCodes" + } + } + }, + "x-appwrite": { + "method": "updateMfaRecoveryCodes", + "group": "mfa", + "weight": 50, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/account\/name": { + "patch": { + "summary": "Update name", + "operationId": "accountUpdateName", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Update currently logged in user account name.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateName", + "group": "account", + "weight": 33, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-name.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-name.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + } + }, + "required": [ + "name" + ] + } + } + ] + } + }, + "\/account\/password": { + "patch": { + "summary": "Update password", + "operationId": "accountUpdatePassword", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Update currently logged in user password. For validation, user is required to pass in the new password, and the old password. For users created with OAuth, Team Invites and Magic URL, oldPassword is optional.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updatePassword", + "group": "account", + "weight": 34, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-password.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-password.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "password": { + "type": "string", + "description": "New user password. Must be at least 8 chars.", + "default": null, + "x-example": null + }, + "oldPassword": { + "type": "string", + "description": "Current user password. Must be at least 8 chars.", + "default": "", + "x-example": "password" + } + }, + "required": [ + "password" + ] + } + } + ] + } + }, + "\/account\/phone": { + "patch": { + "summary": "Update phone", + "operationId": "accountUpdatePhone", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Update the currently logged in user's phone number. After updating the phone number, the phone verification status will be reset. A confirmation SMS is not sent automatically, however you can use the [POST \/account\/verification\/phone](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createPhoneVerification) endpoint to send a confirmation SMS.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updatePhone", + "group": "account", + "weight": 36, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-phone.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-phone.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "default": null, + "x-example": "+12065550100" + }, + "password": { + "type": "string", + "description": "User password. Must be at least 8 chars.", + "default": null, + "x-example": "password" + } + }, + "required": [ + "phone", + "password" + ] + } + } + ] + } + }, + "\/account\/prefs": { + "get": { + "summary": "Get account preferences", + "operationId": "accountGetPrefs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get the preferences as a key-value object for the currently logged in user.", + "responses": { + "200": { + "description": "Preferences", + "schema": { + "$ref": "#\/definitions\/preferences" + } + } + }, + "x-appwrite": { + "method": "getPrefs", + "group": "account", + "weight": 31, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "patch": { + "summary": "Update preferences", + "operationId": "accountUpdatePrefs", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Update currently logged in user account preferences. The object you pass is stored as is, and replaces any previous value. The maximum allowed prefs size is 64kB and throws error if exceeded.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updatePrefs", + "group": "account", + "weight": 37, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "prefs": { + "type": "object", + "description": "Prefs key-value JSON object.", + "default": {}, + "x-example": "{}" + } + }, + "required": [ + "prefs" + ] + } + } + ] + } + }, + "\/account\/recovery": { + "post": { + "summary": "Create password recovery", + "operationId": "accountCreateRecovery", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Sends the user an email with a temporary secret key for password reset. When the user clicks the confirmation link he is redirected back to your app password reset URL with the secret key and email address values attached to the URL query string. Use the query string params to submit a request to the [PUT \/account\/recovery](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updateRecovery) endpoint to complete the process. The verification link sent to the user's email address is valid for 1 hour.", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createRecovery", + "group": "recovery", + "weight": 39, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-recovery.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-recovery.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},email:{param-email}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the recovery email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "default": null, + "x-example": "https:\/\/example.com" + } + }, + "required": [ + "email", + "url" + ] + } + } + ] + }, + "put": { + "summary": "Update password recovery (confirmation)", + "operationId": "accountUpdateRecovery", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to complete the user account password reset. Both the **userId** and **secret** arguments will be passed as query parameters to the redirect URL you have provided when sending your request to the [POST \/account\/recovery](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createRecovery) endpoint.\n\nPlease note that in order to avoid a [Redirect Attack](https:\/\/github.com\/OWASP\/CheatSheetSeries\/blob\/master\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) the only valid redirect URLs are the ones from domains you have set when adding your platforms in the console interface.", + "responses": { + "200": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "updateRecovery", + "group": "recovery", + "weight": 40, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-recovery.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-recovery.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid reset token.", + "default": null, + "x-example": "<SECRET>" + }, + "password": { + "type": "string", + "description": "New user password. Must be between 8 and 256 chars.", + "default": null, + "x-example": null + } + }, + "required": [ + "userId", + "secret", + "password" + ] + } + } + ] + } + }, + "\/account\/sessions": { + "get": { + "summary": "List sessions", + "operationId": "accountListSessions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Get the list of active sessions across different devices for the currently logged in user.", + "responses": { + "200": { + "description": "Sessions List", + "schema": { + "$ref": "#\/definitions\/sessionList" + } + } + }, + "x-appwrite": { + "method": "listSessions", + "group": "sessions", + "weight": 12, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/list-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/list-sessions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "delete": { + "summary": "Delete sessions", + "operationId": "accountDeleteSessions", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "account" + ], + "description": "Delete all sessions from the user account and remove any sessions cookies from the end client.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSessions", + "group": "sessions", + "weight": 13, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-sessions.md", + "rate-limit": 100, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/account\/sessions\/anonymous": { + "post": { + "summary": "Create anonymous session", + "operationId": "accountCreateAnonymousSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to allow a new user to register an anonymous account in your project. This route will also create a new session for the user. To allow the new user to convert an anonymous account to a normal account, you need to update its [email and password](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updateEmail) or create an [OAuth2 session](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#CreateOAuth2Session).", + "responses": { + "201": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "createAnonymousSession", + "group": "sessions", + "weight": 18, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-anonymous-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session-anonymous.md", + "rate-limit": 50, + "rate-time": 3600, + "rate-key": "ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ] + } + }, + "\/account\/sessions\/email": { + "post": { + "summary": "Create email password session", + "operationId": "accountCreateEmailPasswordSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Allow the user to login into their account by providing a valid email and password combination. This route will create a new session for the user.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "201": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "createEmailPasswordSession", + "group": "sessions", + "weight": 17, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-email-password-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session-email-password.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},email:{param-email}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password. Must be at least 8 chars.", + "default": null, + "x-example": "password" + } + }, + "required": [ + "email", + "password" + ] + } + } + ] + } + }, + "\/account\/sessions\/magic-url": { + "put": { + "summary": "Update magic URL session", + "operationId": "accountUpdateMagicURLSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to create a session from token. Provide the **userId** and **secret** parameters from the successful response of authentication flows initiated by token creation. For example, magic URL and phone login.", + "responses": { + "201": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "updateMagicURLSession", + "group": "sessions", + "weight": 27, + "cookies": false, + "type": "", + "deprecated": true, + "demo": "account\/update-magic-u-r-l-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "ip:{ip},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "default": null, + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + ] + } + }, + "\/account\/sessions\/phone": { + "put": { + "summary": "Update phone session", + "operationId": "accountUpdatePhoneSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to create a session from token. Provide the **userId** and **secret** parameters from the successful response of authentication flows initiated by token creation. For example, magic URL and phone login.", + "responses": { + "201": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "updatePhoneSession", + "group": "sessions", + "weight": 28, + "cookies": false, + "type": "", + "deprecated": true, + "demo": "account\/update-phone-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "ip:{ip},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "default": null, + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + ] + } + }, + "\/account\/sessions\/token": { + "post": { + "summary": "Create session", + "operationId": "accountCreateSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to create a session from token. Provide the **userId** and **secret** parameters from the successful response of authentication flows initiated by token creation. For example, magic URL and phone login.", + "responses": { + "201": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "createSession", + "group": "sessions", + "weight": 19, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "ip:{ip},userId:{param-userId}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Secret of a token generated by login methods. For example, the `createMagicURLToken` or `createPhoneToken` methods.", + "default": null, + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + ] + } + }, + "\/account\/sessions\/{sessionId}": { + "get": { + "summary": "Get session", + "operationId": "accountGetSession", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to get a logged in user's session using a Session ID. Inputting 'current' will return the current session being used.", + "responses": { + "200": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "getSession", + "group": "sessions", + "weight": 14, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/get-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/get-session.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "description": "Session ID. Use the string 'current' to get the current device session.", + "required": true, + "type": "string", + "x-example": "<SESSION_ID>", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update session", + "operationId": "accountUpdateSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to extend a session's length. Extending a session is useful when session expiry is short. If the session was created using an OAuth provider, this endpoint refreshes the access token from the provider.", + "responses": { + "200": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "updateSession", + "group": "sessions", + "weight": 16, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-session.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "description": "Session ID. Use the string 'current' to update the current device session.", + "required": true, + "type": "string", + "x-example": "<SESSION_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete session", + "operationId": "accountDeleteSession", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "account" + ], + "description": "Logout the user. Use 'current' as the session ID to logout on this device, use a session ID to logout on another device. If you're looking to logout the user on all devices, use [Delete Sessions](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#deleteSessions) instead.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSession", + "group": "sessions", + "weight": 15, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/delete-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/delete-session.md", + "rate-limit": 100, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "sessionId", + "description": "Session ID. Use the string 'current' to delete the current device session.", + "required": true, + "type": "string", + "x-example": "<SESSION_ID>", + "in": "path" + } + ] + } + }, + "\/account\/status": { + "patch": { + "summary": "Update status", + "operationId": "accountUpdateStatus", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Block the currently logged in user account. Behind the scene, the user record is not deleted but permanently blocked from any access. To completely delete a user, use the Users API instead.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateStatus", + "group": "account", + "weight": 38, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + } + }, + "\/account\/tokens\/email": { + "post": { + "summary": "Create email token (OTP)", + "operationId": "accountCreateEmailToken", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not be registered, a new user will be created. Use the returned user ID and secret and submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The secret sent to the user's email is valid for 15 minutes.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createEmailToken", + "group": "tokens", + "weight": 26, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-email-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-email.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},email:{param-email}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "phrase": { + "type": "boolean", + "description": "Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.", + "default": false, + "x-example": false + } + }, + "required": [ + "userId", + "email" + ] + } + } + ] + } + }, + "\/account\/tokens\/magic-url": { + "post": { + "summary": "Create magic URL token", + "operationId": "accountCreateMagicURLToken", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Sends the user an email with a secret key for creating a session. If the provided user ID has not been registered, a new user will be created. When the user clicks the link in the email, the user is redirected back to the URL you provided with the secret key and userId values attached to the URL query string. Use the query string parameters to submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The link sent to the user's email address is valid for 1 hour.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).\n", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createMagicURLToken", + "group": "tokens", + "weight": 25, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-magic-u-r-l-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-magic-url.md", + "rate-limit": 60, + "rate-time": 3600, + "rate-key": [ + "url:{url},email:{param-email}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the magic URL login. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "default": "", + "x-example": "https:\/\/example.com" + }, + "phrase": { + "type": "boolean", + "description": "Toggle for security phrase. If enabled, email will be send with a randomly generated phrase and the phrase will also be included in the response. Confirming phrases match increases the security of your authentication flow.", + "default": false, + "x-example": false + } + }, + "required": [ + "userId", + "email" + ] + } + } + ] + } + }, + "\/account\/tokens\/oauth2\/{provider}": { + "get": { + "summary": "Create OAuth2 token", + "operationId": "accountCreateOAuth2Token", + "consumes": [], + "produces": [ + "text\/html" + ], + "tags": [ + "account" + ], + "description": "Allow the user to login to their account using the OAuth2 provider of their choice. Each OAuth2 provider should be enabled from the Appwrite console first. Use the success and failure arguments to provide a redirect URL's back to your app when login is completed. \n\nIf authentication succeeds, `userId` and `secret` of a token will be appended to the success URL as query parameters. These can be used to create a new session using the [Create session](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "301": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "createOAuth2Token", + "group": "tokens", + "weight": 24, + "cookies": false, + "type": "webAuth", + "deprecated": false, + "demo": "account\/create-o-auth2token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-oauth2.md", + "rate-limit": 50, + "rate-time": 3600, + "rate-key": "ip:{ip}", + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "provider", + "description": "OAuth2 Provider. Currently, supported providers are: amazon, apple, auth0, authentik, autodesk, bitbucket, bitly, box, dailymotion, discord, disqus, dropbox, etsy, facebook, figma, github, gitlab, google, linkedin, microsoft, notion, oidc, okta, paypal, paypalSandbox, podio, salesforce, slack, spotify, stripe, tradeshift, tradeshiftBox, twitch, wordpress, yahoo, yammer, yandex, zoho, zoom.", + "required": true, + "type": "string", + "x-example": "amazon", + "enum": [ + "amazon", + "apple", + "auth0", + "authentik", + "autodesk", + "bitbucket", + "bitly", + "box", + "dailymotion", + "discord", + "disqus", + "dropbox", + "etsy", + "facebook", + "figma", + "github", + "gitlab", + "google", + "linkedin", + "microsoft", + "notion", + "oidc", + "okta", + "paypal", + "paypalSandbox", + "podio", + "salesforce", + "slack", + "spotify", + "stripe", + "tradeshift", + "tradeshiftBox", + "twitch", + "wordpress", + "yahoo", + "yammer", + "yandex", + "zoho", + "zoom", + "mock" + ], + "x-enum-name": "OAuthProvider", + "x-enum-keys": [], + "in": "path" + }, + { + "name": "success", + "description": "URL to redirect back to your app after a successful login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "", + "in": "query" + }, + { + "name": "failure", + "description": "URL to redirect back to your app after a failed login attempt. Only URLs from hostnames in your project's platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "required": false, + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "default": "", + "in": "query" + }, + { + "name": "scopes", + "description": "A list of custom OAuth2 scopes. Check each provider internal docs for a list of supported scopes. Maximum of 100 scopes are allowed, each 4096 characters long.", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/account\/tokens\/phone": { + "post": { + "summary": "Create phone token", + "operationId": "accountCreatePhoneToken", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Sends the user an SMS with a secret key for creating a session. If the provided user ID has not be registered, a new user will be created. Use the returned user ID and secret and submit a request to the [POST \/v1\/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process. The secret sent to the user's phone is valid for 15 minutes.\n\nA user is limited to 10 active sessions at a time by default. [Learn more about session limits](https:\/\/appwrite.io\/docs\/authentication-security#limits).", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createPhoneToken", + "group": "tokens", + "weight": 29, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-phone-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-token-phone.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},phone:{param-phone}", + "url:{url},ip:{ip}" + ], + "scope": "sessions.write", + "platforms": [ + "server", + "client" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "default": null, + "x-example": "+12065550100" + } + }, + "required": [ + "userId", + "phone" + ] + } + } + ] + } + }, + "\/account\/verification": { + "post": { + "summary": "Create email verification", + "operationId": "accountCreateVerification", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to send a verification message to your user email address to confirm they are the valid owners of that address. Both the **userId** and **secret** arguments will be passed as query parameters to the URL you have provided to be attached to the verification email. The provided URL should redirect the user back to your app and allow you to complete the verification process by verifying both the **userId** and **secret** parameters. Learn more about how to [complete the verification process](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updateVerification). The verification link sent to the user's email address is valid for 7 days.\n\nPlease note that in order to avoid a [Redirect Attack](https:\/\/github.com\/OWASP\/CheatSheetSeries\/blob\/master\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md), the only valid redirect URLs are the ones from domains you have set when adding your platforms in the console interface.\n", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createVerification", + "group": "verification", + "weight": 41, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-email-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{userId}", + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the verification email. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "default": null, + "x-example": "https:\/\/example.com" + } + }, + "required": [ + "url" + ] + } + } + ] + }, + "put": { + "summary": "Update email verification (confirmation)", + "operationId": "accountUpdateVerification", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to complete the user email verification process. Use both the **userId** and **secret** parameters that were attached to your app URL to verify the user email ownership. If confirmed this route will return a 200 status code.", + "responses": { + "200": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "updateVerification", + "group": "verification", + "weight": 42, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-email-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},userId:{param-userId}", + "scope": "public", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "default": null, + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + ] + } + }, + "\/account\/verification\/phone": { + "post": { + "summary": "Create phone verification", + "operationId": "accountCreatePhoneVerification", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to send a verification SMS to the currently logged in user. This endpoint is meant for use after updating a user's phone number using the [accountUpdatePhone](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updatePhone) endpoint. Learn more about how to [complete the verification process](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#updatePhoneVerification). The verification code sent to the user's phone number is valid for 15 minutes.", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createPhoneVerification", + "group": "verification", + "weight": 43, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/create-phone-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/create-phone-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": [ + "url:{url},userId:{userId}", + "url:{url},ip:{ip}" + ], + "scope": "account", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ] + }, + "put": { + "summary": "Update phone verification (confirmation)", + "operationId": "accountUpdatePhoneVerification", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "account" + ], + "description": "Use this endpoint to complete the user phone verification process. Use the **userId** and **secret** that were sent to your user's phone number to verify the user email ownership. If confirmed this route will return a 200 status code.", + "responses": { + "200": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "updatePhoneVerification", + "group": "verification", + "weight": 44, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "account\/update-phone-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/account\/update-phone-verification.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "userId:{param-userId}", + "scope": "public", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Valid verification token.", + "default": null, + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + ] + } + }, + "\/avatars\/browsers\/{code}": { + "get": { + "summary": "Get browser icon", + "operationId": "avatarsGetBrowser", + "consumes": [], + "produces": [ + "image\/png" + ], + "tags": [ + "avatars" + ], + "description": "You can use this endpoint to show different browser icons to your users. The code argument receives the browser code as it appears in your user [GET \/account\/sessions](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#getSessions) endpoint. Use width, height and quality arguments to change the output settings.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getBrowser", + "group": null, + "weight": 61, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-browser.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-browser.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "code", + "description": "Browser Code.", + "required": true, + "type": "string", + "x-example": "aa", + "enum": [ + "aa", + "an", + "ch", + "ci", + "cm", + "cr", + "ff", + "sf", + "mf", + "ps", + "oi", + "om", + "op", + "on" + ], + "x-enum-name": "Browser", + "x-enum-keys": [ + "Avant Browser", + "Android WebView Beta", + "Google Chrome", + "Google Chrome (iOS)", + "Google Chrome (Mobile)", + "Chromium", + "Mozilla Firefox", + "Safari", + "Mobile Safari", + "Microsoft Edge", + "Microsoft Edge (iOS)", + "Opera Mini", + "Opera", + "Opera (Next)" + ], + "in": "path" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + }, + { + "name": "quality", + "description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1, + "in": "query" + } + ] + } + }, + "\/avatars\/credit-cards\/{code}": { + "get": { + "summary": "Get credit card icon", + "operationId": "avatarsGetCreditCard", + "consumes": [], + "produces": [ + "image\/png" + ], + "tags": [ + "avatars" + ], + "description": "The credit card endpoint will return you the icon of the credit card provider you need. Use width, height and quality arguments to change the output settings.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.\n", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getCreditCard", + "group": null, + "weight": 60, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-credit-card.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-credit-card.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "code", + "description": "Credit Card Code. Possible values: amex, argencard, cabal, cencosud, diners, discover, elo, hipercard, jcb, mastercard, naranja, targeta-shopping, union-china-pay, visa, mir, maestro, rupay.", + "required": true, + "type": "string", + "x-example": "amex", + "enum": [ + "amex", + "argencard", + "cabal", + "cencosud", + "diners", + "discover", + "elo", + "hipercard", + "jcb", + "mastercard", + "naranja", + "targeta-shopping", + "union-china-pay", + "visa", + "mir", + "maestro", + "rupay" + ], + "x-enum-name": "CreditCard", + "x-enum-keys": [ + "American Express", + "Argencard", + "Cabal", + "Cencosud", + "Diners Club", + "Discover", + "Elo", + "Hipercard", + "JCB", + "Mastercard", + "Naranja", + "Tarjeta Shopping", + "Union China Pay", + "Visa", + "MIR", + "Maestro", + "Rupay" + ], + "in": "path" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + }, + { + "name": "quality", + "description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1, + "in": "query" + } + ] + } + }, + "\/avatars\/favicon": { + "get": { + "summary": "Get favicon", + "operationId": "avatarsGetFavicon", + "consumes": [], + "produces": [ + "image\/*" + ], + "tags": [ + "avatars" + ], + "description": "Use this endpoint to fetch the favorite icon (AKA favicon) of any remote website URL.\n\nThis endpoint does not follow HTTP redirects.", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getFavicon", + "group": null, + "weight": 64, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-favicon.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-favicon.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "url", + "description": "Website URL which you want to fetch the favicon from.", + "required": true, + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "in": "query" + } + ] + } + }, + "\/avatars\/flags\/{code}": { + "get": { + "summary": "Get country flag", + "operationId": "avatarsGetFlag", + "consumes": [], + "produces": [ + "image\/png" + ], + "tags": [ + "avatars" + ], + "description": "You can use this endpoint to show different country flags icons to your users. The code argument receives the 2 letter country code. Use width, height and quality arguments to change the output settings. Country codes follow the [ISO 3166-1](https:\/\/en.wikipedia.org\/wiki\/ISO_3166-1) standard.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.\n", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getFlag", + "group": null, + "weight": 62, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-flag.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-flag.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "code", + "description": "Country Code. ISO Alpha-2 country code format.", + "required": true, + "type": "string", + "x-example": "af", + "enum": [ + "af", + "ao", + "al", + "ad", + "ae", + "ar", + "am", + "ag", + "au", + "at", + "az", + "bi", + "be", + "bj", + "bf", + "bd", + "bg", + "bh", + "bs", + "ba", + "by", + "bz", + "bo", + "br", + "bb", + "bn", + "bt", + "bw", + "cf", + "ca", + "ch", + "cl", + "cn", + "ci", + "cm", + "cd", + "cg", + "co", + "km", + "cv", + "cr", + "cu", + "cy", + "cz", + "de", + "dj", + "dm", + "dk", + "do", + "dz", + "ec", + "eg", + "er", + "es", + "ee", + "et", + "fi", + "fj", + "fr", + "fm", + "ga", + "gb", + "ge", + "gh", + "gn", + "gm", + "gw", + "gq", + "gr", + "gd", + "gt", + "gy", + "hn", + "hr", + "ht", + "hu", + "id", + "in", + "ie", + "ir", + "iq", + "is", + "il", + "it", + "jm", + "jo", + "jp", + "kz", + "ke", + "kg", + "kh", + "ki", + "kn", + "kr", + "kw", + "la", + "lb", + "lr", + "ly", + "lc", + "li", + "lk", + "ls", + "lt", + "lu", + "lv", + "ma", + "mc", + "md", + "mg", + "mv", + "mx", + "mh", + "mk", + "ml", + "mt", + "mm", + "me", + "mn", + "mz", + "mr", + "mu", + "mw", + "my", + "na", + "ne", + "ng", + "ni", + "nl", + "no", + "np", + "nr", + "nz", + "om", + "pk", + "pa", + "pe", + "ph", + "pw", + "pg", + "pl", + "pf", + "kp", + "pt", + "py", + "qa", + "ro", + "ru", + "rw", + "sa", + "sd", + "sn", + "sg", + "sb", + "sl", + "sv", + "sm", + "so", + "rs", + "ss", + "st", + "sr", + "sk", + "si", + "se", + "sz", + "sc", + "sy", + "td", + "tg", + "th", + "tj", + "tm", + "tl", + "to", + "tt", + "tn", + "tr", + "tv", + "tz", + "ug", + "ua", + "uy", + "us", + "uz", + "va", + "vc", + "ve", + "vn", + "vu", + "ws", + "ye", + "za", + "zm", + "zw" + ], + "x-enum-name": "Flag", + "x-enum-keys": [ + "Afghanistan", + "Angola", + "Albania", + "Andorra", + "United Arab Emirates", + "Argentina", + "Armenia", + "Antigua and Barbuda", + "Australia", + "Austria", + "Azerbaijan", + "Burundi", + "Belgium", + "Benin", + "Burkina Faso", + "Bangladesh", + "Bulgaria", + "Bahrain", + "Bahamas", + "Bosnia and Herzegovina", + "Belarus", + "Belize", + "Bolivia", + "Brazil", + "Barbados", + "Brunei Darussalam", + "Bhutan", + "Botswana", + "Central African Republic", + "Canada", + "Switzerland", + "Chile", + "China", + "C\u00f4te d'Ivoire", + "Cameroon", + "Democratic Republic of the Congo", + "Republic of the Congo", + "Colombia", + "Comoros", + "Cape Verde", + "Costa Rica", + "Cuba", + "Cyprus", + "Czech Republic", + "Germany", + "Djibouti", + "Dominica", + "Denmark", + "Dominican Republic", + "Algeria", + "Ecuador", + "Egypt", + "Eritrea", + "Spain", + "Estonia", + "Ethiopia", + "Finland", + "Fiji", + "France", + "Micronesia (Federated States of)", + "Gabon", + "United Kingdom", + "Georgia", + "Ghana", + "Guinea", + "Gambia", + "Guinea-Bissau", + "Equatorial Guinea", + "Greece", + "Grenada", + "Guatemala", + "Guyana", + "Honduras", + "Croatia", + "Haiti", + "Hungary", + "Indonesia", + "India", + "Ireland", + "Iran (Islamic Republic of)", + "Iraq", + "Iceland", + "Israel", + "Italy", + "Jamaica", + "Jordan", + "Japan", + "Kazakhstan", + "Kenya", + "Kyrgyzstan", + "Cambodia", + "Kiribati", + "Saint Kitts and Nevis", + "South Korea", + "Kuwait", + "Lao People's Democratic Republic", + "Lebanon", + "Liberia", + "Libya", + "Saint Lucia", + "Liechtenstein", + "Sri Lanka", + "Lesotho", + "Lithuania", + "Luxembourg", + "Latvia", + "Morocco", + "Monaco", + "Moldova", + "Madagascar", + "Maldives", + "Mexico", + "Marshall Islands", + "North Macedonia", + "Mali", + "Malta", + "Myanmar", + "Montenegro", + "Mongolia", + "Mozambique", + "Mauritania", + "Mauritius", + "Malawi", + "Malaysia", + "Namibia", + "Niger", + "Nigeria", + "Nicaragua", + "Netherlands", + "Norway", + "Nepal", + "Nauru", + "New Zealand", + "Oman", + "Pakistan", + "Panama", + "Peru", + "Philippines", + "Palau", + "Papua New Guinea", + "Poland", + "French Polynesia", + "North Korea", + "Portugal", + "Paraguay", + "Qatar", + "Romania", + "Russia", + "Rwanda", + "Saudi Arabia", + "Sudan", + "Senegal", + "Singapore", + "Solomon Islands", + "Sierra Leone", + "El Salvador", + "San Marino", + "Somalia", + "Serbia", + "South Sudan", + "Sao Tome and Principe", + "Suriname", + "Slovakia", + "Slovenia", + "Sweden", + "Eswatini", + "Seychelles", + "Syria", + "Chad", + "Togo", + "Thailand", + "Tajikistan", + "Turkmenistan", + "Timor-Leste", + "Tonga", + "Trinidad and Tobago", + "Tunisia", + "Turkey", + "Tuvalu", + "Tanzania", + "Uganda", + "Ukraine", + "Uruguay", + "United States", + "Uzbekistan", + "Vatican City", + "Saint Vincent and the Grenadines", + "Venezuela", + "Vietnam", + "Vanuatu", + "Samoa", + "Yemen", + "South Africa", + "Zambia", + "Zimbabwe" + ], + "in": "path" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 100, + "in": "query" + }, + { + "name": "quality", + "description": "Image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1, + "in": "query" + } + ] + } + }, + "\/avatars\/image": { + "get": { + "summary": "Get image from URL", + "operationId": "avatarsGetImage", + "consumes": [], + "produces": [ + "image\/*" + ], + "tags": [ + "avatars" + ], + "description": "Use this endpoint to fetch a remote image URL and crop it to any image size you want. This endpoint is very useful if you need to crop and display remote images in your app or in case you want to make sure a 3rd party image is properly served using a TLS protocol.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 400x400px.\n\nThis endpoint does not follow HTTP redirects.", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getImage", + "group": null, + "weight": 63, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-image.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-image.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "url", + "description": "Image URL which you want to crop.", + "required": true, + "type": "string", + "format": "url", + "x-example": "https:\/\/example.com", + "in": "query" + }, + { + "name": "width", + "description": "Resize preview image width, Pass an integer between 0 to 2000. Defaults to 400.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 400, + "in": "query" + }, + { + "name": "height", + "description": "Resize preview image height, Pass an integer between 0 to 2000. Defaults to 400.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 400, + "in": "query" + } + ] + } + }, + "\/avatars\/initials": { + "get": { + "summary": "Get user initials", + "operationId": "avatarsGetInitials", + "consumes": [], + "produces": [ + "image\/png" + ], + "tags": [ + "avatars" + ], + "description": "Use this endpoint to show your user initials avatar icon on your website or app. By default, this route will try to print your logged-in user name or email initials. You can also overwrite the user name if you pass the 'name' parameter. If no name is given and no user is logged, an empty avatar will be returned.\n\nYou can use the color and background params to change the avatar colors. By default, a random theme will be selected. The random theme will persist for the user's initials when reloading the same theme will always return for the same initials.\n\nWhen one dimension is specified and the other is 0, the image is scaled with preserved aspect ratio. If both dimensions are 0, the API provides an image at source quality. If dimensions are not specified, the default size of image returned is 100x100px.\n", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getInitials", + "group": null, + "weight": 66, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-initials.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-initials.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "name", + "description": "Full Name. When empty, current user name or email will be used. Max length: 128 chars.", + "required": false, + "type": "string", + "x-example": "<NAME>", + "default": "", + "in": "query" + }, + { + "name": "width", + "description": "Image width. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 500, + "in": "query" + }, + { + "name": "height", + "description": "Image height. Pass an integer between 0 to 2000. Defaults to 100.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 500, + "in": "query" + }, + { + "name": "background", + "description": "Changes background color. By default a random color will be picked and stay will persistent to the given name.", + "required": false, + "type": "string", + "default": "", + "in": "query" + } + ] + } + }, + "\/avatars\/qr": { + "get": { + "summary": "Get QR code", + "operationId": "avatarsGetQR", + "consumes": [], + "produces": [ + "image\/png" + ], + "tags": [ + "avatars" + ], + "description": "Converts a given plain text to a QR code image. You can use the query parameters to change the size and style of the resulting image.\n", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getQR", + "group": null, + "weight": 65, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "avatars\/get-q-r.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/avatars\/get-qr.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "avatars.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "text", + "description": "Plain text to be converted to QR code image.", + "required": true, + "type": "string", + "x-example": "<TEXT>", + "in": "query" + }, + { + "name": "size", + "description": "QR code size. Pass an integer between 1 to 1000. Defaults to 400.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 1, + "default": 400, + "in": "query" + }, + { + "name": "margin", + "description": "Margin from edge. Pass an integer between 0 to 10. Defaults to 1.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 1, + "in": "query" + }, + { + "name": "download", + "description": "Return resulting image with 'Content-Disposition: attachment ' headers for the browser to start downloading it. Pass 0 for no header, or 1 for otherwise. Default value is set to 0.", + "required": false, + "type": "boolean", + "x-example": false, + "default": false, + "in": "query" + } + ] + } + }, + "\/databases": { + "get": { + "summary": "List databases", + "operationId": "databasesList", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a list of all databases from the current Appwrite project. You can use the search parameter to filter your results.", + "responses": { + "200": { + "description": "Databases List", + "schema": { + "$ref": "#\/definitions\/databaseList" + } + } + }, + "x-appwrite": { + "method": "list", + "group": "databases", + "weight": 71, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create database", + "operationId": "databasesCreate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a new Database.\n", + "responses": { + "201": { + "description": "Database", + "schema": { + "$ref": "#\/definitions\/database" + } + } + }, + "x-appwrite": { + "method": "create", + "group": "databases", + "weight": 70, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "databaseId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<DATABASE_ID>" + }, + "name": { + "type": "string", + "description": "Database name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Is the database enabled? When set to 'disabled', users cannot access the database but Server SDKs with an API key can still read and write to the database. No data is lost when this is toggled.", + "default": true, + "x-example": false + } + }, + "required": [ + "databaseId", + "name" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}": { + "get": { + "summary": "Get database", + "operationId": "databasesGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a database by its unique ID. This endpoint response returns a JSON object with the database metadata.", + "responses": { + "200": { + "description": "Database", + "schema": { + "$ref": "#\/definitions\/database" + } + } + }, + "x-appwrite": { + "method": "get", + "group": "databases", + "weight": 72, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update database", + "operationId": "databasesUpdate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a database by its unique ID.", + "responses": { + "200": { + "description": "Database", + "schema": { + "$ref": "#\/definitions\/database" + } + } + }, + "x-appwrite": { + "method": "update", + "group": "databases", + "weight": 74, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Database name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Is database enabled? When set to 'disabled', users cannot access the database but Server SDKs with an API key can still read and write to the database. No data is lost when this is toggled.", + "default": true, + "x-example": false + } + }, + "required": [ + "name" + ] + } + } + ] + }, + "delete": { + "summary": "Delete database", + "operationId": "databasesDelete", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "databases" + ], + "description": "Delete a database by its unique ID. Only API keys with with databases.write scope can delete a database.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "databases", + "weight": 75, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "databases.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections": { + "get": { + "summary": "List collections", + "operationId": "databasesListCollections", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a list of all collections that belong to the provided databaseId. You can use the search parameter to filter your results.", + "responses": { + "200": { + "description": "Collections List", + "schema": { + "$ref": "#\/definitions\/collectionList" + } + } + }, + "x-appwrite": { + "method": "listCollections", + "group": "collections", + "weight": 77, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-collections.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-collections.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, enabled, documentSecurity", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create collection", + "operationId": "databasesCreateCollection", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a new Collection. Before using this route, you should create a new database resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "201": { + "description": "Collection", + "schema": { + "$ref": "#\/definitions\/collection" + } + } + }, + "x-appwrite": { + "method": "createCollection", + "group": "collections", + "weight": 76, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-collection.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-collection.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "collectionId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<COLLECTION_ID>" + }, + "name": { + "type": "string", + "description": "Collection name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, no user is granted with any permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "documentSecurity": { + "type": "boolean", + "description": "Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": false, + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Is collection enabled? When set to 'disabled', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.", + "default": true, + "x-example": false + } + }, + "required": [ + "collectionId", + "name" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}": { + "get": { + "summary": "Get collection", + "operationId": "databasesGetCollection", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a collection by its unique ID. This endpoint response returns a JSON object with the collection metadata.", + "responses": { + "200": { + "description": "Collection", + "schema": { + "$ref": "#\/definitions\/collection" + } + } + }, + "x-appwrite": { + "method": "getCollection", + "group": "collections", + "weight": 78, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-collection.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-collection.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update collection", + "operationId": "databasesUpdateCollection", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a collection by its unique ID.", + "responses": { + "200": { + "description": "Collection", + "schema": { + "$ref": "#\/definitions\/collection" + } + } + }, + "x-appwrite": { + "method": "updateCollection", + "group": "collections", + "weight": 80, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-collection.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-collection.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Collection name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "permissions": { + "type": "array", + "description": "An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "documentSecurity": { + "type": "boolean", + "description": "Enables configuring permissions for individual documents. A user needs one of document or collection level permissions to access a document. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": false, + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Is collection enabled? When set to 'disabled', users cannot access the collection but Server SDKs with and API key can still read and write to the collection. No data is lost when this is toggled.", + "default": true, + "x-example": false + } + }, + "required": [ + "name" + ] + } + } + ] + }, + "delete": { + "summary": "Delete collection", + "operationId": "databasesDeleteCollection", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "databases" + ], + "description": "Delete a collection by its unique ID. Only users with write permissions have access to delete this resource.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteCollection", + "group": "collections", + "weight": 81, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-collection.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-collection.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes": { + "get": { + "summary": "List attributes", + "operationId": "databasesListAttributes", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "List attributes in the collection.", + "responses": { + "200": { + "description": "Attributes List", + "schema": { + "$ref": "#\/definitions\/attributeList" + } + } + }, + "x-appwrite": { + "method": "listAttributes", + "group": "attributes", + "weight": 92, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-attributes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-attributes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: key, type, size, required, array, status, error", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/boolean": { + "post": { + "summary": "Create boolean attribute", + "operationId": "databasesCreateBooleanAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a boolean attribute.\n", + "responses": { + "202": { + "description": "AttributeBoolean", + "schema": { + "$ref": "#\/definitions\/attributeBoolean" + } + } + }, + "x-appwrite": { + "method": "createBooleanAttribute", + "group": "attributes", + "weight": 89, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-boolean-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-boolean-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "boolean", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": false + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "default": false, + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/boolean\/{key}": { + "patch": { + "summary": "Update boolean attribute", + "operationId": "databasesUpdateBooleanAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a boolean attribute. Changing the `default` value will not update already existing documents.", + "responses": { + "200": { + "description": "AttributeBoolean", + "schema": { + "$ref": "#\/definitions\/attributeBoolean" + } + } + }, + "x-appwrite": { + "method": "updateBooleanAttribute", + "group": "attributes", + "weight": 101, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-boolean-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-boolean-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "boolean", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": false, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/datetime": { + "post": { + "summary": "Create datetime attribute", + "operationId": "databasesCreateDatetimeAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a date time attribute according to the ISO 8601 standard.", + "responses": { + "202": { + "description": "AttributeDatetime", + "schema": { + "$ref": "#\/definitions\/attributeDatetime" + } + } + }, + "x-appwrite": { + "method": "createDatetimeAttribute", + "group": "attributes", + "weight": 90, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-datetime-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-datetime-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for the attribute in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. Cannot be set when attribute is required.", + "default": null, + "x-example": null + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "default": false, + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/datetime\/{key}": { + "patch": { + "summary": "Update dateTime attribute", + "operationId": "databasesUpdateDatetimeAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a date time attribute. Changing the `default` value will not update already existing documents.", + "responses": { + "200": { + "description": "AttributeDatetime", + "schema": { + "$ref": "#\/definitions\/attributeDatetime" + } + } + }, + "x-appwrite": { + "method": "updateDatetimeAttribute", + "group": "attributes", + "weight": 102, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-datetime-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-datetime-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": null, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/email": { + "post": { + "summary": "Create email attribute", + "operationId": "databasesCreateEmailAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create an email attribute.\n", + "responses": { + "202": { + "description": "AttributeEmail", + "schema": { + "$ref": "#\/definitions\/attributeEmail" + } + } + }, + "x-appwrite": { + "method": "createEmailAttribute", + "group": "attributes", + "weight": 83, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-email-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-email-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": "email@example.com" + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "default": false, + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/email\/{key}": { + "patch": { + "summary": "Update email attribute", + "operationId": "databasesUpdateEmailAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update an email attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeEmail", + "schema": { + "$ref": "#\/definitions\/attributeEmail" + } + } + }, + "x-appwrite": { + "method": "updateEmailAttribute", + "group": "attributes", + "weight": 95, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-email-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-email-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": "email@example.com", + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/enum": { + "post": { + "summary": "Create enum attribute", + "operationId": "databasesCreateEnumAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create an enumeration attribute. The `elements` param acts as a white-list of accepted values for this attribute. \n", + "responses": { + "202": { + "description": "AttributeEnum", + "schema": { + "$ref": "#\/definitions\/attributeEnum" + } + } + }, + "x-appwrite": { + "method": "createEnumAttribute", + "group": "attributes", + "weight": 84, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-enum-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-attribute-enum.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "elements": { + "type": "array", + "description": "Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of 100 elements are allowed, each 255 characters long.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": "<DEFAULT>" + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "default": false, + "x-example": false + } + }, + "required": [ + "key", + "elements", + "required" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/enum\/{key}": { + "patch": { + "summary": "Update enum attribute", + "operationId": "databasesUpdateEnumAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update an enum attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeEnum", + "schema": { + "$ref": "#\/definitions\/attributeEnum" + } + } + }, + "x-appwrite": { + "method": "updateEnumAttribute", + "group": "attributes", + "weight": 96, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-enum-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-enum-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "elements": { + "type": "array", + "description": "Array of elements in enumerated type. Uses length of longest element to determine size. Maximum of 100 elements are allowed, each 255 characters long.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": "<DEFAULT>", + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + }, + "required": [ + "elements", + "required", + "default" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/float": { + "post": { + "summary": "Create float attribute", + "operationId": "databasesCreateFloatAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a float attribute. Optionally, minimum and maximum values can be provided.\n", + "responses": { + "202": { + "description": "AttributeFloat", + "schema": { + "$ref": "#\/definitions\/attributeFloat" + } + } + }, + "x-appwrite": { + "method": "createFloatAttribute", + "group": "attributes", + "weight": 88, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-float-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-float-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "min": { + "type": "number", + "description": "Minimum value to enforce on new documents", + "default": null, + "x-example": null + }, + "max": { + "type": "number", + "description": "Maximum value to enforce on new documents", + "default": null, + "x-example": null + }, + "default": { + "type": "number", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": null + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "default": false, + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/float\/{key}": { + "patch": { + "summary": "Update float attribute", + "operationId": "databasesUpdateFloatAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a float attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeFloat", + "schema": { + "$ref": "#\/definitions\/attributeFloat" + } + } + }, + "x-appwrite": { + "method": "updateFloatAttribute", + "group": "attributes", + "weight": 100, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-float-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-float-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "min": { + "type": "number", + "description": "Minimum value to enforce on new documents", + "default": null, + "x-example": null + }, + "max": { + "type": "number", + "description": "Maximum value to enforce on new documents", + "default": null, + "x-example": null + }, + "default": { + "type": "number", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": null, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/integer": { + "post": { + "summary": "Create integer attribute", + "operationId": "databasesCreateIntegerAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create an integer attribute. Optionally, minimum and maximum values can be provided.\n", + "responses": { + "202": { + "description": "AttributeInteger", + "schema": { + "$ref": "#\/definitions\/attributeInteger" + } + } + }, + "x-appwrite": { + "method": "createIntegerAttribute", + "group": "attributes", + "weight": 87, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-integer-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-integer-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "min": { + "type": "integer", + "description": "Minimum value to enforce on new documents", + "default": null, + "x-example": null + }, + "max": { + "type": "integer", + "description": "Maximum value to enforce on new documents", + "default": null, + "x-example": null + }, + "default": { + "type": "integer", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": null + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "default": false, + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/integer\/{key}": { + "patch": { + "summary": "Update integer attribute", + "operationId": "databasesUpdateIntegerAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update an integer attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeInteger", + "schema": { + "$ref": "#\/definitions\/attributeInteger" + } + } + }, + "x-appwrite": { + "method": "updateIntegerAttribute", + "group": "attributes", + "weight": 99, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-integer-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-integer-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "min": { + "type": "integer", + "description": "Minimum value to enforce on new documents", + "default": null, + "x-example": null + }, + "max": { + "type": "integer", + "description": "Maximum value to enforce on new documents", + "default": null, + "x-example": null + }, + "default": { + "type": "integer", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": null, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/ip": { + "post": { + "summary": "Create IP address attribute", + "operationId": "databasesCreateIpAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create IP address attribute.\n", + "responses": { + "202": { + "description": "AttributeIP", + "schema": { + "$ref": "#\/definitions\/attributeIp" + } + } + }, + "x-appwrite": { + "method": "createIpAttribute", + "group": "attributes", + "weight": 85, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-ip-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-ip-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": null + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "default": false, + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/ip\/{key}": { + "patch": { + "summary": "Update IP address attribute", + "operationId": "databasesUpdateIpAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update an ip attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeIP", + "schema": { + "$ref": "#\/definitions\/attributeIp" + } + } + }, + "x-appwrite": { + "method": "updateIpAttribute", + "group": "attributes", + "weight": 97, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-ip-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-ip-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": null, + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/relationship": { + "post": { + "summary": "Create relationship attribute", + "operationId": "databasesCreateRelationshipAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create relationship attribute. [Learn more about relationship attributes](https:\/\/appwrite.io\/docs\/databases-relationships#relationship-attributes).\n", + "responses": { + "202": { + "description": "AttributeRelationship", + "schema": { + "$ref": "#\/definitions\/attributeRelationship" + } + } + }, + "x-appwrite": { + "method": "createRelationshipAttribute", + "group": "attributes", + "weight": 91, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-relationship-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-relationship-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "relatedCollectionId": { + "type": "string", + "description": "Related Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "default": null, + "x-example": "<RELATED_COLLECTION_ID>" + }, + "type": { + "type": "string", + "description": "Relation type", + "default": null, + "x-example": "oneToOne", + "enum": [ + "oneToOne", + "manyToOne", + "manyToMany", + "oneToMany" + ], + "x-enum-name": "RelationshipType", + "x-enum-keys": [] + }, + "twoWay": { + "type": "boolean", + "description": "Is Two Way?", + "default": false, + "x-example": false + }, + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "twoWayKey": { + "type": "string", + "description": "Two Way Attribute Key.", + "default": null, + "x-example": null + }, + "onDelete": { + "type": "string", + "description": "Constraints option", + "default": "restrict", + "x-example": "cascade", + "enum": [ + "cascade", + "restrict", + "setNull" + ], + "x-enum-name": "RelationMutate", + "x-enum-keys": [] + } + }, + "required": [ + "relatedCollectionId", + "type" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/string": { + "post": { + "summary": "Create string attribute", + "operationId": "databasesCreateStringAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a string attribute.\n", + "responses": { + "202": { + "description": "AttributeString", + "schema": { + "$ref": "#\/definitions\/attributeString" + } + } + }, + "x-appwrite": { + "method": "createStringAttribute", + "group": "attributes", + "weight": 82, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-string-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-string-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "size": { + "type": "integer", + "description": "Attribute size for text attributes, in number of characters.", + "default": null, + "x-example": 1 + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": "<DEFAULT>" + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "default": false, + "x-example": false + }, + "encrypt": { + "type": "boolean", + "description": "Toggle encryption for the attribute. Encryption enhances security by not storing any plain text values in the database. However, encrypted attributes cannot be queried.", + "default": false, + "x-example": false + } + }, + "required": [ + "key", + "size", + "required" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/string\/{key}": { + "patch": { + "summary": "Update string attribute", + "operationId": "databasesUpdateStringAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a string attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeString", + "schema": { + "$ref": "#\/definitions\/attributeString" + } + } + }, + "x-appwrite": { + "method": "updateStringAttribute", + "group": "attributes", + "weight": 94, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-string-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-string-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": "<DEFAULT>", + "x-nullable": true + }, + "size": { + "type": "integer", + "description": "Maximum size of the string attribute.", + "default": null, + "x-example": 1 + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/url": { + "post": { + "summary": "Create URL attribute", + "operationId": "databasesCreateUrlAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a URL attribute.\n", + "responses": { + "202": { + "description": "AttributeURL", + "schema": { + "$ref": "#\/definitions\/attributeUrl" + } + } + }, + "x-appwrite": { + "method": "createUrlAttribute", + "group": "attributes", + "weight": 86, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-url-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-url-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "default": null, + "x-example": null + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": "https:\/\/example.com" + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "default": false, + "x-example": false + } + }, + "required": [ + "key", + "required" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/url\/{key}": { + "patch": { + "summary": "Update URL attribute", + "operationId": "databasesUpdateUrlAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update an url attribute. Changing the `default` value will not update already existing documents.\n", + "responses": { + "200": { + "description": "AttributeURL", + "schema": { + "$ref": "#\/definitions\/attributeUrl" + } + } + }, + "x-appwrite": { + "method": "updateUrlAttribute", + "group": "attributes", + "weight": 98, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-url-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-url-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "required": { + "type": "boolean", + "description": "Is attribute required?", + "default": null, + "x-example": false + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "default": null, + "x-example": "https:\/\/example.com", + "x-nullable": true + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + }, + "required": [ + "required", + "default" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/{key}": { + "get": { + "summary": "Get attribute", + "operationId": "databasesGetAttribute", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get attribute by ID.", + "responses": { + "200": { + "description": "AttributeBoolean, or AttributeInteger, or AttributeFloat, or AttributeEmail, or AttributeEnum, or AttributeURL, or AttributeIP, or AttributeDatetime, or AttributeRelationship, or AttributeString", + "schema": { + "x-oneOf": [ + { + "$ref": "#\/definitions\/attributeBoolean" + }, + { + "$ref": "#\/definitions\/attributeInteger" + }, + { + "$ref": "#\/definitions\/attributeFloat" + }, + { + "$ref": "#\/definitions\/attributeEmail" + }, + { + "$ref": "#\/definitions\/attributeEnum" + }, + { + "$ref": "#\/definitions\/attributeUrl" + }, + { + "$ref": "#\/definitions\/attributeIp" + }, + { + "$ref": "#\/definitions\/attributeDatetime" + }, + { + "$ref": "#\/definitions\/attributeRelationship" + }, + { + "$ref": "#\/definitions\/attributeString" + } + ] + } + } + }, + "x-appwrite": { + "method": "getAttribute", + "group": "attributes", + "weight": 93, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete attribute", + "operationId": "databasesDeleteAttribute", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "databases" + ], + "description": "Deletes an attribute.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteAttribute", + "group": "attributes", + "weight": 104, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/attributes\/{key}\/relationship": { + "patch": { + "summary": "Update relationship attribute", + "operationId": "databasesUpdateRelationshipAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update relationship attribute. [Learn more about relationship attributes](https:\/\/appwrite.io\/docs\/databases-relationships#relationship-attributes).\n", + "responses": { + "200": { + "description": "AttributeRelationship", + "schema": { + "$ref": "#\/definitions\/attributeRelationship" + } + } + }, + "x-appwrite": { + "method": "updateRelationshipAttribute", + "group": "attributes", + "weight": 103, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-relationship-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-relationship-attribute.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Attribute Key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "onDelete": { + "type": "string", + "description": "Constraints option", + "default": null, + "x-example": "cascade", + "enum": [ + "cascade", + "restrict", + "setNull" + ], + "x-enum-name": "RelationMutate", + "x-enum-keys": [] + }, + "newKey": { + "type": "string", + "description": "New attribute key.", + "default": null, + "x-example": null + } + } + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents": { + "get": { + "summary": "List documents", + "operationId": "databasesListDocuments", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a list of all the user's documents in a given collection. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Documents List", + "schema": { + "$ref": "#\/definitions\/documentList" + } + } + }, + "x-appwrite": { + "method": "listDocuments", + "group": "documents", + "weight": 110, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-documents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-documents.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create document", + "operationId": "databasesCreateDocument", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "201": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "createDocument", + "group": "documents", + "weight": 109, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "methods": [ + { + "name": "createDocument", + "auth": { + "Session": [], + "Key": [], + "JWT": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documentId", + "data", + "permissions" + ], + "required": [ + "databaseId", + "collectionId", + "documentId", + "data" + ], + "responses": [ + { + "code": 201, + "model": "#\/definitions\/document" + } + ], + "description": "Create a new Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + }, + { + "name": "createDocuments", + "auth": { + "Key": [] + }, + "parameters": [ + "databaseId", + "collectionId", + "documents" + ], + "required": [ + "databaseId", + "collectionId", + "documents" + ], + "responses": [ + { + "code": 201, + "model": "#\/definitions\/documentList" + } + ], + "description": "Create new Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console." + } + ], + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection). Make sure to define attributes before creating documents.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "documentId": { + "type": "string", + "description": "Document ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": "", + "x-example": "<DOCUMENT_ID>" + }, + "data": { + "type": "object", + "description": "Document data as JSON object.", + "default": [], + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "documents": { + "type": "array", + "description": "Array of documents data as JSON objects.", + "default": [], + "x-example": null, + "items": { + "type": "object" + } + } + } + } + } + ] + }, + "put": { + "summary": "Create or update documents", + "operationId": "databasesUpsertDocuments", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create or update Documents. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.\n", + "responses": { + "200": { + "description": "Documents List", + "schema": { + "$ref": "#\/definitions\/documentList" + } + } + }, + "x-appwrite": { + "method": "upsertDocuments", + "group": "documents", + "weight": 118, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-documents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-documents.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "documents": { + "type": "array", + "description": "Array of document data as JSON objects. May contain partial documents.", + "default": null, + "x-example": null, + "items": { + "type": "object" + } + } + }, + "required": [ + "documents" + ] + } + } + ] + }, + "patch": { + "summary": "Update documents", + "operationId": "databasesUpdateDocuments", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update all documents that match your queries, if no queries are submitted then all documents are updated. You can pass only specific fields to be updated.", + "responses": { + "200": { + "description": "Documents List", + "schema": { + "$ref": "#\/definitions\/documentList" + } + } + }, + "x-appwrite": { + "method": "updateDocuments", + "group": "documents", + "weight": 117, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-documents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-documents.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include only attribute and value pairs to be updated.", + "default": [], + "x-example": "{}" + }, + "queries": { + "type": "array", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + } + } + } + } + ] + }, + "delete": { + "summary": "Delete documents", + "operationId": "databasesDeleteDocuments", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Bulk delete documents using queries, if no queries are passed then all documents are deleted.", + "responses": { + "200": { + "description": "Documents List", + "schema": { + "$ref": "#\/definitions\/documentList" + } + } + }, + "x-appwrite": { + "method": "deleteDocuments", + "group": "documents", + "weight": 120, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-documents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-documents.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "queries": { + "type": "array", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + } + } + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}": { + "get": { + "summary": "Get document", + "operationId": "databasesGetDocument", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get a document by its unique ID. This endpoint response returns a JSON object with the document data.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "getDocument", + "group": "documents", + "weight": 111, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-document.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "documents.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long.", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "put": { + "summary": "Upsert document", + "operationId": "databasesUpsertDocument", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Create or update a Document. Before using this route, you should create a new collection resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection) API or directly from your database console.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "upsertDocument", + "group": "documents", + "weight": 114, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/upsert-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/upsert-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include all required attributes of the document to be created or updated.", + "default": {}, + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "data" + ] + } + } + ] + }, + "patch": { + "summary": "Update document", + "operationId": "databasesUpdateDocument", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Update a document by its unique ID. Using the patch method you can pass only specific fields that will get updated.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "updateDocument", + "group": "documents", + "weight": 113, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/update-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/update-document.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "data": { + "type": "object", + "description": "Document data as JSON object. Include only attribute and value pairs to be updated.", + "default": [], + "x-example": "{}" + }, + "permissions": { + "type": "array", + "description": "An array of permissions strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + } + } + } + ] + }, + "delete": { + "summary": "Delete document", + "operationId": "databasesDeleteDocument", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "databases" + ], + "description": "Delete a document by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDocument", + "group": "documents", + "weight": 119, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-document.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-document.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/decrement": { + "patch": { + "summary": "Decrement document attribute", + "operationId": "databasesDecrementDocumentAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Decrement a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "decrementDocumentAttribute", + "group": "documents", + "weight": 116, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/decrement-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/decrement-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to decrement the attribute by. The value must be a number.", + "default": 1, + "x-example": null + }, + "min": { + "type": "mixed", + "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", + "default": null, + "x-example": null + } + } + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/increment": { + "patch": { + "summary": "Increment document attribute", + "operationId": "databasesIncrementDocumentAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Increment a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "incrementDocumentAttribute", + "group": "documents", + "weight": 115, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/increment-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/increment-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to increment the attribute by. The value must be a number.", + "default": 1, + "x-example": null + }, + "max": { + "type": "mixed", + "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", + "default": null, + "x-example": null + } + } + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/indexes": { + "get": { + "summary": "List indexes", + "operationId": "databasesListIndexes", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "List indexes in the collection.", + "responses": { + "200": { + "description": "Indexes List", + "schema": { + "$ref": "#\/definitions\/indexList" + } + } + }, + "x-appwrite": { + "method": "listIndexes", + "group": "indexes", + "weight": 106, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/list-indexes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/list-indexes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: key, type, status, attributes, error", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create index", + "operationId": "databasesCreateIndex", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Creates an index on the attributes listed. Your index should include all the attributes you will query in a single request.\nAttributes can be `key`, `fulltext`, and `unique`.", + "responses": { + "202": { + "description": "Index", + "schema": { + "$ref": "#\/definitions\/index" + } + } + }, + "x-appwrite": { + "method": "createIndex", + "group": "collections", + "weight": 105, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/create-index.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/create-index.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Index Key.", + "default": null, + "x-example": null + }, + "type": { + "type": "string", + "description": "Index type.", + "default": null, + "x-example": "key", + "enum": [ + "key", + "fulltext", + "unique" + ], + "x-enum-name": "IndexType", + "x-enum-keys": [] + }, + "attributes": { + "type": "array", + "description": "Array of attributes to index. Maximum of 100 attributes are allowed, each 32 characters long.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "orders": { + "type": "array", + "description": "Array of index orders. Maximum of 100 orders are allowed.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "lengths": { + "type": "array", + "description": "Length of index. Maximum of 100", + "default": [], + "x-example": null, + "items": { + "type": "integer" + } + } + }, + "required": [ + "key", + "type", + "attributes" + ] + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/indexes\/{key}": { + "get": { + "summary": "Get index", + "operationId": "databasesGetIndex", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Get index by ID.", + "responses": { + "200": { + "description": "Index", + "schema": { + "$ref": "#\/definitions\/index" + } + } + }, + "x-appwrite": { + "method": "getIndex", + "group": "indexes", + "weight": 107, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/get-index.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/get-index.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Index Key.", + "required": true, + "type": "string", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete index", + "operationId": "databasesDeleteIndex", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "databases" + ], + "description": "Delete an index.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteIndex", + "group": "indexes", + "weight": 108, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/delete-index.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/delete-index.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "collections.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID. You can create a new collection using the Database service [server integration](https:\/\/appwrite.io\/docs\/server\/databases#databasesCreateCollection).", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "key", + "description": "Index Key.", + "required": true, + "type": "string", + "in": "path" + } + ] + } + }, + "\/functions": { + "get": { + "summary": "List functions", + "operationId": "functionsList", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a list of all the project's functions. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Functions List", + "schema": { + "$ref": "#\/definitions\/functionList" + } + } + }, + "x-appwrite": { + "method": "list", + "group": "functions", + "weight": 378, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the project's functions. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, enabled, runtime, deploymentId, schedule, scheduleNext, schedulePrevious, timeout, entrypoint, commands, installationId", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create function", + "operationId": "functionsCreate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Create a new function. You can pass a list of [permissions](https:\/\/appwrite.io\/docs\/permissions) to allow different project users or team with access to execute the function using the client API.", + "responses": { + "201": { + "description": "Function", + "schema": { + "$ref": "#\/definitions\/function" + } + } + }, + "x-appwrite": { + "method": "create", + "group": "functions", + "weight": 375, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new function. You can pass a list of [permissions](https:\/\/appwrite.io\/docs\/permissions) to allow different project users or team with access to execute the function using the client API.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "functionId": { + "type": "string", + "description": "Function ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<FUNCTION_ID>" + }, + "name": { + "type": "string", + "description": "Function name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "runtime": { + "type": "string", + "description": "Execution runtime.", + "default": null, + "x-example": "node-14.5", + "enum": [ + "node-14.5", + "node-16.0", + "node-18.0", + "node-19.0", + "node-20.0", + "node-21.0", + "node-22", + "php-8.0", + "php-8.1", + "php-8.2", + "php-8.3", + "ruby-3.0", + "ruby-3.1", + "ruby-3.2", + "ruby-3.3", + "python-3.8", + "python-3.9", + "python-3.10", + "python-3.11", + "python-3.12", + "python-ml-3.11", + "python-ml-3.12", + "deno-1.21", + "deno-1.24", + "deno-1.35", + "deno-1.40", + "deno-1.46", + "deno-2.0", + "dart-2.15", + "dart-2.16", + "dart-2.17", + "dart-2.18", + "dart-2.19", + "dart-3.0", + "dart-3.1", + "dart-3.3", + "dart-3.5", + "dart-3.8", + "dotnet-6.0", + "dotnet-7.0", + "dotnet-8.0", + "java-8.0", + "java-11.0", + "java-17.0", + "java-18.0", + "java-21.0", + "java-22", + "swift-5.5", + "swift-5.8", + "swift-5.9", + "swift-5.10", + "kotlin-1.6", + "kotlin-1.8", + "kotlin-1.9", + "kotlin-2.0", + "cpp-17", + "cpp-20", + "bun-1.0", + "bun-1.1", + "go-1.23", + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29", + "flutter-3.32" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "execute": { + "type": "array", + "description": "An array of role strings with execution permissions. By default no user is granted with any execute permissions. [learn more about roles](https:\/\/appwrite.io\/docs\/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.", + "default": [], + "x-example": "[\"any\"]", + "items": { + "type": "string" + } + }, + "events": { + "type": "array", + "description": "Events list. Maximum of 100 events are allowed.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "schedule": { + "type": "string", + "description": "Schedule CRON syntax.", + "default": "", + "x-example": null + }, + "timeout": { + "type": "integer", + "description": "Function maximum execution time in seconds.", + "default": 15, + "x-example": 1 + }, + "enabled": { + "type": "boolean", + "description": "Is function enabled? When set to 'disabled', users cannot access the function but Server SDKs with and API key can still access the function. No data is lost when this is toggled.", + "default": true, + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", + "default": true, + "x-example": false + }, + "entrypoint": { + "type": "string", + "description": "Entrypoint File. This path is relative to the \"providerRootDirectory\".", + "default": "", + "x-example": "<ENTRYPOINT>" + }, + "commands": { + "type": "string", + "description": "Build Commands.", + "default": "", + "x-example": "<COMMANDS>" + }, + "scopes": { + "type": "array", + "description": "List of scopes allowed for API key auto-generated for every execution. Maximum of 100 scopes are allowed.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "installationId": { + "type": "string", + "description": "Appwrite Installation ID for VCS (Version Control System) deployment.", + "default": "", + "x-example": "<INSTALLATION_ID>" + }, + "providerRepositoryId": { + "type": "string", + "description": "Repository ID of the repo linked to the function.", + "default": "", + "x-example": "<PROVIDER_REPOSITORY_ID>" + }, + "providerBranch": { + "type": "string", + "description": "Production branch for the repo linked to the function.", + "default": "", + "x-example": "<PROVIDER_BRANCH>" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is the VCS (Version Control System) connection in silent mode for the repo linked to the function? In silent mode, comments will not be made on commits and pull requests.", + "default": false, + "x-example": false + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to function code in the linked repo.", + "default": "", + "x-example": "<PROVIDER_ROOT_DIRECTORY>" + }, + "specification": { + "type": "string", + "description": "Runtime specification for the function and builds.", + "default": "s-1vcpu-512mb", + "x-example": null + } + }, + "required": [ + "functionId", + "name", + "runtime" + ] + } + } + ] + } + }, + "\/functions\/runtimes": { + "get": { + "summary": "List runtimes", + "operationId": "functionsListRuntimes", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a list of all runtimes that are currently active on your instance.", + "responses": { + "200": { + "description": "Runtimes List", + "schema": { + "$ref": "#\/definitions\/runtimeList" + } + } + }, + "x-appwrite": { + "method": "listRuntimes", + "group": "runtimes", + "weight": 380, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-runtimes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all runtimes that are currently active on your instance.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/functions\/specifications": { + "get": { + "summary": "List specifications", + "operationId": "functionsListSpecifications", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "List allowed function specifications for this instance.", + "responses": { + "200": { + "description": "Specifications List", + "schema": { + "$ref": "#\/definitions\/specificationList" + } + } + }, + "x-appwrite": { + "method": "listSpecifications", + "group": "runtimes", + "weight": 381, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-specifications.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList allowed function specifications for this instance.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/functions\/{functionId}": { + "get": { + "summary": "Get function", + "operationId": "functionsGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a function by its unique ID.", + "responses": { + "200": { + "description": "Function", + "schema": { + "$ref": "#\/definitions\/function" + } + } + }, + "x-appwrite": { + "method": "get", + "group": "functions", + "weight": 376, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update function", + "operationId": "functionsUpdate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Update function by its unique ID.", + "responses": { + "200": { + "description": "Function", + "schema": { + "$ref": "#\/definitions\/function" + } + } + }, + "x-appwrite": { + "method": "update", + "group": "functions", + "weight": 377, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/update.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate function by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Function name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "runtime": { + "type": "string", + "description": "Execution runtime.", + "default": "", + "x-example": "node-14.5", + "enum": [ + "node-14.5", + "node-16.0", + "node-18.0", + "node-19.0", + "node-20.0", + "node-21.0", + "node-22", + "php-8.0", + "php-8.1", + "php-8.2", + "php-8.3", + "ruby-3.0", + "ruby-3.1", + "ruby-3.2", + "ruby-3.3", + "python-3.8", + "python-3.9", + "python-3.10", + "python-3.11", + "python-3.12", + "python-ml-3.11", + "python-ml-3.12", + "deno-1.21", + "deno-1.24", + "deno-1.35", + "deno-1.40", + "deno-1.46", + "deno-2.0", + "dart-2.15", + "dart-2.16", + "dart-2.17", + "dart-2.18", + "dart-2.19", + "dart-3.0", + "dart-3.1", + "dart-3.3", + "dart-3.5", + "dart-3.8", + "dotnet-6.0", + "dotnet-7.0", + "dotnet-8.0", + "java-8.0", + "java-11.0", + "java-17.0", + "java-18.0", + "java-21.0", + "java-22", + "swift-5.5", + "swift-5.8", + "swift-5.9", + "swift-5.10", + "kotlin-1.6", + "kotlin-1.8", + "kotlin-1.9", + "kotlin-2.0", + "cpp-17", + "cpp-20", + "bun-1.0", + "bun-1.1", + "go-1.23", + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29", + "flutter-3.32" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "execute": { + "type": "array", + "description": "An array of role strings with execution permissions. By default no user is granted with any execute permissions. [learn more about roles](https:\/\/appwrite.io\/docs\/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.", + "default": [], + "x-example": "[\"any\"]", + "items": { + "type": "string" + } + }, + "events": { + "type": "array", + "description": "Events list. Maximum of 100 events are allowed.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "schedule": { + "type": "string", + "description": "Schedule CRON syntax.", + "default": "", + "x-example": null + }, + "timeout": { + "type": "integer", + "description": "Maximum execution time in seconds.", + "default": 15, + "x-example": 1 + }, + "enabled": { + "type": "boolean", + "description": "Is function enabled? When set to 'disabled', users cannot access the function but Server SDKs with and API key can still access the function. No data is lost when this is toggled.", + "default": true, + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", + "default": true, + "x-example": false + }, + "entrypoint": { + "type": "string", + "description": "Entrypoint File. This path is relative to the \"providerRootDirectory\".", + "default": "", + "x-example": "<ENTRYPOINT>" + }, + "commands": { + "type": "string", + "description": "Build Commands.", + "default": "", + "x-example": "<COMMANDS>" + }, + "scopes": { + "type": "array", + "description": "List of scopes allowed for API Key auto-generated for every execution. Maximum of 100 scopes are allowed.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "installationId": { + "type": "string", + "description": "Appwrite Installation ID for VCS (Version Controle System) deployment.", + "default": "", + "x-example": "<INSTALLATION_ID>" + }, + "providerRepositoryId": { + "type": "string", + "description": "Repository ID of the repo linked to the function", + "default": null, + "x-example": "<PROVIDER_REPOSITORY_ID>", + "x-nullable": true + }, + "providerBranch": { + "type": "string", + "description": "Production branch for the repo linked to the function", + "default": "", + "x-example": "<PROVIDER_BRANCH>" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is the VCS (Version Control System) connection in silent mode for the repo linked to the function? In silent mode, comments will not be made on commits and pull requests.", + "default": false, + "x-example": false + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to function code in the linked repo.", + "default": "", + "x-example": "<PROVIDER_ROOT_DIRECTORY>" + }, + "specification": { + "type": "string", + "description": "Runtime specification for the function and builds.", + "default": "s-1vcpu-512mb", + "x-example": null + } + }, + "required": [ + "name" + ] + } + } + ] + }, + "delete": { + "summary": "Delete function", + "operationId": "functionsDelete", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "functions" + ], + "description": "Delete a function by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "functions", + "weight": 379, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a function by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + } + ] + } + }, + "\/functions\/{functionId}\/deployment": { + "patch": { + "summary": "Update function's deployment", + "operationId": "functionsUpdateFunctionDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Update the function active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your function.", + "responses": { + "200": { + "description": "Function", + "schema": { + "$ref": "#\/definitions\/function" + } + } + }, + "x-appwrite": { + "method": "updateFunctionDeployment", + "group": "functions", + "weight": 384, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/update-function-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate the function active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your function.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "deploymentId": { + "type": "string", + "description": "Deployment ID.", + "default": null, + "x-example": "<DEPLOYMENT_ID>" + } + }, + "required": [ + "deploymentId" + ] + } + } + ] + } + }, + "\/functions\/{functionId}\/deployments": { + "get": { + "summary": "List deployments", + "operationId": "functionsListDeployments", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a list of all the function's code deployments. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Deployments List", + "schema": { + "$ref": "#\/definitions\/deploymentList" + } + } + }, + "x-appwrite": { + "method": "listDeployments", + "group": "deployments", + "weight": 385, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-deployments.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the function's code deployments. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create deployment", + "operationId": "functionsCreateDeployment", + "consumes": [ + "multipart\/form-data" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Create a new function code deployment. Use this endpoint to upload a new version of your code function. To execute your newly uploaded code, you'll need to update the function's deployment to use your new deployment UID.\n\nThis endpoint accepts a tar.gz file compressed with your code. Make sure to include any dependencies your code has within the compressed file. You can learn more about code packaging in the [Appwrite Cloud Functions tutorial](https:\/\/appwrite.io\/docs\/functions).\n\nUse the \"command\" param to set the entrypoint used to execute your code.", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createDeployment", + "group": "deployments", + "weight": 382, + "cookies": false, + "type": "upload", + "deprecated": false, + "demo": "functions\/create-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new function code deployment. Use this endpoint to upload a new version of your code function. To execute your newly uploaded code, you'll need to update the function's deployment to use your new deployment UID.\n\nThis endpoint accepts a tar.gz file compressed with your code. Make sure to include any dependencies your code has within the compressed file. You can learn more about code packaging in the [Appwrite Cloud Functions tutorial](https:\/\/appwrite.io\/docs\/functions).\n\nUse the \"command\" param to set the entrypoint used to execute your code.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": true, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "entrypoint", + "description": "Entrypoint File.", + "required": false, + "type": "string", + "x-example": "<ENTRYPOINT>", + "in": "formData" + }, + { + "name": "commands", + "description": "Build Commands.", + "required": false, + "type": "string", + "x-example": "<COMMANDS>", + "in": "formData" + }, + { + "name": "code", + "description": "Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.", + "required": true, + "type": "file", + "in": "formData" + }, + { + "name": "activate", + "description": "Automatically activate the deployment when it is finished building.", + "required": true, + "type": "boolean", + "x-example": false, + "in": "formData" + } + ] + } + }, + "\/functions\/{functionId}\/deployments\/duplicate": { + "post": { + "summary": "Create duplicate deployment", + "operationId": "functionsCreateDuplicateDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Create a new build for an existing function deployment. This endpoint allows you to rebuild a deployment with the updated function configuration, including its entrypoint and build commands if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createDuplicateDeployment", + "group": "deployments", + "weight": 390, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-duplicate-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new build for an existing function deployment. This endpoint allows you to rebuild a deployment with the updated function configuration, including its entrypoint and build commands if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "deploymentId": { + "type": "string", + "description": "Deployment ID.", + "default": null, + "x-example": "<DEPLOYMENT_ID>" + }, + "buildId": { + "type": "string", + "description": "Build unique ID.", + "default": "", + "x-example": "<BUILD_ID>" + } + }, + "required": [ + "deploymentId" + ] + } + } + ] + } + }, + "\/functions\/{functionId}\/deployments\/template": { + "post": { + "summary": "Create template deployment", + "operationId": "functionsCreateTemplateDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Create a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/functions#listTemplates) to find the template details.", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createTemplateDeployment", + "group": "deployments", + "weight": 387, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-template-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/functions#listTemplates) to find the template details.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "repository": { + "type": "string", + "description": "Repository name of the template.", + "default": null, + "x-example": "<REPOSITORY>" + }, + "owner": { + "type": "string", + "description": "The name of the owner of the template.", + "default": null, + "x-example": "<OWNER>" + }, + "rootDirectory": { + "type": "string", + "description": "Path to function code in the template repo.", + "default": null, + "x-example": "<ROOT_DIRECTORY>" + }, + "version": { + "type": "string", + "description": "Version (tag) for the repo linked to the function template.", + "default": null, + "x-example": "<VERSION>" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "default": false, + "x-example": false + } + }, + "required": [ + "repository", + "owner", + "rootDirectory", + "version" + ] + } + } + ] + } + }, + "\/functions\/{functionId}\/deployments\/vcs": { + "post": { + "summary": "Create VCS deployment", + "operationId": "functionsCreateVcsDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Create a deployment when a function is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createVcsDeployment", + "group": "deployments", + "weight": 388, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-vcs-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment when a function is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Type of reference passed. Allowed values are: branch, commit", + "default": null, + "x-example": "branch", + "enum": [ + "branch", + "commit" + ], + "x-enum-name": "VCSDeploymentType", + "x-enum-keys": [] + }, + "reference": { + "type": "string", + "description": "VCS reference to create deployment from. Depending on type this can be: branch name, commit hash", + "default": null, + "x-example": "<REFERENCE>" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "default": false, + "x-example": false + } + }, + "required": [ + "type", + "reference" + ] + } + } + ] + } + }, + "\/functions\/{functionId}\/deployments\/{deploymentId}": { + "get": { + "summary": "Get deployment", + "operationId": "functionsGetDeployment", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a function deployment by its unique ID.", + "responses": { + "200": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "getDeployment", + "group": "deployments", + "weight": 383, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function deployment by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "type": "string", + "x-example": "<DEPLOYMENT_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete deployment", + "operationId": "functionsDeleteDeployment", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "functions" + ], + "description": "Delete a code deployment by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDeployment", + "group": "deployments", + "weight": 386, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/delete-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a code deployment by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "type": "string", + "x-example": "<DEPLOYMENT_ID>", + "in": "path" + } + ] + } + }, + "\/functions\/{functionId}\/deployments\/{deploymentId}\/download": { + "get": { + "summary": "Get deployment download", + "operationId": "functionsGetDeploymentDownload", + "consumes": [], + "produces": [ + "*\/*" + ], + "tags": [ + "functions" + ], + "description": "Get a function deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "responses": { + "200": { + "description": "File", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getDeploymentDownload", + "group": "deployments", + "weight": 389, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "functions\/get-deployment-download.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "type": "string", + "x-example": "<DEPLOYMENT_ID>", + "in": "path" + }, + { + "name": "type", + "description": "Deployment file to download. Can be: \"source\", \"output\".", + "required": false, + "type": "string", + "x-example": "source", + "enum": [ + "source", + "output" + ], + "x-enum-name": "DeploymentDownloadType", + "x-enum-keys": [], + "default": "source", + "in": "query" + } + ] + } + }, + "\/functions\/{functionId}\/deployments\/{deploymentId}\/status": { + "patch": { + "summary": "Update deployment status", + "operationId": "functionsUpdateDeploymentStatus", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Cancel an ongoing function deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", + "responses": { + "200": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "updateDeploymentStatus", + "group": "deployments", + "weight": 391, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/update-deployment-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCancel an ongoing function deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "type": "string", + "x-example": "<DEPLOYMENT_ID>", + "in": "path" + } + ] + } + }, + "\/functions\/{functionId}\/executions": { + "get": { + "summary": "List executions", + "operationId": "functionsListExecutions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a list of all the current user function execution logs. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Executions List", + "schema": { + "$ref": "#\/definitions\/executionList" + } + } + }, + "x-appwrite": { + "method": "listExecutions", + "group": "executions", + "weight": 394, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-executions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the current user function execution logs. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: trigger, status, responseStatusCode, duration, requestMethod, requestPath, deploymentId", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create execution", + "operationId": "functionsCreateExecution", + "consumes": [ + "application\/json" + ], + "produces": [ + "multipart\/form-data" + ], + "tags": [ + "functions" + ], + "description": "Trigger a function execution. The returned object will return you the current execution status. You can ping the `Get Execution` endpoint to get updates on the current execution status. Once this endpoint is called, your function execution process will start asynchronously.", + "responses": { + "201": { + "description": "Execution", + "schema": { + "$ref": "#\/definitions\/execution" + } + } + }, + "x-appwrite": { + "method": "createExecution", + "group": "executions", + "weight": 392, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-execution.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterTrigger a function execution. The returned object will return you the current execution status. You can ping the `Get Execution` endpoint to get updates on the current execution status. Once this endpoint is called, your function execution process will start asynchronously.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "body": { + "type": "string", + "description": "HTTP body of execution. Default value is empty string.", + "default": "", + "x-example": "<BODY>" + }, + "async": { + "type": "boolean", + "description": "Execute code in the background. Default value is false.", + "default": false, + "x-example": false + }, + "path": { + "type": "string", + "description": "HTTP path of execution. Path can include query params. Default value is \/", + "default": "\/", + "x-example": "<PATH>" + }, + "method": { + "type": "string", + "description": "HTTP method of execution. Default value is GET.", + "default": "POST", + "x-example": "GET", + "enum": [ + "GET", + "POST", + "PUT", + "PATCH", + "DELETE", + "OPTIONS" + ], + "x-enum-name": "ExecutionMethod", + "x-enum-keys": [] + }, + "headers": { + "type": "object", + "description": "HTTP headers of execution. Defaults to empty.", + "default": [], + "x-example": "{}" + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled execution time in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future with precision in minutes.", + "default": null, + "x-example": null + } + } + } + } + ] + } + }, + "\/functions\/{functionId}\/executions\/{executionId}": { + "get": { + "summary": "Get execution", + "operationId": "functionsGetExecution", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a function execution log by its unique ID.", + "responses": { + "200": { + "description": "Execution", + "schema": { + "$ref": "#\/definitions\/execution" + } + } + }, + "x-appwrite": { + "method": "getExecution", + "group": "executions", + "weight": 393, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get-execution.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a function execution log by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "executionId", + "description": "Execution ID.", + "required": true, + "type": "string", + "x-example": "<EXECUTION_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete execution", + "operationId": "functionsDeleteExecution", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "functions" + ], + "description": "Delete a function execution by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteExecution", + "group": "executions", + "weight": 395, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/delete-execution.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a function execution by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "execution.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "executionId", + "description": "Execution ID.", + "required": true, + "type": "string", + "x-example": "<EXECUTION_ID>", + "in": "path" + } + ] + } + }, + "\/functions\/{functionId}\/variables": { + "get": { + "summary": "List variables", + "operationId": "functionsListVariables", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a list of all variables of a specific function.", + "responses": { + "200": { + "description": "Variables List", + "schema": { + "$ref": "#\/definitions\/variableList" + } + } + }, + "x-appwrite": { + "method": "listVariables", + "group": "variables", + "weight": 400, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/list-variables.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all variables of a specific function.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + } + ] + }, + "post": { + "summary": "Create variable", + "operationId": "functionsCreateVariable", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Create a new function environment variable. These variables can be accessed in the function at runtime as environment variables.", + "responses": { + "201": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "createVariable", + "group": "variables", + "weight": 398, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/create-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new function environment variable. These variables can be accessed in the function at runtime as environment variables.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "default": null, + "x-example": "<KEY>" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "default": null, + "x-example": "<VALUE>" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only functions can read them during build and runtime.", + "default": true, + "x-example": false + } + }, + "required": [ + "key", + "value" + ] + } + } + ] + } + }, + "\/functions\/{functionId}\/variables\/{variableId}": { + "get": { + "summary": "Get variable", + "operationId": "functionsGetVariable", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Get a variable by its unique ID.", + "responses": { + "200": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "getVariable", + "group": "variables", + "weight": 399, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/get-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "type": "string", + "x-example": "<VARIABLE_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update variable", + "operationId": "functionsUpdateVariable", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "functions" + ], + "description": "Update variable by its unique ID.", + "responses": { + "200": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "updateVariable", + "group": "variables", + "weight": 401, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/update-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "type": "string", + "x-example": "<VARIABLE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "default": null, + "x-example": "<KEY>" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "default": null, + "x-example": "<VALUE>" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only functions can read them during build and runtime.", + "default": null, + "x-example": false + } + }, + "required": [ + "key" + ] + } + } + ] + }, + "delete": { + "summary": "Delete variable", + "operationId": "functionsDeleteVariable", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "functions" + ], + "description": "Delete a variable by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteVariable", + "group": "variables", + "weight": 402, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "functions\/delete-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "functions.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "functionId", + "description": "Function unique ID.", + "required": true, + "type": "string", + "x-example": "<FUNCTION_ID>", + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "type": "string", + "x-example": "<VARIABLE_ID>", + "in": "path" + } + ] + } + }, + "\/graphql": { + "post": { + "summary": "GraphQL endpoint", + "operationId": "graphqlQuery", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "graphql" + ], + "description": "Execute a GraphQL mutation.", + "responses": { + "200": { + "description": "Any", + "schema": { + "$ref": "#\/definitions\/any" + } + } + }, + "x-appwrite": { + "method": "query", + "group": "graphql", + "weight": 308, + "cookies": false, + "type": "graphql", + "deprecated": false, + "demo": "graphql\/query.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/graphql\/post.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "url:{url},ip:{ip}", + "scope": "graphql", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "query": { + "type": "object", + "description": "The query or queries to execute.", + "default": {}, + "x-example": "{}" + } + }, + "required": [ + "query" + ] + } + } + ] + } + }, + "\/graphql\/mutation": { + "post": { + "summary": "GraphQL endpoint", + "operationId": "graphqlMutation", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "graphql" + ], + "description": "Execute a GraphQL mutation.", + "responses": { + "200": { + "description": "Any", + "schema": { + "$ref": "#\/definitions\/any" + } + } + }, + "x-appwrite": { + "method": "mutation", + "group": "graphql", + "weight": 307, + "cookies": false, + "type": "graphql", + "deprecated": false, + "demo": "graphql\/mutation.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/graphql\/post.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "url:{url},ip:{ip}", + "scope": "graphql", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "query": { + "type": "object", + "description": "The query or queries to execute.", + "default": {}, + "x-example": "{}" + } + }, + "required": [ + "query" + ] + } + } + ] + } + }, + "\/health": { + "get": { + "summary": "Get HTTP", + "operationId": "healthGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Check the Appwrite HTTP server is up and responsive.", + "responses": { + "200": { + "description": "Health Status", + "schema": { + "$ref": "#\/definitions\/healthStatus" + } + } + }, + "x-appwrite": { + "method": "get", + "group": "health", + "weight": 132, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/anti-virus": { + "get": { + "summary": "Get antivirus", + "operationId": "healthGetAntivirus", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Check the Appwrite Antivirus server is up and connection is successful.", + "responses": { + "200": { + "description": "Health Antivirus", + "schema": { + "$ref": "#\/definitions\/healthAntivirus" + } + } + }, + "x-appwrite": { + "method": "getAntivirus", + "group": "health", + "weight": 153, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-antivirus.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-storage-anti-virus.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/cache": { + "get": { + "summary": "Get cache", + "operationId": "healthGetCache", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Check the Appwrite in-memory cache servers are up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "schema": { + "$ref": "#\/definitions\/healthStatus" + } + } + }, + "x-appwrite": { + "method": "getCache", + "group": "health", + "weight": 135, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-cache.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-cache.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/certificate": { + "get": { + "summary": "Get the SSL certificate for a domain", + "operationId": "healthGetCertificate", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the SSL certificate for a domain", + "responses": { + "200": { + "description": "Health Certificate", + "schema": { + "$ref": "#\/definitions\/healthCertificate" + } + } + }, + "x-appwrite": { + "method": "getCertificate", + "group": "health", + "weight": 140, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-certificate.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-certificate.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "domain", + "description": "string", + "required": false, + "type": "string", + "in": "query" + } + ] + } + }, + "\/health\/db": { + "get": { + "summary": "Get DB", + "operationId": "healthGetDB", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Check the Appwrite database servers are up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "schema": { + "$ref": "#\/definitions\/healthStatus" + } + } + }, + "x-appwrite": { + "method": "getDB", + "group": "health", + "weight": 134, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-d-b.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-db.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/pubsub": { + "get": { + "summary": "Get pubsub", + "operationId": "healthGetPubSub", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Check the Appwrite pub-sub servers are up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "schema": { + "$ref": "#\/definitions\/healthStatus" + } + } + }, + "x-appwrite": { + "method": "getPubSub", + "group": "health", + "weight": 136, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-pub-sub.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-pubsub.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/queue\/builds": { + "get": { + "summary": "Get builds queue", + "operationId": "healthGetQueueBuilds", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of builds that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueBuilds", + "group": "queue", + "weight": 142, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-builds.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-builds.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/certificates": { + "get": { + "summary": "Get certificates queue", + "operationId": "healthGetQueueCertificates", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of certificates that are waiting to be issued against [Letsencrypt](https:\/\/letsencrypt.org\/) in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueCertificates", + "group": "queue", + "weight": 141, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-certificates.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-certificates.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/databases": { + "get": { + "summary": "Get databases queue", + "operationId": "healthGetQueueDatabases", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of database changes that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueDatabases", + "group": "queue", + "weight": 143, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-databases.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-databases.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "name", + "description": "Queue name for which to check the queue size", + "required": false, + "type": "string", + "x-example": "<NAME>", + "default": "database_db_main", + "in": "query" + }, + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/deletes": { + "get": { + "summary": "Get deletes queue", + "operationId": "healthGetQueueDeletes", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of background destructive changes that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueDeletes", + "group": "queue", + "weight": 144, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-deletes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-deletes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/failed\/{name}": { + "get": { + "summary": "Get number of failed queue jobs", + "operationId": "healthGetFailedJobs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Returns the amount of failed jobs in a given queue.\n", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getFailedJobs", + "group": "queue", + "weight": 154, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-failed-jobs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-failed-queue-jobs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "name", + "description": "The name of the queue", + "required": true, + "type": "string", + "x-example": "v1-database", + "enum": [ + "v1-database", + "v1-deletes", + "v1-audits", + "v1-mails", + "v1-functions", + "v1-stats-resources", + "v1-stats-usage", + "v1-webhooks", + "v1-certificates", + "v1-builds", + "v1-messaging", + "v1-migrations" + ], + "x-enum-name": null, + "x-enum-keys": [], + "in": "path" + }, + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/functions": { + "get": { + "summary": "Get functions queue", + "operationId": "healthGetQueueFunctions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of function executions that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueFunctions", + "group": "queue", + "weight": 148, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-functions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-functions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/logs": { + "get": { + "summary": "Get logs queue", + "operationId": "healthGetQueueLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of logs that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueLogs", + "group": "queue", + "weight": 139, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/mails": { + "get": { + "summary": "Get mails queue", + "operationId": "healthGetQueueMails", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of mails that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueMails", + "group": "queue", + "weight": 145, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-mails.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-mails.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/messaging": { + "get": { + "summary": "Get messaging queue", + "operationId": "healthGetQueueMessaging", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of messages that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueMessaging", + "group": "queue", + "weight": 146, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-messaging.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-messaging.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/migrations": { + "get": { + "summary": "Get migrations queue", + "operationId": "healthGetQueueMigrations", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of migrations that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueMigrations", + "group": "queue", + "weight": 147, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-migrations.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-migrations.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/stats-resources": { + "get": { + "summary": "Get stats resources queue", + "operationId": "healthGetQueueStatsResources", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of metrics that are waiting to be processed in the Appwrite stats resources queue.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueStatsResources", + "group": "queue", + "weight": 149, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-stats-resources.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-resources.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/stats-usage": { + "get": { + "summary": "Get stats usage queue", + "operationId": "healthGetQueueUsage", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of metrics that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueUsage", + "group": "queue", + "weight": 150, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-usage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-stats-usage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/queue\/webhooks": { + "get": { + "summary": "Get webhooks queue", + "operationId": "healthGetQueueWebhooks", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Get the number of webhooks that are waiting to be processed in the Appwrite internal queue server.", + "responses": { + "200": { + "description": "Health Queue", + "schema": { + "$ref": "#\/definitions\/healthQueue" + } + } + }, + "x-appwrite": { + "method": "getQueueWebhooks", + "group": "queue", + "weight": 138, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-queue-webhooks.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-queue-webhooks.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "threshold", + "description": "Queue size threshold. When hit (equal or higher), endpoint returns server error. Default value is 5000.", + "required": false, + "type": "integer", + "format": "int32", + "default": 5000, + "in": "query" + } + ] + } + }, + "\/health\/storage": { + "get": { + "summary": "Get storage", + "operationId": "healthGetStorage", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Check the Appwrite storage device is up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "schema": { + "$ref": "#\/definitions\/healthStatus" + } + } + }, + "x-appwrite": { + "method": "getStorage", + "group": "storage", + "weight": 152, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-storage.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-storage.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/storage\/local": { + "get": { + "summary": "Get local storage", + "operationId": "healthGetStorageLocal", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Check the Appwrite local storage device is up and connection is successful.", + "responses": { + "200": { + "description": "Health Status", + "schema": { + "$ref": "#\/definitions\/healthStatus" + } + } + }, + "x-appwrite": { + "method": "getStorageLocal", + "group": "storage", + "weight": 151, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-storage-local.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-storage-local.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/health\/time": { + "get": { + "summary": "Get time", + "operationId": "healthGetTime", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "health" + ], + "description": "Check the Appwrite server time is synced with Google remote NTP server. We use this technology to smoothly handle leap seconds with no disruptive events. The [Network Time Protocol](https:\/\/en.wikipedia.org\/wiki\/Network_Time_Protocol) (NTP) is used by hundreds of millions of computers and devices to synchronize their clocks over the Internet. If your computer sets its own clock, it likely uses NTP.", + "responses": { + "200": { + "description": "Health Time", + "schema": { + "$ref": "#\/definitions\/healthTime" + } + } + }, + "x-appwrite": { + "method": "getTime", + "group": "health", + "weight": 137, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "health\/get-time.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/health\/get-time.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "health.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/locale": { + "get": { + "summary": "Get user locale", + "operationId": "localeGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "Get the current user location based on IP. Returns an object with user country code, country name, continent name, continent code, ip address and suggested currency. You can use the locale header to get the data in a supported language.\n\n([IP Geolocation by DB-IP](https:\/\/db-ip.com))", + "responses": { + "200": { + "description": "Locale", + "schema": { + "$ref": "#\/definitions\/locale" + } + } + }, + "x-appwrite": { + "method": "get", + "group": null, + "weight": 124, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/get-locale.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/codes": { + "get": { + "summary": "List locale codes", + "operationId": "localeListCodes", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all locale codes in [ISO 639-1](https:\/\/en.wikipedia.org\/wiki\/List_of_ISO_639-1_codes).", + "responses": { + "200": { + "description": "Locale codes list", + "schema": { + "$ref": "#\/definitions\/localeCodeList" + } + } + }, + "x-appwrite": { + "method": "listCodes", + "group": null, + "weight": 125, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-locale-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/continents": { + "get": { + "summary": "List continents", + "operationId": "localeListContinents", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all continents. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Continents List", + "schema": { + "$ref": "#\/definitions\/continentList" + } + } + }, + "x-appwrite": { + "method": "listContinents", + "group": null, + "weight": 129, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-continents.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-continents.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/countries": { + "get": { + "summary": "List countries", + "operationId": "localeListCountries", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all countries. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Countries List", + "schema": { + "$ref": "#\/definitions\/countryList" + } + } + }, + "x-appwrite": { + "method": "listCountries", + "group": null, + "weight": 126, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-countries.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-countries.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/countries\/eu": { + "get": { + "summary": "List EU countries", + "operationId": "localeListCountriesEU", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all countries that are currently members of the EU. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Countries List", + "schema": { + "$ref": "#\/definitions\/countryList" + } + } + }, + "x-appwrite": { + "method": "listCountriesEU", + "group": null, + "weight": 127, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-countries-e-u.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-countries-eu.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/countries\/phones": { + "get": { + "summary": "List countries phone codes", + "operationId": "localeListCountriesPhones", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all countries phone codes. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Phones List", + "schema": { + "$ref": "#\/definitions\/phoneList" + } + } + }, + "x-appwrite": { + "method": "listCountriesPhones", + "group": null, + "weight": 128, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-countries-phones.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-countries-phones.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/currencies": { + "get": { + "summary": "List currencies", + "operationId": "localeListCurrencies", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all currencies, including currency symbol, name, plural, and decimal digits for all major and minor currencies. You can use the locale header to get the data in a supported language.", + "responses": { + "200": { + "description": "Currencies List", + "schema": { + "$ref": "#\/definitions\/currencyList" + } + } + }, + "x-appwrite": { + "method": "listCurrencies", + "group": null, + "weight": 130, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-currencies.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-currencies.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/locale\/languages": { + "get": { + "summary": "List languages", + "operationId": "localeListLanguages", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "locale" + ], + "description": "List of all languages classified by ISO 639-1 including 2-letter code, name in English, and name in the respective language.", + "responses": { + "200": { + "description": "Languages List", + "schema": { + "$ref": "#\/definitions\/languageList" + } + } + }, + "x-appwrite": { + "method": "listLanguages", + "group": null, + "weight": 131, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "locale\/list-languages.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/locale\/list-languages.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "locale.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ] + } + }, + "\/messaging\/messages": { + "get": { + "summary": "List messages", + "operationId": "messagingListMessages", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get a list of all messages from the current Appwrite project.", + "responses": { + "200": { + "description": "Message list", + "schema": { + "$ref": "#\/definitions\/messageList" + } + } + }, + "x-appwrite": { + "method": "listMessages", + "group": "messages", + "weight": 362, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-messages.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-messages.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: scheduledAt, deliveredAt, deliveredTotal, status, description, providerType", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + } + }, + "\/messaging\/messages\/email": { + "post": { + "summary": "Create email", + "operationId": "messagingCreateEmail", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new email message.", + "responses": { + "201": { + "description": "Message", + "schema": { + "$ref": "#\/definitions\/message" + } + } + }, + "x-appwrite": { + "method": "createEmail", + "group": "messages", + "weight": 359, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-email.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "messageId": { + "type": "string", + "description": "Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<MESSAGE_ID>" + }, + "subject": { + "type": "string", + "description": "Email Subject.", + "default": null, + "x-example": "<SUBJECT>" + }, + "content": { + "type": "string", + "description": "Email Content.", + "default": null, + "x-example": "<CONTENT>" + }, + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "cc": { + "type": "array", + "description": "Array of target IDs to be added as CC.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "bcc": { + "type": "array", + "description": "Array of target IDs to be added as BCC.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "attachments": { + "type": "array", + "description": "Array of compound ID strings of bucket IDs and file IDs to be attached to the email. They should be formatted as <BUCKET_ID>:<FILE_ID>.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "default": false, + "x-example": false + }, + "html": { + "type": "boolean", + "description": "Is content of type HTML", + "default": false, + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "default": null, + "x-example": null + } + }, + "required": [ + "messageId", + "subject", + "content" + ] + } + } + ] + } + }, + "\/messaging\/messages\/email\/{messageId}": { + "patch": { + "summary": "Update email", + "operationId": "messagingUpdateEmail", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update an email message by its unique ID. This endpoint only works on messages that are in draft status. Messages that are already processing, sent, or failed cannot be updated.\n", + "responses": { + "200": { + "description": "Message", + "schema": { + "$ref": "#\/definitions\/message" + } + } + }, + "x-appwrite": { + "method": "updateEmail", + "group": "messages", + "weight": 366, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-email.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "type": "string", + "x-example": "<MESSAGE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "subject": { + "type": "string", + "description": "Email Subject.", + "default": null, + "x-example": "<SUBJECT>" + }, + "content": { + "type": "string", + "description": "Email Content.", + "default": null, + "x-example": "<CONTENT>" + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "default": null, + "x-example": false + }, + "html": { + "type": "boolean", + "description": "Is content of type HTML", + "default": null, + "x-example": false + }, + "cc": { + "type": "array", + "description": "Array of target IDs to be added as CC.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "bcc": { + "type": "array", + "description": "Array of target IDs to be added as BCC.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "default": null, + "x-example": null + }, + "attachments": { + "type": "array", + "description": "Array of compound ID strings of bucket IDs and file IDs to be attached to the email. They should be formatted as <BUCKET_ID>:<FILE_ID>.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + } + } + } + } + ] + } + }, + "\/messaging\/messages\/push": { + "post": { + "summary": "Create push notification", + "operationId": "messagingCreatePush", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new push notification.", + "responses": { + "201": { + "description": "Message", + "schema": { + "$ref": "#\/definitions\/message" + } + } + }, + "x-appwrite": { + "method": "createPush", + "group": "messages", + "weight": 361, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-push.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-push.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "messageId": { + "type": "string", + "description": "Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<MESSAGE_ID>" + }, + "title": { + "type": "string", + "description": "Title for push notification.", + "default": "", + "x-example": "<TITLE>" + }, + "body": { + "type": "string", + "description": "Body for push notification.", + "default": "", + "x-example": "<BODY>" + }, + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "data": { + "type": "object", + "description": "Additional key-value pair data for push notification.", + "default": {}, + "x-example": "{}" + }, + "action": { + "type": "string", + "description": "Action for push notification.", + "default": "", + "x-example": "<ACTION>" + }, + "image": { + "type": "string", + "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as <BUCKET_ID>:<FILE_ID>.", + "default": "", + "x-example": "[ID1:ID2]" + }, + "icon": { + "type": "string", + "description": "Icon for push notification. Available only for Android and Web Platform.", + "default": "", + "x-example": "<ICON>" + }, + "sound": { + "type": "string", + "description": "Sound for push notification. Available only for Android and iOS Platform.", + "default": "", + "x-example": "<SOUND>" + }, + "color": { + "type": "string", + "description": "Color for push notification. Available only for Android Platform.", + "default": "", + "x-example": "<COLOR>" + }, + "tag": { + "type": "string", + "description": "Tag for push notification. Available only for Android Platform.", + "default": "", + "x-example": "<TAG>" + }, + "badge": { + "type": "integer", + "description": "Badge for push notification. Available only for iOS Platform.", + "default": -1, + "x-example": null + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "default": false, + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "default": null, + "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "default": false, + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "default": false, + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device state and may not deliver notifications immediately. \"high\" will always attempt to immediately deliver the notification.", + "default": "high", + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": "MessagePriority", + "x-enum-keys": [] + } + }, + "required": [ + "messageId" + ] + } + } + ] + } + }, + "\/messaging\/messages\/push\/{messageId}": { + "patch": { + "summary": "Update push notification", + "operationId": "messagingUpdatePush", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a push notification by its unique ID. This endpoint only works on messages that are in draft status. Messages that are already processing, sent, or failed cannot be updated.\n", + "responses": { + "200": { + "description": "Message", + "schema": { + "$ref": "#\/definitions\/message" + } + } + }, + "x-appwrite": { + "method": "updatePush", + "group": "messages", + "weight": 368, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-push.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-push.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "type": "string", + "x-example": "<MESSAGE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "title": { + "type": "string", + "description": "Title for push notification.", + "default": null, + "x-example": "<TITLE>" + }, + "body": { + "type": "string", + "description": "Body for push notification.", + "default": null, + "x-example": "<BODY>" + }, + "data": { + "type": "object", + "description": "Additional Data for push notification.", + "default": {}, + "x-example": "{}" + }, + "action": { + "type": "string", + "description": "Action for push notification.", + "default": null, + "x-example": "<ACTION>" + }, + "image": { + "type": "string", + "description": "Image for push notification. Must be a compound bucket ID to file ID of a jpeg, png, or bmp image in Appwrite Storage. It should be formatted as <BUCKET_ID>:<FILE_ID>.", + "default": null, + "x-example": "[ID1:ID2]" + }, + "icon": { + "type": "string", + "description": "Icon for push notification. Available only for Android and Web platforms.", + "default": null, + "x-example": "<ICON>" + }, + "sound": { + "type": "string", + "description": "Sound for push notification. Available only for Android and iOS platforms.", + "default": null, + "x-example": "<SOUND>" + }, + "color": { + "type": "string", + "description": "Color for push notification. Available only for Android platforms.", + "default": null, + "x-example": "<COLOR>" + }, + "tag": { + "type": "string", + "description": "Tag for push notification. Available only for Android platforms.", + "default": null, + "x-example": "<TAG>" + }, + "badge": { + "type": "integer", + "description": "Badge for push notification. Available only for iOS platforms.", + "default": null, + "x-example": null + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "default": null, + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "default": null, + "x-example": null + }, + "contentAvailable": { + "type": "boolean", + "description": "If set to true, the notification will be delivered in the background. Available only for iOS Platform.", + "default": null, + "x-example": false + }, + "critical": { + "type": "boolean", + "description": "If set to true, the notification will be marked as critical. This requires the app to have the critical notification entitlement. Available only for iOS Platform.", + "default": null, + "x-example": false + }, + "priority": { + "type": "string", + "description": "Set the notification priority. \"normal\" will consider device battery state and may send notifications later. \"high\" will always attempt to immediately deliver the notification.", + "default": null, + "x-example": "normal", + "enum": [ + "normal", + "high" + ], + "x-enum-name": "MessagePriority", + "x-enum-keys": [] + } + } + } + } + ] + } + }, + "\/messaging\/messages\/sms": { + "post": { + "summary": "Create SMS", + "operationId": "messagingCreateSms", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new SMS message.", + "responses": { + "201": { + "description": "Message", + "schema": { + "$ref": "#\/definitions\/message" + } + } + }, + "x-appwrite": { + "method": "createSms", + "group": "messages", + "weight": 360, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-sms.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-sms.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "messageId": { + "type": "string", + "description": "Message ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<MESSAGE_ID>" + }, + "content": { + "type": "string", + "description": "SMS Content.", + "default": null, + "x-example": "<CONTENT>" + }, + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "default": false, + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "default": null, + "x-example": null + } + }, + "required": [ + "messageId", + "content" + ] + } + } + ] + } + }, + "\/messaging\/messages\/sms\/{messageId}": { + "patch": { + "summary": "Update SMS", + "operationId": "messagingUpdateSms", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update an SMS message by its unique ID. This endpoint only works on messages that are in draft status. Messages that are already processing, sent, or failed cannot be updated.\n", + "responses": { + "200": { + "description": "Message", + "schema": { + "$ref": "#\/definitions\/message" + } + } + }, + "x-appwrite": { + "method": "updateSms", + "group": "messages", + "weight": 367, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-sms.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-sms.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "type": "string", + "x-example": "<MESSAGE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "topics": { + "type": "array", + "description": "List of Topic IDs.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "users": { + "type": "array", + "description": "List of User IDs.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "targets": { + "type": "array", + "description": "List of Targets IDs.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "content": { + "type": "string", + "description": "Email Content.", + "default": null, + "x-example": "<CONTENT>" + }, + "draft": { + "type": "boolean", + "description": "Is message a draft", + "default": null, + "x-example": false + }, + "scheduledAt": { + "type": "string", + "description": "Scheduled delivery time for message in [ISO 8601](https:\/\/www.iso.org\/iso-8601-date-and-time-format.html) format. DateTime value must be in future.", + "default": null, + "x-example": null + } + } + } + } + ] + } + }, + "\/messaging\/messages\/{messageId}": { + "get": { + "summary": "Get message", + "operationId": "messagingGetMessage", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get a message by its unique ID.\n", + "responses": { + "200": { + "description": "Message", + "schema": { + "$ref": "#\/definitions\/message" + } + } + }, + "x-appwrite": { + "method": "getMessage", + "group": "messages", + "weight": 365, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/get-message.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/get-message.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "type": "string", + "x-example": "<MESSAGE_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete message", + "operationId": "messagingDelete", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "messaging" + ], + "description": "Delete a message. If the message is not a draft or scheduled, but has been sent, this will not recall the message.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "messages", + "weight": 369, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/delete-message.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "type": "string", + "x-example": "<MESSAGE_ID>", + "in": "path" + } + ] + } + }, + "\/messaging\/messages\/{messageId}\/logs": { + "get": { + "summary": "List message logs", + "operationId": "messagingListMessageLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get the message activity logs listed by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "schema": { + "$ref": "#\/definitions\/logList" + } + } + }, + "x-appwrite": { + "method": "listMessageLogs", + "group": "logs", + "weight": 363, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-message-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-message-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "type": "string", + "x-example": "<MESSAGE_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/messaging\/messages\/{messageId}\/targets": { + "get": { + "summary": "List message targets", + "operationId": "messagingListTargets", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get a list of the targets associated with a message.", + "responses": { + "200": { + "description": "Target list", + "schema": { + "$ref": "#\/definitions\/targetList" + } + } + }, + "x-appwrite": { + "method": "listTargets", + "group": "messages", + "weight": 364, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-targets.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-message-targets.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "messages.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "messageId", + "description": "Message ID.", + "required": true, + "type": "string", + "x-example": "<MESSAGE_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, providerId, identifier, providerType", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/messaging\/providers": { + "get": { + "summary": "List providers", + "operationId": "messagingListProviders", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get a list of all providers from the current Appwrite project.", + "responses": { + "200": { + "description": "Provider list", + "schema": { + "$ref": "#\/definitions\/providerList" + } + } + }, + "x-appwrite": { + "method": "listProviders", + "group": "providers", + "weight": 334, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-providers.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-providers.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, provider, type, enabled", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + } + }, + "\/messaging\/providers\/apns": { + "post": { + "summary": "Create APNS provider", + "operationId": "messagingCreateApnsProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new Apple Push Notification service provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createApnsProvider", + "group": "providers", + "weight": 333, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-apns-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-apns-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "authKey": { + "type": "string", + "description": "APNS authentication key.", + "default": "", + "x-example": "<AUTH_KEY>" + }, + "authKeyId": { + "type": "string", + "description": "APNS authentication key ID.", + "default": "", + "x-example": "<AUTH_KEY_ID>" + }, + "teamId": { + "type": "string", + "description": "APNS team ID.", + "default": "", + "x-example": "<TEAM_ID>" + }, + "bundleId": { + "type": "string", + "description": "APNS bundle ID.", + "default": "", + "x-example": "<BUNDLE_ID>" + }, + "sandbox": { + "type": "boolean", + "description": "Use APNS sandbox environment.", + "default": false, + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/providers\/apns\/{providerId}": { + "patch": { + "summary": "Update APNS provider", + "operationId": "messagingUpdateApnsProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a Apple Push Notification service provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateApnsProvider", + "group": "providers", + "weight": 346, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-apns-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-apns-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + }, + "authKey": { + "type": "string", + "description": "APNS authentication key.", + "default": "", + "x-example": "<AUTH_KEY>" + }, + "authKeyId": { + "type": "string", + "description": "APNS authentication key ID.", + "default": "", + "x-example": "<AUTH_KEY_ID>" + }, + "teamId": { + "type": "string", + "description": "APNS team ID.", + "default": "", + "x-example": "<TEAM_ID>" + }, + "bundleId": { + "type": "string", + "description": "APNS bundle ID.", + "default": "", + "x-example": "<BUNDLE_ID>" + }, + "sandbox": { + "type": "boolean", + "description": "Use APNS sandbox environment.", + "default": null, + "x-example": false + } + } + } + } + ] + } + }, + "\/messaging\/providers\/fcm": { + "post": { + "summary": "Create FCM provider", + "operationId": "messagingCreateFcmProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new Firebase Cloud Messaging provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createFcmProvider", + "group": "providers", + "weight": 332, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-fcm-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-fcm-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "serviceAccountJSON": { + "type": "object", + "description": "FCM service account JSON.", + "default": {}, + "x-example": "{}" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/providers\/fcm\/{providerId}": { + "patch": { + "summary": "Update FCM provider", + "operationId": "messagingUpdateFcmProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a Firebase Cloud Messaging provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateFcmProvider", + "group": "providers", + "weight": 345, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-fcm-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-fcm-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + }, + "serviceAccountJSON": { + "type": "object", + "description": "FCM service account JSON.", + "default": {}, + "x-example": "{}" + } + } + } + } + ] + } + }, + "\/messaging\/providers\/mailgun": { + "post": { + "summary": "Create Mailgun provider", + "operationId": "messagingCreateMailgunProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new Mailgun provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createMailgunProvider", + "group": "providers", + "weight": 324, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-mailgun-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-mailgun-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "apiKey": { + "type": "string", + "description": "Mailgun API Key.", + "default": "", + "x-example": "<API_KEY>" + }, + "domain": { + "type": "string", + "description": "Mailgun Domain.", + "default": "", + "x-example": "<DOMAIN>" + }, + "isEuRegion": { + "type": "boolean", + "description": "Set as EU region.", + "default": null, + "x-example": false + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "default": "", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "default": "", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the reply to field for the mail. Default value is sender name. Reply to name must have reply to email as well.", + "default": "", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the reply to field for the mail. Default value is sender email. Reply to email must have reply to name as well.", + "default": "", + "x-example": "email@example.com" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/providers\/mailgun\/{providerId}": { + "patch": { + "summary": "Update Mailgun provider", + "operationId": "messagingUpdateMailgunProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a Mailgun provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateMailgunProvider", + "group": "providers", + "weight": 337, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-mailgun-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-mailgun-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "apiKey": { + "type": "string", + "description": "Mailgun API Key.", + "default": "", + "x-example": "<API_KEY>" + }, + "domain": { + "type": "string", + "description": "Mailgun Domain.", + "default": "", + "x-example": "<DOMAIN>" + }, + "isEuRegion": { + "type": "boolean", + "description": "Set as EU region.", + "default": null, + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "default": "", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "default": "", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the reply to field for the mail. Default value is sender name.", + "default": "", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the reply to field for the mail. Default value is sender email.", + "default": "", + "x-example": "<REPLY_TO_EMAIL>" + } + } + } + } + ] + } + }, + "\/messaging\/providers\/msg91": { + "post": { + "summary": "Create Msg91 provider", + "operationId": "messagingCreateMsg91Provider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new MSG91 provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createMsg91Provider", + "group": "providers", + "weight": 327, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-msg91provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-msg91-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "templateId": { + "type": "string", + "description": "Msg91 template ID", + "default": "", + "x-example": "<TEMPLATE_ID>" + }, + "senderId": { + "type": "string", + "description": "Msg91 sender ID.", + "default": "", + "x-example": "<SENDER_ID>" + }, + "authKey": { + "type": "string", + "description": "Msg91 auth key.", + "default": "", + "x-example": "<AUTH_KEY>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/providers\/msg91\/{providerId}": { + "patch": { + "summary": "Update Msg91 provider", + "operationId": "messagingUpdateMsg91Provider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a MSG91 provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateMsg91Provider", + "group": "providers", + "weight": 340, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-msg91provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-msg91-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + }, + "templateId": { + "type": "string", + "description": "Msg91 template ID.", + "default": "", + "x-example": "<TEMPLATE_ID>" + }, + "senderId": { + "type": "string", + "description": "Msg91 sender ID.", + "default": "", + "x-example": "<SENDER_ID>" + }, + "authKey": { + "type": "string", + "description": "Msg91 auth key.", + "default": "", + "x-example": "<AUTH_KEY>" + } + } + } + } + ] + } + }, + "\/messaging\/providers\/sendgrid": { + "post": { + "summary": "Create Sendgrid provider", + "operationId": "messagingCreateSendgridProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new Sendgrid provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createSendgridProvider", + "group": "providers", + "weight": 325, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-sendgrid-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-sendgrid-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "apiKey": { + "type": "string", + "description": "Sendgrid API key.", + "default": "", + "x-example": "<API_KEY>" + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "default": "", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "default": "", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the reply to field for the mail. Default value is sender name.", + "default": "", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the reply to field for the mail. Default value is sender email.", + "default": "", + "x-example": "email@example.com" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/providers\/sendgrid\/{providerId}": { + "patch": { + "summary": "Update Sendgrid provider", + "operationId": "messagingUpdateSendgridProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a Sendgrid provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateSendgridProvider", + "group": "providers", + "weight": 338, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-sendgrid-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-sendgrid-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + }, + "apiKey": { + "type": "string", + "description": "Sendgrid API key.", + "default": "", + "x-example": "<API_KEY>" + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "default": "", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "default": "", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the Reply To field for the mail. Default value is Sender Name.", + "default": "", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the Reply To field for the mail. Default value is Sender Email.", + "default": "", + "x-example": "<REPLY_TO_EMAIL>" + } + } + } + } + ] + } + }, + "\/messaging\/providers\/smtp": { + "post": { + "summary": "Create SMTP provider", + "operationId": "messagingCreateSmtpProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new SMTP provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createSmtpProvider", + "group": "providers", + "weight": 326, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-smtp-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-smtp-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "host": { + "type": "string", + "description": "SMTP hosts. Either a single hostname or multiple semicolon-delimited hostnames. You can also specify a different port for each host such as `smtp1.example.com:25;smtp2.example.com`. You can also specify encryption type, for example: `tls:\/\/smtp1.example.com:587;ssl:\/\/smtp2.example.com:465\"`. Hosts will be tried in order.", + "default": null, + "x-example": "<HOST>" + }, + "port": { + "type": "integer", + "description": "The default SMTP server port.", + "default": 587, + "x-example": 1 + }, + "username": { + "type": "string", + "description": "Authentication username.", + "default": "", + "x-example": "<USERNAME>" + }, + "password": { + "type": "string", + "description": "Authentication password.", + "default": "", + "x-example": "<PASSWORD>" + }, + "encryption": { + "type": "string", + "description": "Encryption type. Can be omitted, 'ssl', or 'tls'", + "default": "", + "x-example": "none", + "enum": [ + "none", + "ssl", + "tls" + ], + "x-enum-name": "SmtpEncryption", + "x-enum-keys": [] + }, + "autoTLS": { + "type": "boolean", + "description": "Enable SMTP AutoTLS feature.", + "default": true, + "x-example": false + }, + "mailer": { + "type": "string", + "description": "The value to use for the X-Mailer header.", + "default": "", + "x-example": "<MAILER>" + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "default": "", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "default": "", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the reply to field for the mail. Default value is sender name.", + "default": "", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the reply to field for the mail. Default value is sender email.", + "default": "", + "x-example": "email@example.com" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name", + "host" + ] + } + } + ] + } + }, + "\/messaging\/providers\/smtp\/{providerId}": { + "patch": { + "summary": "Update SMTP provider", + "operationId": "messagingUpdateSmtpProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a SMTP provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateSmtpProvider", + "group": "providers", + "weight": 339, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-smtp-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-smtp-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "host": { + "type": "string", + "description": "SMTP hosts. Either a single hostname or multiple semicolon-delimited hostnames. You can also specify a different port for each host such as `smtp1.example.com:25;smtp2.example.com`. You can also specify encryption type, for example: `tls:\/\/smtp1.example.com:587;ssl:\/\/smtp2.example.com:465\"`. Hosts will be tried in order.", + "default": "", + "x-example": "<HOST>" + }, + "port": { + "type": "integer", + "description": "SMTP port.", + "default": null, + "x-example": 1 + }, + "username": { + "type": "string", + "description": "Authentication username.", + "default": "", + "x-example": "<USERNAME>" + }, + "password": { + "type": "string", + "description": "Authentication password.", + "default": "", + "x-example": "<PASSWORD>" + }, + "encryption": { + "type": "string", + "description": "Encryption type. Can be 'ssl' or 'tls'", + "default": "", + "x-example": "none", + "enum": [ + "none", + "ssl", + "tls" + ], + "x-enum-name": "SmtpEncryption", + "x-enum-keys": [] + }, + "autoTLS": { + "type": "boolean", + "description": "Enable SMTP AutoTLS feature.", + "default": null, + "x-example": false + }, + "mailer": { + "type": "string", + "description": "The value to use for the X-Mailer header.", + "default": "", + "x-example": "<MAILER>" + }, + "fromName": { + "type": "string", + "description": "Sender Name.", + "default": "", + "x-example": "<FROM_NAME>" + }, + "fromEmail": { + "type": "string", + "description": "Sender email address.", + "default": "", + "x-example": "email@example.com" + }, + "replyToName": { + "type": "string", + "description": "Name set in the Reply To field for the mail. Default value is Sender Name.", + "default": "", + "x-example": "<REPLY_TO_NAME>" + }, + "replyToEmail": { + "type": "string", + "description": "Email set in the Reply To field for the mail. Default value is Sender Email.", + "default": "", + "x-example": "<REPLY_TO_EMAIL>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + } + } + } + ] + } + }, + "\/messaging\/providers\/telesign": { + "post": { + "summary": "Create Telesign provider", + "operationId": "messagingCreateTelesignProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new Telesign provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createTelesignProvider", + "group": "providers", + "weight": 328, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-telesign-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-telesign-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "from": { + "type": "string", + "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "default": "", + "x-example": "+12065550100" + }, + "customerId": { + "type": "string", + "description": "Telesign customer ID.", + "default": "", + "x-example": "<CUSTOMER_ID>" + }, + "apiKey": { + "type": "string", + "description": "Telesign API key.", + "default": "", + "x-example": "<API_KEY>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/providers\/telesign\/{providerId}": { + "patch": { + "summary": "Update Telesign provider", + "operationId": "messagingUpdateTelesignProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a Telesign provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateTelesignProvider", + "group": "providers", + "weight": 341, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-telesign-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-telesign-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + }, + "customerId": { + "type": "string", + "description": "Telesign customer ID.", + "default": "", + "x-example": "<CUSTOMER_ID>" + }, + "apiKey": { + "type": "string", + "description": "Telesign API key.", + "default": "", + "x-example": "<API_KEY>" + }, + "from": { + "type": "string", + "description": "Sender number.", + "default": "", + "x-example": "<FROM>" + } + } + } + } + ] + } + }, + "\/messaging\/providers\/textmagic": { + "post": { + "summary": "Create Textmagic provider", + "operationId": "messagingCreateTextmagicProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new Textmagic provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createTextmagicProvider", + "group": "providers", + "weight": 329, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-textmagic-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-textmagic-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "from": { + "type": "string", + "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "default": "", + "x-example": "+12065550100" + }, + "username": { + "type": "string", + "description": "Textmagic username.", + "default": "", + "x-example": "<USERNAME>" + }, + "apiKey": { + "type": "string", + "description": "Textmagic apiKey.", + "default": "", + "x-example": "<API_KEY>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/providers\/textmagic\/{providerId}": { + "patch": { + "summary": "Update Textmagic provider", + "operationId": "messagingUpdateTextmagicProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a Textmagic provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateTextmagicProvider", + "group": "providers", + "weight": 342, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-textmagic-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-textmagic-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + }, + "username": { + "type": "string", + "description": "Textmagic username.", + "default": "", + "x-example": "<USERNAME>" + }, + "apiKey": { + "type": "string", + "description": "Textmagic apiKey.", + "default": "", + "x-example": "<API_KEY>" + }, + "from": { + "type": "string", + "description": "Sender number.", + "default": "", + "x-example": "<FROM>" + } + } + } + } + ] + } + }, + "\/messaging\/providers\/twilio": { + "post": { + "summary": "Create Twilio provider", + "operationId": "messagingCreateTwilioProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new Twilio provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createTwilioProvider", + "group": "providers", + "weight": 330, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-twilio-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-twilio-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "from": { + "type": "string", + "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "default": "", + "x-example": "+12065550100" + }, + "accountSid": { + "type": "string", + "description": "Twilio account secret ID.", + "default": "", + "x-example": "<ACCOUNT_SID>" + }, + "authToken": { + "type": "string", + "description": "Twilio authentication token.", + "default": "", + "x-example": "<AUTH_TOKEN>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/providers\/twilio\/{providerId}": { + "patch": { + "summary": "Update Twilio provider", + "operationId": "messagingUpdateTwilioProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a Twilio provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateTwilioProvider", + "group": "providers", + "weight": 343, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-twilio-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-twilio-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + }, + "accountSid": { + "type": "string", + "description": "Twilio account secret ID.", + "default": "", + "x-example": "<ACCOUNT_SID>" + }, + "authToken": { + "type": "string", + "description": "Twilio authentication token.", + "default": "", + "x-example": "<AUTH_TOKEN>" + }, + "from": { + "type": "string", + "description": "Sender number.", + "default": "", + "x-example": "<FROM>" + } + } + } + } + ] + } + }, + "\/messaging\/providers\/vonage": { + "post": { + "summary": "Create Vonage provider", + "operationId": "messagingCreateVonageProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new Vonage provider.", + "responses": { + "201": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "createVonageProvider", + "group": "providers", + "weight": 331, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-vonage-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-vonage-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "providerId": { + "type": "string", + "description": "Provider ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Provider name.", + "default": null, + "x-example": "<NAME>" + }, + "from": { + "type": "string", + "description": "Sender Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "default": "", + "x-example": "+12065550100" + }, + "apiKey": { + "type": "string", + "description": "Vonage API key.", + "default": "", + "x-example": "<API_KEY>" + }, + "apiSecret": { + "type": "string", + "description": "Vonage API secret.", + "default": "", + "x-example": "<API_SECRET>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + } + }, + "required": [ + "providerId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/providers\/vonage\/{providerId}": { + "patch": { + "summary": "Update Vonage provider", + "operationId": "messagingUpdateVonageProvider", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a Vonage provider by its unique ID.", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "updateVonageProvider", + "group": "providers", + "weight": 344, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-vonage-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-vonage-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Provider name.", + "default": "", + "x-example": "<NAME>" + }, + "enabled": { + "type": "boolean", + "description": "Set as enabled.", + "default": null, + "x-example": false + }, + "apiKey": { + "type": "string", + "description": "Vonage API key.", + "default": "", + "x-example": "<API_KEY>" + }, + "apiSecret": { + "type": "string", + "description": "Vonage API secret.", + "default": "", + "x-example": "<API_SECRET>" + }, + "from": { + "type": "string", + "description": "Sender number.", + "default": "", + "x-example": "<FROM>" + } + } + } + } + ] + } + }, + "\/messaging\/providers\/{providerId}": { + "get": { + "summary": "Get provider", + "operationId": "messagingGetProvider", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get a provider by its unique ID.\n", + "responses": { + "200": { + "description": "Provider", + "schema": { + "$ref": "#\/definitions\/provider" + } + } + }, + "x-appwrite": { + "method": "getProvider", + "group": "providers", + "weight": 336, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/get-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/get-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete provider", + "operationId": "messagingDeleteProvider", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "messaging" + ], + "description": "Delete a provider by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteProvider", + "group": "providers", + "weight": 347, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/delete-provider.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/delete-provider.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + } + ] + } + }, + "\/messaging\/providers\/{providerId}\/logs": { + "get": { + "summary": "List provider logs", + "operationId": "messagingListProviderLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get the provider activity logs listed by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "schema": { + "$ref": "#\/definitions\/logList" + } + } + }, + "x-appwrite": { + "method": "listProviderLogs", + "group": "providers", + "weight": 335, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-provider-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-provider-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "providers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "providerId", + "description": "Provider ID.", + "required": true, + "type": "string", + "x-example": "<PROVIDER_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/messaging\/subscribers\/{subscriberId}\/logs": { + "get": { + "summary": "List subscriber logs", + "operationId": "messagingListSubscriberLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get the subscriber activity logs listed by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "schema": { + "$ref": "#\/definitions\/logList" + } + } + }, + "x-appwrite": { + "method": "listSubscriberLogs", + "group": "subscribers", + "weight": 356, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-subscriber-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-subscriber-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "subscriberId", + "description": "Subscriber ID.", + "required": true, + "type": "string", + "x-example": "<SUBSCRIBER_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/messaging\/topics": { + "get": { + "summary": "List topics", + "operationId": "messagingListTopics", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get a list of all topics from the current Appwrite project.", + "responses": { + "200": { + "description": "Topic list", + "schema": { + "$ref": "#\/definitions\/topicList" + } + } + }, + "x-appwrite": { + "method": "listTopics", + "group": "topics", + "weight": 349, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-topics.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-topics.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, description, emailTotal, smsTotal, pushTotal", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create topic", + "operationId": "messagingCreateTopic", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new topic.", + "responses": { + "201": { + "description": "Topic", + "schema": { + "$ref": "#\/definitions\/topic" + } + } + }, + "x-appwrite": { + "method": "createTopic", + "group": "topics", + "weight": 348, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-topic.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-topic.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "topicId": { + "type": "string", + "description": "Topic ID. Choose a custom Topic ID or a new Topic ID.", + "default": null, + "x-example": "<TOPIC_ID>" + }, + "name": { + "type": "string", + "description": "Topic Name.", + "default": null, + "x-example": "<NAME>" + }, + "subscribe": { + "type": "array", + "description": "An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https:\/\/appwrite.io\/docs\/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.", + "default": [ + "users" + ], + "x-example": "[\"any\"]", + "items": { + "type": "string" + } + } + }, + "required": [ + "topicId", + "name" + ] + } + } + ] + } + }, + "\/messaging\/topics\/{topicId}": { + "get": { + "summary": "Get topic", + "operationId": "messagingGetTopic", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get a topic by its unique ID.\n", + "responses": { + "200": { + "description": "Topic", + "schema": { + "$ref": "#\/definitions\/topic" + } + } + }, + "x-appwrite": { + "method": "getTopic", + "group": "topics", + "weight": 351, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/get-topic.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/get-topic.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID.", + "required": true, + "type": "string", + "x-example": "<TOPIC_ID>", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update topic", + "operationId": "messagingUpdateTopic", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Update a topic by its unique ID.\n", + "responses": { + "200": { + "description": "Topic", + "schema": { + "$ref": "#\/definitions\/topic" + } + } + }, + "x-appwrite": { + "method": "updateTopic", + "group": "topics", + "weight": 352, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/update-topic.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/update-topic.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID.", + "required": true, + "type": "string", + "x-example": "<TOPIC_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Topic Name.", + "default": null, + "x-example": "<NAME>" + }, + "subscribe": { + "type": "array", + "description": "An array of role strings with subscribe permission. By default all users are granted with any subscribe permission. [learn more about roles](https:\/\/appwrite.io\/docs\/permissions#permission-roles). Maximum of 100 roles are allowed, each 64 characters long.", + "default": null, + "x-example": "[\"any\"]", + "items": { + "type": "string" + } + } + } + } + } + ] + }, + "delete": { + "summary": "Delete topic", + "operationId": "messagingDeleteTopic", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "messaging" + ], + "description": "Delete a topic by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteTopic", + "group": "topics", + "weight": 353, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/delete-topic.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/delete-topic.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID.", + "required": true, + "type": "string", + "x-example": "<TOPIC_ID>", + "in": "path" + } + ] + } + }, + "\/messaging\/topics\/{topicId}\/logs": { + "get": { + "summary": "List topic logs", + "operationId": "messagingListTopicLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get the topic activity logs listed by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "schema": { + "$ref": "#\/definitions\/logList" + } + } + }, + "x-appwrite": { + "method": "listTopicLogs", + "group": "topics", + "weight": 350, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-topic-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-topic-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "topics.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID.", + "required": true, + "type": "string", + "x-example": "<TOPIC_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/messaging\/topics\/{topicId}\/subscribers": { + "get": { + "summary": "List subscribers", + "operationId": "messagingListSubscribers", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get a list of all subscribers from the current Appwrite project.", + "responses": { + "200": { + "description": "Subscriber list", + "schema": { + "$ref": "#\/definitions\/subscriberList" + } + } + }, + "x-appwrite": { + "method": "listSubscribers", + "group": "subscribers", + "weight": 355, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/list-subscribers.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/list-subscribers.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID subscribed to.", + "required": true, + "type": "string", + "x-example": "<TOPIC_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, provider, type, enabled", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create subscriber", + "operationId": "messagingCreateSubscriber", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Create a new subscriber.", + "responses": { + "201": { + "description": "Subscriber", + "schema": { + "$ref": "#\/definitions\/subscriber" + } + } + }, + "x-appwrite": { + "method": "createSubscriber", + "group": "subscribers", + "weight": 354, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/create-subscriber.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/create-subscriber.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.write", + "platforms": [ + "server", + "client", + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "JWT": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [], + "Session": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID to subscribe to.", + "required": true, + "type": "string", + "x-example": "<TOPIC_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "subscriberId": { + "type": "string", + "description": "Subscriber ID. Choose a custom Subscriber ID or a new Subscriber ID.", + "default": null, + "x-example": "<SUBSCRIBER_ID>" + }, + "targetId": { + "type": "string", + "description": "Target ID. The target ID to link to the specified Topic ID.", + "default": null, + "x-example": "<TARGET_ID>" + } + }, + "required": [ + "subscriberId", + "targetId" + ] + } + } + ] + } + }, + "\/messaging\/topics\/{topicId}\/subscribers\/{subscriberId}": { + "get": { + "summary": "Get subscriber", + "operationId": "messagingGetSubscriber", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "messaging" + ], + "description": "Get a subscriber by its unique ID.\n", + "responses": { + "200": { + "description": "Subscriber", + "schema": { + "$ref": "#\/definitions\/subscriber" + } + } + }, + "x-appwrite": { + "method": "getSubscriber", + "group": "subscribers", + "weight": 357, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/get-subscriber.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/get-subscriber.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID subscribed to.", + "required": true, + "type": "string", + "x-example": "<TOPIC_ID>", + "in": "path" + }, + { + "name": "subscriberId", + "description": "Subscriber ID.", + "required": true, + "type": "string", + "x-example": "<SUBSCRIBER_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete subscriber", + "operationId": "messagingDeleteSubscriber", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "messaging" + ], + "description": "Delete a subscriber by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSubscriber", + "group": "subscribers", + "weight": 358, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "messaging\/delete-subscriber.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/messaging\/delete-subscriber.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "subscribers.write", + "platforms": [ + "server", + "client", + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "JWT": [] + } + }, + "security": [ + { + "Project": [], + "JWT": [], + "Session": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "topicId", + "description": "Topic ID. The topic ID subscribed to.", + "required": true, + "type": "string", + "x-example": "<TOPIC_ID>", + "in": "path" + }, + { + "name": "subscriberId", + "description": "Subscriber ID.", + "required": true, + "type": "string", + "x-example": "<SUBSCRIBER_ID>", + "in": "path" + } + ] + } + }, + "\/sites": { + "get": { + "summary": "List sites", + "operationId": "sitesList", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get a list of all the project's sites. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Sites List", + "schema": { + "$ref": "#\/definitions\/siteList" + } + } + }, + "x-appwrite": { + "method": "list", + "group": "sites", + "weight": 407, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the project's sites. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, enabled, framework, deploymentId, buildCommand, installCommand, outputDirectory, installationId", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create site", + "operationId": "sitesCreate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Create a new site.", + "responses": { + "201": { + "description": "Site", + "schema": { + "$ref": "#\/definitions\/site" + } + } + }, + "x-appwrite": { + "method": "create", + "group": "sites", + "weight": 405, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new site.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "siteId": { + "type": "string", + "description": "Site ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<SITE_ID>" + }, + "name": { + "type": "string", + "description": "Site name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "framework": { + "type": "string", + "description": "Sites framework.", + "default": null, + "x-example": "analog", + "enum": [ + "analog", + "angular", + "nextjs", + "react", + "nuxt", + "vue", + "sveltekit", + "astro", + "remix", + "lynx", + "flutter", + "react-native", + "vite", + "other" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "enabled": { + "type": "boolean", + "description": "Is site enabled? When set to 'disabled', users cannot access the site but Server SDKs with and API key can still access the site. No data is lost when this is toggled.", + "default": true, + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.", + "default": true, + "x-example": false + }, + "timeout": { + "type": "integer", + "description": "Maximum request time in seconds.", + "default": 30, + "x-example": 1 + }, + "installCommand": { + "type": "string", + "description": "Install Command.", + "default": "", + "x-example": "<INSTALL_COMMAND>" + }, + "buildCommand": { + "type": "string", + "description": "Build Command.", + "default": "", + "x-example": "<BUILD_COMMAND>" + }, + "outputDirectory": { + "type": "string", + "description": "Output Directory for site.", + "default": "", + "x-example": "<OUTPUT_DIRECTORY>" + }, + "buildRuntime": { + "type": "string", + "description": "Runtime to use during build step.", + "default": null, + "x-example": "node-14.5", + "enum": [ + "node-14.5", + "node-16.0", + "node-18.0", + "node-19.0", + "node-20.0", + "node-21.0", + "node-22", + "php-8.0", + "php-8.1", + "php-8.2", + "php-8.3", + "ruby-3.0", + "ruby-3.1", + "ruby-3.2", + "ruby-3.3", + "python-3.8", + "python-3.9", + "python-3.10", + "python-3.11", + "python-3.12", + "python-ml-3.11", + "python-ml-3.12", + "deno-1.21", + "deno-1.24", + "deno-1.35", + "deno-1.40", + "deno-1.46", + "deno-2.0", + "dart-2.15", + "dart-2.16", + "dart-2.17", + "dart-2.18", + "dart-2.19", + "dart-3.0", + "dart-3.1", + "dart-3.3", + "dart-3.5", + "dart-3.8", + "dotnet-6.0", + "dotnet-7.0", + "dotnet-8.0", + "java-8.0", + "java-11.0", + "java-17.0", + "java-18.0", + "java-21.0", + "java-22", + "swift-5.5", + "swift-5.8", + "swift-5.9", + "swift-5.10", + "kotlin-1.6", + "kotlin-1.8", + "kotlin-1.9", + "kotlin-2.0", + "cpp-17", + "cpp-20", + "bun-1.0", + "bun-1.1", + "go-1.23", + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29", + "flutter-3.32" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "adapter": { + "type": "string", + "description": "Framework adapter defining rendering strategy. Allowed values are: static, ssr", + "default": "", + "x-example": "static", + "enum": [ + "static", + "ssr" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "installationId": { + "type": "string", + "description": "Appwrite Installation ID for VCS (Version Control System) deployment.", + "default": "", + "x-example": "<INSTALLATION_ID>" + }, + "fallbackFile": { + "type": "string", + "description": "Fallback file for single page application sites.", + "default": "", + "x-example": "<FALLBACK_FILE>" + }, + "providerRepositoryId": { + "type": "string", + "description": "Repository ID of the repo linked to the site.", + "default": "", + "x-example": "<PROVIDER_REPOSITORY_ID>" + }, + "providerBranch": { + "type": "string", + "description": "Production branch for the repo linked to the site.", + "default": "", + "x-example": "<PROVIDER_BRANCH>" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is the VCS (Version Control System) connection in silent mode for the repo linked to the site? In silent mode, comments will not be made on commits and pull requests.", + "default": false, + "x-example": false + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to site code in the linked repo.", + "default": "", + "x-example": "<PROVIDER_ROOT_DIRECTORY>" + }, + "specification": { + "type": "string", + "description": "Framework specification for the site and builds.", + "default": "s-1vcpu-512mb", + "x-example": null + } + }, + "required": [ + "siteId", + "name", + "framework", + "buildRuntime" + ] + } + } + ] + } + }, + "\/sites\/frameworks": { + "get": { + "summary": "List frameworks", + "operationId": "sitesListFrameworks", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get a list of all frameworks that are currently available on the server instance.", + "responses": { + "200": { + "description": "Frameworks List", + "schema": { + "$ref": "#\/definitions\/frameworkList" + } + } + }, + "x-appwrite": { + "method": "listFrameworks", + "group": "frameworks", + "weight": 410, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-frameworks.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all frameworks that are currently available on the server instance.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/sites\/specifications": { + "get": { + "summary": "List specifications", + "operationId": "sitesListSpecifications", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "List allowed site specifications for this instance.", + "responses": { + "200": { + "description": "Specifications List", + "schema": { + "$ref": "#\/definitions\/specificationList" + } + } + }, + "x-appwrite": { + "method": "listSpecifications", + "group": "frameworks", + "weight": 433, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-specifications.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList allowed site specifications for this instance.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ] + } + }, + "\/sites\/{siteId}": { + "get": { + "summary": "Get site", + "operationId": "sitesGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get a site by its unique ID.", + "responses": { + "200": { + "description": "Site", + "schema": { + "$ref": "#\/definitions\/site" + } + } + }, + "x-appwrite": { + "method": "get", + "group": "sites", + "weight": 406, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a site by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update site", + "operationId": "sitesUpdate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Update site by its unique ID.", + "responses": { + "200": { + "description": "Site", + "schema": { + "$ref": "#\/definitions\/site" + } + } + }, + "x-appwrite": { + "method": "update", + "group": "sites", + "weight": 408, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/update.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate site by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Site name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "framework": { + "type": "string", + "description": "Sites framework.", + "default": null, + "x-example": "analog", + "enum": [ + "analog", + "angular", + "nextjs", + "react", + "nuxt", + "vue", + "sveltekit", + "astro", + "remix", + "lynx", + "flutter", + "react-native", + "vite", + "other" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "enabled": { + "type": "boolean", + "description": "Is site enabled? When set to 'disabled', users cannot access the site but Server SDKs with and API key can still access the site. No data is lost when this is toggled.", + "default": true, + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.", + "default": true, + "x-example": false + }, + "timeout": { + "type": "integer", + "description": "Maximum request time in seconds.", + "default": 30, + "x-example": 1 + }, + "installCommand": { + "type": "string", + "description": "Install Command.", + "default": "", + "x-example": "<INSTALL_COMMAND>" + }, + "buildCommand": { + "type": "string", + "description": "Build Command.", + "default": "", + "x-example": "<BUILD_COMMAND>" + }, + "outputDirectory": { + "type": "string", + "description": "Output Directory for site.", + "default": "", + "x-example": "<OUTPUT_DIRECTORY>" + }, + "buildRuntime": { + "type": "string", + "description": "Runtime to use during build step.", + "default": "", + "x-example": "node-14.5", + "enum": [ + "node-14.5", + "node-16.0", + "node-18.0", + "node-19.0", + "node-20.0", + "node-21.0", + "node-22", + "php-8.0", + "php-8.1", + "php-8.2", + "php-8.3", + "ruby-3.0", + "ruby-3.1", + "ruby-3.2", + "ruby-3.3", + "python-3.8", + "python-3.9", + "python-3.10", + "python-3.11", + "python-3.12", + "python-ml-3.11", + "python-ml-3.12", + "deno-1.21", + "deno-1.24", + "deno-1.35", + "deno-1.40", + "deno-1.46", + "deno-2.0", + "dart-2.15", + "dart-2.16", + "dart-2.17", + "dart-2.18", + "dart-2.19", + "dart-3.0", + "dart-3.1", + "dart-3.3", + "dart-3.5", + "dart-3.8", + "dotnet-6.0", + "dotnet-7.0", + "dotnet-8.0", + "java-8.0", + "java-11.0", + "java-17.0", + "java-18.0", + "java-21.0", + "java-22", + "swift-5.5", + "swift-5.8", + "swift-5.9", + "swift-5.10", + "kotlin-1.6", + "kotlin-1.8", + "kotlin-1.9", + "kotlin-2.0", + "cpp-17", + "cpp-20", + "bun-1.0", + "bun-1.1", + "go-1.23", + "static-1", + "flutter-3.24", + "flutter-3.27", + "flutter-3.29", + "flutter-3.32" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "adapter": { + "type": "string", + "description": "Framework adapter defining rendering strategy. Allowed values are: static, ssr", + "default": "", + "x-example": "static", + "enum": [ + "static", + "ssr" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "fallbackFile": { + "type": "string", + "description": "Fallback file for single page application sites.", + "default": "", + "x-example": "<FALLBACK_FILE>" + }, + "installationId": { + "type": "string", + "description": "Appwrite Installation ID for VCS (Version Control System) deployment.", + "default": "", + "x-example": "<INSTALLATION_ID>" + }, + "providerRepositoryId": { + "type": "string", + "description": "Repository ID of the repo linked to the site.", + "default": "", + "x-example": "<PROVIDER_REPOSITORY_ID>" + }, + "providerBranch": { + "type": "string", + "description": "Production branch for the repo linked to the site.", + "default": "", + "x-example": "<PROVIDER_BRANCH>" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is the VCS (Version Control System) connection in silent mode for the repo linked to the site? In silent mode, comments will not be made on commits and pull requests.", + "default": false, + "x-example": false + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to site code in the linked repo.", + "default": "", + "x-example": "<PROVIDER_ROOT_DIRECTORY>" + }, + "specification": { + "type": "string", + "description": "Framework specification for the site and builds.", + "default": "s-1vcpu-512mb", + "x-example": null + } + }, + "required": [ + "name", + "framework" + ] + } + } + ] + }, + "delete": { + "summary": "Delete site", + "operationId": "sitesDelete", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "sites" + ], + "description": "Delete a site by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "sites", + "weight": 409, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a site by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + } + ] + } + }, + "\/sites\/{siteId}\/deployment": { + "patch": { + "summary": "Update site's deployment", + "operationId": "sitesUpdateSiteDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Update the site active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your site.", + "responses": { + "200": { + "description": "Site", + "schema": { + "$ref": "#\/definitions\/site" + } + } + }, + "x-appwrite": { + "method": "updateSiteDeployment", + "group": "sites", + "weight": 416, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/update-site-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate the site active deployment. Use this endpoint to switch the code deployment that should be used when visitor opens your site.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "deploymentId": { + "type": "string", + "description": "Deployment ID.", + "default": null, + "x-example": "<DEPLOYMENT_ID>" + } + }, + "required": [ + "deploymentId" + ] + } + } + ] + } + }, + "\/sites\/{siteId}\/deployments": { + "get": { + "summary": "List deployments", + "operationId": "sitesListDeployments", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get a list of all the site's code deployments. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Deployments List", + "schema": { + "$ref": "#\/definitions\/deploymentList" + } + } + }, + "x-appwrite": { + "method": "listDeployments", + "group": "deployments", + "weight": 415, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-deployments.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all the site's code deployments. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: buildSize, sourceSize, totalSize, buildDuration, status, activate, type", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create deployment", + "operationId": "sitesCreateDeployment", + "consumes": [ + "multipart\/form-data" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Create a new site code deployment. Use this endpoint to upload a new version of your site code. To activate your newly uploaded code, you'll need to update the function's deployment to use your new deployment ID.", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createDeployment", + "group": "deployments", + "weight": 411, + "cookies": false, + "type": "upload", + "deprecated": false, + "demo": "sites\/create-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new site code deployment. Use this endpoint to upload a new version of your site code. To activate your newly uploaded code, you'll need to update the function's deployment to use your new deployment ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": true, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "installCommand", + "description": "Install Commands.", + "required": false, + "type": "string", + "x-example": "<INSTALL_COMMAND>", + "in": "formData" + }, + { + "name": "buildCommand", + "description": "Build Commands.", + "required": false, + "type": "string", + "x-example": "<BUILD_COMMAND>", + "in": "formData" + }, + { + "name": "outputDirectory", + "description": "Output Directory.", + "required": false, + "type": "string", + "x-example": "<OUTPUT_DIRECTORY>", + "in": "formData" + }, + { + "name": "code", + "description": "Gzip file with your code package. When used with the Appwrite CLI, pass the path to your code directory, and the CLI will automatically package your code. Use a path that is within the current directory.", + "required": true, + "type": "file", + "in": "formData" + }, + { + "name": "activate", + "description": "Automatically activate the deployment when it is finished building.", + "required": true, + "type": "boolean", + "x-example": false, + "in": "formData" + } + ] + } + }, + "\/sites\/{siteId}\/deployments\/duplicate": { + "post": { + "summary": "Create duplicate deployment", + "operationId": "sitesCreateDuplicateDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Create a new build for an existing site deployment. This endpoint allows you to rebuild a deployment with the updated site configuration, including its commands and output directory if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createDuplicateDeployment", + "group": "deployments", + "weight": 419, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create-duplicate-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new build for an existing site deployment. This endpoint allows you to rebuild a deployment with the updated site configuration, including its commands and output directory if they have been modified. The build process will be queued and executed asynchronously. The original deployment's code will be preserved and used for the new build.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "deploymentId": { + "type": "string", + "description": "Deployment ID.", + "default": null, + "x-example": "<DEPLOYMENT_ID>" + } + }, + "required": [ + "deploymentId" + ] + } + } + ] + } + }, + "\/sites\/{siteId}\/deployments\/template": { + "post": { + "summary": "Create template deployment", + "operationId": "sitesCreateTemplateDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Create a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/sites#listTemplates) to find the template details.", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createTemplateDeployment", + "group": "deployments", + "weight": 412, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create-template-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment based on a template.\n\nUse this endpoint with combination of [listTemplates](https:\/\/appwrite.io\/docs\/server\/sites#listTemplates) to find the template details.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "repository": { + "type": "string", + "description": "Repository name of the template.", + "default": null, + "x-example": "<REPOSITORY>" + }, + "owner": { + "type": "string", + "description": "The name of the owner of the template.", + "default": null, + "x-example": "<OWNER>" + }, + "rootDirectory": { + "type": "string", + "description": "Path to site code in the template repo.", + "default": null, + "x-example": "<ROOT_DIRECTORY>" + }, + "version": { + "type": "string", + "description": "Version (tag) for the repo linked to the site template.", + "default": null, + "x-example": "<VERSION>" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "default": false, + "x-example": false + } + }, + "required": [ + "repository", + "owner", + "rootDirectory", + "version" + ] + } + } + ] + } + }, + "\/sites\/{siteId}\/deployments\/vcs": { + "post": { + "summary": "Create VCS deployment", + "operationId": "sitesCreateVcsDeployment", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Create a deployment when a site is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", + "responses": { + "202": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "createVcsDeployment", + "group": "deployments", + "weight": 413, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create-vcs-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a deployment when a site is connected to VCS.\n\nThis endpoint lets you create deployment from a branch, commit, or a tag.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Type of reference passed. Allowed values are: branch, commit", + "default": null, + "x-example": "branch", + "enum": [ + "branch", + "commit", + "tag" + ], + "x-enum-name": "VCSDeploymentType", + "x-enum-keys": [] + }, + "reference": { + "type": "string", + "description": "VCS reference to create deployment from. Depending on type this can be: branch name, commit hash", + "default": null, + "x-example": "<REFERENCE>" + }, + "activate": { + "type": "boolean", + "description": "Automatically activate the deployment when it is finished building.", + "default": false, + "x-example": false + } + }, + "required": [ + "type", + "reference" + ] + } + } + ] + } + }, + "\/sites\/{siteId}\/deployments\/{deploymentId}": { + "get": { + "summary": "Get deployment", + "operationId": "sitesGetDeployment", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get a site deployment by its unique ID.", + "responses": { + "200": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "getDeployment", + "group": "deployments", + "weight": 414, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a site deployment by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "type": "string", + "x-example": "<DEPLOYMENT_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete deployment", + "operationId": "sitesDeleteDeployment", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "sites" + ], + "description": "Delete a site deployment by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteDeployment", + "group": "deployments", + "weight": 417, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/delete-deployment.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a site deployment by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "type": "string", + "x-example": "<DEPLOYMENT_ID>", + "in": "path" + } + ] + } + }, + "\/sites\/{siteId}\/deployments\/{deploymentId}\/download": { + "get": { + "summary": "Get deployment download", + "operationId": "sitesGetDeploymentDownload", + "consumes": [], + "produces": [ + "*\/*" + ], + "tags": [ + "sites" + ], + "description": "Get a site deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "responses": { + "200": { + "description": "File", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getDeploymentDownload", + "group": "deployments", + "weight": 418, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "sites\/get-deployment-download.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a site deployment content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "type": "string", + "x-example": "<DEPLOYMENT_ID>", + "in": "path" + }, + { + "name": "type", + "description": "Deployment file to download. Can be: \"source\", \"output\".", + "required": false, + "type": "string", + "x-example": "source", + "enum": [ + "source", + "output" + ], + "x-enum-name": "DeploymentDownloadType", + "x-enum-keys": [], + "default": "source", + "in": "query" + } + ] + } + }, + "\/sites\/{siteId}\/deployments\/{deploymentId}\/status": { + "patch": { + "summary": "Update deployment status", + "operationId": "sitesUpdateDeploymentStatus", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Cancel an ongoing site deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", + "responses": { + "200": { + "description": "Deployment", + "schema": { + "$ref": "#\/definitions\/deployment" + } + } + }, + "x-appwrite": { + "method": "updateDeploymentStatus", + "group": "deployments", + "weight": 420, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/update-deployment-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCancel an ongoing site deployment build. If the build is already in progress, it will be stopped and marked as canceled. If the build hasn't started yet, it will be marked as canceled without executing. You cannot cancel builds that have already completed (status 'ready') or failed. The response includes the final build status and details.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "deploymentId", + "description": "Deployment ID.", + "required": true, + "type": "string", + "x-example": "<DEPLOYMENT_ID>", + "in": "path" + } + ] + } + }, + "\/sites\/{siteId}\/logs": { + "get": { + "summary": "List logs", + "operationId": "sitesListLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get a list of all site logs. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Executions List", + "schema": { + "$ref": "#\/definitions\/executionList" + } + } + }, + "x-appwrite": { + "method": "listLogs", + "group": "logs", + "weight": 422, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all site logs. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "log.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: trigger, status, responseStatusCode, duration, requestMethod, requestPath, deploymentId", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/sites\/{siteId}\/logs\/{logId}": { + "get": { + "summary": "Get log", + "operationId": "sitesGetLog", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get a site request log by its unique ID.", + "responses": { + "200": { + "description": "Execution", + "schema": { + "$ref": "#\/definitions\/execution" + } + } + }, + "x-appwrite": { + "method": "getLog", + "group": "logs", + "weight": 421, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get-log.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a site request log by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "log.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "logId", + "description": "Log ID.", + "required": true, + "type": "string", + "x-example": "<LOG_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete log", + "operationId": "sitesDeleteLog", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Delete a site log by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteLog", + "group": "logs", + "weight": 423, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/delete-log.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a site log by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "log.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "logId", + "description": "Log ID.", + "required": true, + "type": "string", + "x-example": "<LOG_ID>", + "in": "path" + } + ] + } + }, + "\/sites\/{siteId}\/variables": { + "get": { + "summary": "List variables", + "operationId": "sitesListVariables", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get a list of all variables of a specific site.", + "responses": { + "200": { + "description": "Variables List", + "schema": { + "$ref": "#\/definitions\/variableList" + } + } + }, + "x-appwrite": { + "method": "listVariables", + "group": "variables", + "weight": 426, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/list-variables.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a list of all variables of a specific site.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + } + ] + }, + "post": { + "summary": "Create variable", + "operationId": "sitesCreateVariable", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Create a new site variable. These variables can be accessed during build and runtime (server-side rendering) as environment variables.", + "responses": { + "201": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "createVariable", + "group": "variables", + "weight": 424, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/create-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new site variable. These variables can be accessed during build and runtime (server-side rendering) as environment variables.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "default": null, + "x-example": "<KEY>" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "default": null, + "x-example": "<VALUE>" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only sites can read them during build and runtime.", + "default": true, + "x-example": false + } + }, + "required": [ + "key", + "value" + ] + } + } + ] + } + }, + "\/sites\/{siteId}\/variables\/{variableId}": { + "get": { + "summary": "Get variable", + "operationId": "sitesGetVariable", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Get a variable by its unique ID.", + "responses": { + "200": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "getVariable", + "group": "variables", + "weight": 425, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/get-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "type": "string", + "x-example": "<VARIABLE_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update variable", + "operationId": "sitesUpdateVariable", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "sites" + ], + "description": "Update variable by its unique ID.", + "responses": { + "200": { + "description": "Variable", + "schema": { + "$ref": "#\/definitions\/variable" + } + } + }, + "x-appwrite": { + "method": "updateVariable", + "group": "variables", + "weight": 427, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/update-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "type": "string", + "x-example": "<VARIABLE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Variable key. Max length: 255 chars.", + "default": null, + "x-example": "<KEY>" + }, + "value": { + "type": "string", + "description": "Variable value. Max length: 8192 chars.", + "default": null, + "x-example": "<VALUE>" + }, + "secret": { + "type": "boolean", + "description": "Secret variables can be updated or deleted, but only sites can read them during build and runtime.", + "default": null, + "x-example": false + } + }, + "required": [ + "key" + ] + } + } + ] + }, + "delete": { + "summary": "Delete variable", + "operationId": "sitesDeleteVariable", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "sites" + ], + "description": "Delete a variable by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteVariable", + "group": "variables", + "weight": 428, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "sites\/delete-variable.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a variable by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "sites.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "siteId", + "description": "Site unique ID.", + "required": true, + "type": "string", + "x-example": "<SITE_ID>", + "in": "path" + }, + { + "name": "variableId", + "description": "Variable unique ID.", + "required": true, + "type": "string", + "x-example": "<VARIABLE_ID>", + "in": "path" + } + ] + } + }, + "\/storage\/buckets": { + "get": { + "summary": "List buckets", + "operationId": "storageListBuckets", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Get a list of all the storage buckets. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Buckets List", + "schema": { + "$ref": "#\/definitions\/bucketList" + } + } + }, + "x-appwrite": { + "method": "listBuckets", + "group": "buckets", + "weight": 209, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/list-buckets.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/list-buckets.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: enabled, name, fileSecurity, maximumFileSize, encryption, antivirus", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create bucket", + "operationId": "storageCreateBucket", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Create a new storage bucket.", + "responses": { + "201": { + "description": "Bucket", + "schema": { + "$ref": "#\/definitions\/bucket" + } + } + }, + "x-appwrite": { + "method": "createBucket", + "group": "buckets", + "weight": 208, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/create-bucket.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/create-bucket.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "bucketId": { + "type": "string", + "description": "Unique Id. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<BUCKET_ID>" + }, + "name": { + "type": "string", + "description": "Bucket name", + "default": null, + "x-example": "<NAME>" + }, + "permissions": { + "type": "array", + "description": "An array of permission strings. By default, no user is granted with any permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "fileSecurity": { + "type": "boolean", + "description": "Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": false, + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Is bucket enabled? When set to 'disabled', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.", + "default": true, + "x-example": false + }, + "maximumFileSize": { + "type": "integer", + "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", + "default": {}, + "x-example": 1 + }, + "allowedFileExtensions": { + "type": "array", + "description": "Allowed file extensions. Maximum of 100 extensions are allowed, each 64 characters long.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "compression": { + "type": "string", + "description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", + "default": "none", + "x-example": "none", + "enum": [ + "none", + "gzip", + "zstd" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "encryption": { + "type": "boolean", + "description": "Is encryption enabled? For file size above 20MB encryption is skipped even if it's enabled", + "default": true, + "x-example": false + }, + "antivirus": { + "type": "boolean", + "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", + "default": true, + "x-example": false + } + }, + "required": [ + "bucketId", + "name" + ] + } + } + ] + } + }, + "\/storage\/buckets\/{bucketId}": { + "get": { + "summary": "Get bucket", + "operationId": "storageGetBucket", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Get a storage bucket by its unique ID. This endpoint response returns a JSON object with the storage bucket metadata.", + "responses": { + "200": { + "description": "Bucket", + "schema": { + "$ref": "#\/definitions\/bucket" + } + } + }, + "x-appwrite": { + "method": "getBucket", + "group": "buckets", + "weight": 210, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/get-bucket.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-bucket.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Bucket unique ID.", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update bucket", + "operationId": "storageUpdateBucket", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Update a storage bucket by its unique ID.", + "responses": { + "200": { + "description": "Bucket", + "schema": { + "$ref": "#\/definitions\/bucket" + } + } + }, + "x-appwrite": { + "method": "updateBucket", + "group": "buckets", + "weight": 211, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/update-bucket.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/update-bucket.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Bucket unique ID.", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Bucket name", + "default": null, + "x-example": "<NAME>" + }, + "permissions": { + "type": "array", + "description": "An array of permission strings. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + }, + "fileSecurity": { + "type": "boolean", + "description": "Enables configuring permissions for individual file. A user needs one of file or bucket level permissions to access a file. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": false, + "x-example": false + }, + "enabled": { + "type": "boolean", + "description": "Is bucket enabled? When set to 'disabled', users cannot access the files in this bucket but Server SDKs with and API key can still access the bucket. No files are lost when this is toggled.", + "default": true, + "x-example": false + }, + "maximumFileSize": { + "type": "integer", + "description": "Maximum file size allowed in bytes. Maximum allowed value is 30MB.", + "default": {}, + "x-example": 1 + }, + "allowedFileExtensions": { + "type": "array", + "description": "Allowed file extensions. Maximum of 100 extensions are allowed, each 64 characters long.", + "default": [], + "x-example": null, + "items": { + "type": "string" + } + }, + "compression": { + "type": "string", + "description": "Compression algorithm choosen for compression. Can be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd), For file size above 20MB compression is skipped even if it's enabled", + "default": "none", + "x-example": "none", + "enum": [ + "none", + "gzip", + "zstd" + ], + "x-enum-name": null, + "x-enum-keys": [] + }, + "encryption": { + "type": "boolean", + "description": "Is encryption enabled? For file size above 20MB encryption is skipped even if it's enabled", + "default": true, + "x-example": false + }, + "antivirus": { + "type": "boolean", + "description": "Is virus scanning enabled? For file size above 20MB AntiVirus scanning is skipped even if it's enabled", + "default": true, + "x-example": false + } + }, + "required": [ + "name" + ] + } + } + ] + }, + "delete": { + "summary": "Delete bucket", + "operationId": "storageDeleteBucket", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "storage" + ], + "description": "Delete a storage bucket by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteBucket", + "group": "buckets", + "weight": 212, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/delete-bucket.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/delete-bucket.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "buckets.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Bucket unique ID.", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files": { + "get": { + "summary": "List files", + "operationId": "storageListFiles", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Get a list of all the user files. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Files List", + "schema": { + "$ref": "#\/definitions\/fileList" + } + } + }, + "x-appwrite": { + "method": "listFiles", + "group": "files", + "weight": 214, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/list-files.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/list-files.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, signature, mimeType, sizeOriginal, chunksTotal, chunksUploaded", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create file", + "operationId": "storageCreateFile", + "consumes": [ + "multipart\/form-data" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Create a new file. Before using this route, you should create a new bucket resource using either a [server integration](https:\/\/appwrite.io\/docs\/server\/storage#storageCreateBucket) API or directly from your Appwrite console.\n\nLarger files should be uploaded using multiple requests with the [content-range](https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTTP\/Headers\/Content-Range) header to send a partial request with a maximum supported chunk of `5MB`. The `content-range` header values should always be in bytes.\n\nWhen the first request is sent, the server will return the **File** object, and the subsequent part request must include the file's **id** in `x-appwrite-id` header to allow the server to know that the partial upload is for the existing file and not for a new one.\n\nIf you're creating a new file using one of the Appwrite SDKs, all the chunking logic will be managed by the SDK internally.\n", + "responses": { + "201": { + "description": "File", + "schema": { + "$ref": "#\/definitions\/file" + } + } + }, + "x-appwrite": { + "method": "createFile", + "group": "files", + "weight": 213, + "cookies": false, + "type": "upload", + "deprecated": false, + "demo": "storage\/create-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/create-file.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId},chunkId:{chunkId}", + "scope": "files.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "required": true, + "x-upload-id": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "formData" + }, + { + "name": "file", + "description": "Binary file. Appwrite SDKs provide helpers to handle file input. [Learn about file input](https:\/\/appwrite.io\/docs\/products\/storage\/upload-download#input-file).", + "required": true, + "type": "file", + "in": "formData" + }, + { + "name": "permissions", + "description": "An array of permission strings. By default, only the current user is granted all permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "x-example": "[\"read(\"any\")\"]", + "in": "formData" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}": { + "get": { + "summary": "Get file", + "operationId": "storageGetFile", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Get a file by its unique ID. This endpoint response returns a JSON object with the file metadata.", + "responses": { + "200": { + "description": "File", + "schema": { + "$ref": "#\/definitions\/file" + } + } + }, + "x-appwrite": { + "method": "getFile", + "group": "files", + "weight": 215, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/get-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update file", + "operationId": "storageUpdateFile", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "storage" + ], + "description": "Update a file by its unique ID. Only users with write permissions have access to update this resource.", + "responses": { + "200": { + "description": "File", + "schema": { + "$ref": "#\/definitions\/file" + } + } + }, + "x-appwrite": { + "method": "updateFile", + "group": "files", + "weight": 220, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/update-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/update-file.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "files.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the file", + "default": null, + "x-example": "<NAME>" + }, + "permissions": { + "type": "array", + "description": "An array of permission string. By default, the current permissions are inherited. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "default": null, + "x-example": "[\"read(\"any\")\"]", + "items": { + "type": "string" + } + } + } + } + } + ] + }, + "delete": { + "summary": "Delete file", + "operationId": "storageDeleteFile", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "storage" + ], + "description": "Delete a file by its unique ID. Only users with write permissions have access to delete this resource.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteFile", + "group": "files", + "weight": 221, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "storage\/delete-file.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/delete-file.md", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "files.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/download": { + "get": { + "summary": "Get file for download", + "operationId": "storageGetFileDownload", + "consumes": [], + "produces": [ + "*\/*" + ], + "tags": [ + "storage" + ], + "description": "Get a file content by its unique ID. The endpoint response return with a 'Content-Disposition: attachment' header that tells the browser to start downloading the file to user downloads directory.", + "responses": { + "200": { + "description": "File", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getFileDownload", + "group": "files", + "weight": 217, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "storage\/get-file-download.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file-download.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + }, + { + "name": "token", + "description": "File token for accessing this file.", + "required": false, + "type": "string", + "x-example": "<TOKEN>", + "default": "", + "in": "query" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/preview": { + "get": { + "summary": "Get file preview", + "operationId": "storageGetFilePreview", + "consumes": [], + "produces": [ + "image\/*" + ], + "tags": [ + "storage" + ], + "description": "Get a file preview image. Currently, this method supports preview for image files (jpg, png, and gif), other supported formats, like pdf, docs, slides, and spreadsheets, will return the file icon image. You can also pass query string arguments for cutting and resizing your preview image. Preview is supported only for image files smaller than 10MB.", + "responses": { + "200": { + "description": "Image", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getFilePreview", + "group": "files", + "weight": 216, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "storage\/get-file-preview.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file-preview.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File ID", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + }, + { + "name": "width", + "description": "Resize preview image width, Pass an integer between 0 to 4000.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0, + "in": "query" + }, + { + "name": "height", + "description": "Resize preview image height, Pass an integer between 0 to 4000.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0, + "in": "query" + }, + { + "name": "gravity", + "description": "Image crop gravity. Can be one of center,top-left,top,top-right,left,right,bottom-left,bottom,bottom-right", + "required": false, + "type": "string", + "x-example": "center", + "enum": [ + "center", + "top-left", + "top", + "top-right", + "left", + "right", + "bottom-left", + "bottom", + "bottom-right" + ], + "x-enum-name": "ImageGravity", + "x-enum-keys": [], + "default": "center", + "in": "query" + }, + { + "name": "quality", + "description": "Preview image quality. Pass an integer between 0 to 100. Defaults to keep existing image quality.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": -1, + "default": -1, + "in": "query" + }, + { + "name": "borderWidth", + "description": "Preview image border in pixels. Pass an integer between 0 to 100. Defaults to 0.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0, + "in": "query" + }, + { + "name": "borderColor", + "description": "Preview image border color. Use a valid HEX color, no # is needed for prefix.", + "required": false, + "type": "string", + "default": "", + "in": "query" + }, + { + "name": "borderRadius", + "description": "Preview image border radius in pixels. Pass an integer between 0 to 4000.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": 0, + "default": 0, + "in": "query" + }, + { + "name": "opacity", + "description": "Preview image opacity. Only works with images having an alpha channel (like png). Pass a number between 0 to 1.", + "required": false, + "type": "number", + "format": "float", + "x-example": 0, + "default": 1, + "in": "query" + }, + { + "name": "rotation", + "description": "Preview image rotation in degrees. Pass an integer between -360 and 360.", + "required": false, + "type": "integer", + "format": "int32", + "x-example": -360, + "default": 0, + "in": "query" + }, + { + "name": "background", + "description": "Preview image background color. Only works with transparent images (png). Use a valid HEX color, no # is needed for prefix.", + "required": false, + "type": "string", + "default": "", + "in": "query" + }, + { + "name": "output", + "description": "Output format type (jpeg, jpg, png, gif and webp).", + "required": false, + "type": "string", + "x-example": "jpg", + "enum": [ + "jpg", + "jpeg", + "png", + "webp", + "heic", + "avif", + "gif" + ], + "x-enum-name": "ImageFormat", + "x-enum-keys": [], + "default": "", + "in": "query" + }, + { + "name": "token", + "description": "File token for accessing this file.", + "required": false, + "type": "string", + "x-example": "<TOKEN>", + "default": "", + "in": "query" + } + ] + } + }, + "\/storage\/buckets\/{bucketId}\/files\/{fileId}\/view": { + "get": { + "summary": "Get file for view", + "operationId": "storageGetFileView", + "consumes": [], + "produces": [ + "*\/*" + ], + "tags": [ + "storage" + ], + "description": "Get a file content by its unique ID. This endpoint is similar to the download method but returns with no 'Content-Disposition: attachment' header.", + "responses": { + "200": { + "description": "File", + "schema": { + "type": "file" + } + } + }, + "x-appwrite": { + "method": "getFileView", + "group": "files", + "weight": 218, + "cookies": false, + "type": "location", + "deprecated": false, + "demo": "storage\/get-file-view.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/storage\/get-file-view.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "files.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File ID.", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + }, + { + "name": "token", + "description": "File token for accessing this file.", + "required": false, + "type": "string", + "x-example": "<TOKEN>", + "default": "", + "in": "query" + } + ] + } + }, + "\/teams": { + "get": { + "summary": "List teams", + "operationId": "teamsList", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Get a list of all the teams in which the current user is a member. You can use the parameters to filter your results.", + "responses": { + "200": { + "description": "Teams List", + "schema": { + "$ref": "#\/definitions\/teamList" + } + } + }, + "x-appwrite": { + "method": "list", + "group": "teams", + "weight": 225, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/list-teams.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, total, billingPlan", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create team", + "operationId": "teamsCreate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Create a new team. The user who creates the team will automatically be assigned as the owner of the team. Only the users with the owner role can invite new members, add new owners and delete or update the team.", + "responses": { + "201": { + "description": "Team", + "schema": { + "$ref": "#\/definitions\/team" + } + } + }, + "x-appwrite": { + "method": "create", + "group": "teams", + "weight": 224, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/create-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "teamId": { + "type": "string", + "description": "Team ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<TEAM_ID>" + }, + "name": { + "type": "string", + "description": "Team name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + }, + "roles": { + "type": "array", + "description": "Array of strings. Use this param to set the roles in the team for the user who created it. The default role is **owner**. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.", + "default": [ + "owner" + ], + "x-example": null, + "items": { + "type": "string" + } + } + }, + "required": [ + "teamId", + "name" + ] + } + } + ] + } + }, + "\/teams\/{teamId}": { + "get": { + "summary": "Get team", + "operationId": "teamsGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Get a team by its ID. All team members have read access for this resource.", + "responses": { + "200": { + "description": "Team", + "schema": { + "$ref": "#\/definitions\/team" + } + } + }, + "x-appwrite": { + "method": "get", + "group": "teams", + "weight": 226, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update name", + "operationId": "teamsUpdateName", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Update the team's name by its unique ID.", + "responses": { + "200": { + "description": "Team", + "schema": { + "$ref": "#\/definitions\/team" + } + } + }, + "x-appwrite": { + "method": "updateName", + "group": "teams", + "weight": 228, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-name.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-name.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "New team name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + } + }, + "required": [ + "name" + ] + } + } + ] + }, + "delete": { + "summary": "Delete team", + "operationId": "teamsDelete", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "teams" + ], + "description": "Delete a team using its ID. Only team members with the owner role can delete the team.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "teams", + "weight": 230, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/delete-team.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + } + ] + } + }, + "\/teams\/{teamId}\/memberships": { + "get": { + "summary": "List team memberships", + "operationId": "teamsListMemberships", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Use this endpoint to list a team's members using the team's ID. All team members have read access to this endpoint. Hide sensitive attributes from the response by toggling membership privacy in the Console.", + "responses": { + "200": { + "description": "Memberships List", + "schema": { + "$ref": "#\/definitions\/membershipList" + } + } + }, + "x-appwrite": { + "method": "listMemberships", + "group": "memberships", + "weight": 232, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/list-memberships.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/list-team-members.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create team membership", + "operationId": "teamsCreateMembership", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Invite a new member to join your team. Provide an ID for existing users, or invite unregistered users using an email or phone number. If initiated from a Client SDK, Appwrite will send an email or sms with a link to join the team to the invited user, and an account will be created for them if one doesn't exist. If initiated from a Server SDK, the new member will be added automatically to the team.\n\nYou only need to provide one of a user ID, email, or phone number. Appwrite will prioritize accepting the user ID > email > phone number if you provide more than one of these parameters.\n\nUse the `url` parameter to redirect the user from the invitation email to your app. After the user is redirected, use the [Update Team Membership Status](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/teams#updateMembershipStatus) endpoint to allow the user to accept the invitation to the team. \n\nPlease note that to avoid a [Redirect Attack](https:\/\/github.com\/OWASP\/CheatSheetSeries\/blob\/master\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.md) Appwrite will accept the only redirect URLs under the domains you have added as a platform on the Appwrite Console.\n", + "responses": { + "201": { + "description": "Membership", + "schema": { + "$ref": "#\/definitions\/membership" + } + } + }, + "x-appwrite": { + "method": "createMembership", + "group": "memberships", + "weight": 231, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/create-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/create-team-membership.md", + "rate-limit": 10, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "Email of the new team member.", + "default": "", + "x-example": "email@example.com" + }, + "userId": { + "type": "string", + "description": "ID of the user to be added to a team.", + "default": "", + "x-example": "<USER_ID>" + }, + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "default": "", + "x-example": "+12065550100" + }, + "roles": { + "type": "array", + "description": "Array of strings. Use this param to set the user roles in the team. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + }, + "url": { + "type": "string", + "description": "URL to redirect the user back to your app from the invitation email. This parameter is not required when an API key is supplied. Only URLs from hostnames in your project platform list are allowed. This requirement helps to prevent an [open redirect](https:\/\/cheatsheetseries.owasp.org\/cheatsheets\/Unvalidated_Redirects_and_Forwards_Cheat_Sheet.html) attack against your project API.", + "default": "", + "x-example": "https:\/\/example.com" + }, + "name": { + "type": "string", + "description": "Name of the new team member. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "roles" + ] + } + } + ] + } + }, + "\/teams\/{teamId}\/memberships\/{membershipId}": { + "get": { + "summary": "Get team membership", + "operationId": "teamsGetMembership", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Get a team member by the membership unique id. All team members have read access for this resource. Hide sensitive attributes from the response by toggling membership privacy in the Console.", + "responses": { + "200": { + "description": "Membership", + "schema": { + "$ref": "#\/definitions\/membership" + } + } + }, + "x-appwrite": { + "method": "getMembership", + "group": "memberships", + "weight": 233, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/get-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team-member.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "type": "string", + "x-example": "<MEMBERSHIP_ID>", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update membership", + "operationId": "teamsUpdateMembership", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Modify the roles of a team member. Only team members with the owner role have access to this endpoint. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions).\n", + "responses": { + "200": { + "description": "Membership", + "schema": { + "$ref": "#\/definitions\/membership" + } + } + }, + "x-appwrite": { + "method": "updateMembership", + "group": "memberships", + "weight": 234, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-membership.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "type": "string", + "x-example": "<MEMBERSHIP_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "roles": { + "type": "array", + "description": "An array of strings. Use this param to set the user's roles in the team. A role can be any string. Learn more about [roles and permissions](https:\/\/appwrite.io\/docs\/permissions). Maximum of 100 roles are allowed, each 32 characters long.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + } + }, + "required": [ + "roles" + ] + } + } + ] + }, + "delete": { + "summary": "Delete team membership", + "operationId": "teamsDeleteMembership", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "teams" + ], + "description": "This endpoint allows a user to leave a team or for a team owner to delete the membership of any other team member. You can also use this endpoint to delete a user membership even if it is not accepted.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteMembership", + "group": "memberships", + "weight": 236, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/delete-membership.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/delete-team-membership.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "type": "string", + "x-example": "<MEMBERSHIP_ID>", + "in": "path" + } + ] + } + }, + "\/teams\/{teamId}\/memberships\/{membershipId}\/status": { + "patch": { + "summary": "Update team membership status", + "operationId": "teamsUpdateMembershipStatus", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Use this endpoint to allow a user to accept an invitation to join a team after being redirected back to your app from the invitation email received by the user.\n\nIf the request is successful, a session for the user is automatically created.\n", + "responses": { + "200": { + "description": "Membership", + "schema": { + "$ref": "#\/definitions\/membership" + } + } + }, + "x-appwrite": { + "method": "updateMembershipStatus", + "group": "memberships", + "weight": 235, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-membership-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-membership-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "public", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "membershipId", + "description": "Membership ID.", + "required": true, + "type": "string", + "x-example": "<MEMBERSHIP_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID.", + "default": null, + "x-example": "<USER_ID>" + }, + "secret": { + "type": "string", + "description": "Secret key.", + "default": null, + "x-example": "<SECRET>" + } + }, + "required": [ + "userId", + "secret" + ] + } + } + ] + } + }, + "\/teams\/{teamId}\/prefs": { + "get": { + "summary": "Get team preferences", + "operationId": "teamsGetPrefs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Get the team's shared preferences by its unique ID. If a preference doesn't need to be shared by all team members, prefer storing them in [user preferences](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#getPrefs).", + "responses": { + "200": { + "description": "Preferences", + "schema": { + "$ref": "#\/definitions\/preferences" + } + } + }, + "x-appwrite": { + "method": "getPrefs", + "group": "teams", + "weight": 227, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/get-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/get-team-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.read", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update preferences", + "operationId": "teamsUpdatePrefs", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "teams" + ], + "description": "Update the team's preferences by its unique ID. The object you pass is stored as is and replaces any previous value. The maximum allowed prefs size is 64kB and throws an error if exceeded.", + "responses": { + "200": { + "description": "Preferences", + "schema": { + "$ref": "#\/definitions\/preferences" + } + } + }, + "x-appwrite": { + "method": "updatePrefs", + "group": "teams", + "weight": 229, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "teams\/update-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/teams\/update-team-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "teams.write", + "platforms": [ + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Session": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "teamId", + "description": "Team ID.", + "required": true, + "type": "string", + "x-example": "<TEAM_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "prefs": { + "type": "object", + "description": "Prefs key-value JSON object.", + "default": {}, + "x-example": "{}" + } + }, + "required": [ + "prefs" + ] + } + } + ] + } + }, + "\/tokens\/buckets\/{bucketId}\/files\/{fileId}": { + "get": { + "summary": "List tokens", + "operationId": "tokensList", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "tokens" + ], + "description": "List all the tokens created for a specific file or bucket. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Resource Tokens List", + "schema": { + "$ref": "#\/definitions\/resourceTokenList" + } + } + }, + "x-appwrite": { + "method": "list", + "group": "files", + "weight": 441, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterList all the tokens created for a specific file or bucket. You can use the query params to filter your results.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "tokens.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: expire", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create file token", + "operationId": "tokensCreateFileToken", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tokens" + ], + "description": "Create a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", + "responses": { + "201": { + "description": "ResourceToken", + "schema": { + "$ref": "#\/definitions\/resourceToken" + } + } + }, + "x-appwrite": { + "method": "createFileToken", + "group": "files", + "weight": 439, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/create-file-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterCreate a new token. A token is linked to a file. Token can be passed as a request URL search parameter.", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "tokens.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "bucketId", + "description": "Storage bucket unique ID. You can create a new storage bucket using the Storage service [server integration](https:\/\/appwrite.io\/docs\/server\/storage#createBucket).", + "required": true, + "type": "string", + "x-example": "<BUCKET_ID>", + "in": "path" + }, + { + "name": "fileId", + "description": "File unique ID.", + "required": true, + "type": "string", + "x-example": "<FILE_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "expire": { + "type": "string", + "description": "Token expiry date", + "default": null, + "x-example": null, + "x-nullable": true + } + } + } + } + ] + } + }, + "\/tokens\/{tokenId}": { + "get": { + "summary": "Get token", + "operationId": "tokensGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "tokens" + ], + "description": "Get a token by its unique ID.", + "responses": { + "200": { + "description": "ResourceToken", + "schema": { + "$ref": "#\/definitions\/resourceToken" + } + } + }, + "x-appwrite": { + "method": "get", + "group": "tokens", + "weight": 440, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterGet a token by its unique ID.", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "tokens.read", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "type": "string", + "x-example": "<TOKEN_ID>", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update token", + "operationId": "tokensUpdate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "tokens" + ], + "description": "Update a token by its unique ID. Use this endpoint to update a token's expiry date.", + "responses": { + "200": { + "description": "ResourceToken", + "schema": { + "$ref": "#\/definitions\/resourceToken" + } + } + }, + "x-appwrite": { + "method": "update", + "group": "tokens", + "weight": 442, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/update.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterUpdate a token by its unique ID. Use this endpoint to update a token's expiry date.", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "tokens.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token unique ID.", + "required": true, + "type": "string", + "x-example": "<TOKEN_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "expire": { + "type": "string", + "description": "File token expiry date", + "default": null, + "x-example": null, + "x-nullable": true + } + } + } + } + ] + }, + "delete": { + "summary": "Delete token", + "operationId": "tokensDelete", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "tokens" + ], + "description": "Delete a token by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "tokens", + "weight": 443, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "tokens\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/masterDelete a token by its unique ID.", + "rate-limit": 60, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "tokens.write", + "platforms": [ + "console", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "tokenId", + "description": "Token ID.", + "required": true, + "type": "string", + "x-example": "<TOKEN_ID>", + "in": "path" + } + ] + } + }, + "\/users": { + "get": { + "summary": "List users", + "operationId": "usersList", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get a list of all the project's users. You can use the query params to filter your results.", + "responses": { + "200": { + "description": "Users List", + "schema": { + "$ref": "#\/definitions\/userList" + } + } + }, + "x-appwrite": { + "method": "list", + "group": "users", + "weight": 247, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-users.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, email, phone, status, passwordUpdate, registration, emailVerification, phoneVerification, labels", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + }, + "post": { + "summary": "Create user", + "operationId": "usersCreate", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Create a new user.", + "responses": { + "201": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "create", + "group": "users", + "weight": 238, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "phone": { + "type": "string", + "description": "Phone number. Format this number with a leading '+' and a country code, e.g., +16175551212.", + "default": null, + "x-example": "+12065550100" + }, + "password": { + "type": "string", + "description": "Plain text user password. Must be at least 8 chars.", + "default": "", + "x-example": null + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "userId" + ] + } + } + ] + } + }, + "\/users\/argon2": { + "post": { + "summary": "Create user with Argon2 password", + "operationId": "usersCreateArgon2User", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [Argon2](https:\/\/en.wikipedia.org\/wiki\/Argon2) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "createArgon2User", + "group": "users", + "weight": 241, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-argon2user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-argon2-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using Argon2.", + "default": null, + "x-example": "password" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + ] + } + }, + "\/users\/bcrypt": { + "post": { + "summary": "Create user with bcrypt password", + "operationId": "usersCreateBcryptUser", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [Bcrypt](https:\/\/en.wikipedia.org\/wiki\/Bcrypt) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "createBcryptUser", + "group": "users", + "weight": 239, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-bcrypt-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-bcrypt-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using Bcrypt.", + "default": null, + "x-example": "password" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + ] + } + }, + "\/users\/identities": { + "get": { + "summary": "List identities", + "operationId": "usersListIdentities", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get identities for all users.", + "responses": { + "200": { + "description": "Identities List", + "schema": { + "$ref": "#\/definitions\/identityList" + } + } + }, + "x-appwrite": { + "method": "listIdentities", + "group": "identities", + "weight": 255, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-identities.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-identities.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, provider, providerUid, providerEmail, providerAccessTokenExpiry", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + } + }, + "\/users\/identities\/{identityId}": { + "delete": { + "summary": "Delete identity", + "operationId": "usersDeleteIdentity", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "users" + ], + "description": "Delete an identity by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteIdentity", + "group": "identities", + "weight": 278, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-identity.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-identity.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "identityId", + "description": "Identity ID.", + "required": true, + "type": "string", + "x-example": "<IDENTITY_ID>", + "in": "path" + } + ] + } + }, + "\/users\/md5": { + "post": { + "summary": "Create user with MD5 password", + "operationId": "usersCreateMD5User", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [MD5](https:\/\/en.wikipedia.org\/wiki\/MD5) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "createMD5User", + "group": "users", + "weight": 240, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-m-d5user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-md5-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using MD5.", + "default": null, + "x-example": "password" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + ] + } + }, + "\/users\/phpass": { + "post": { + "summary": "Create user with PHPass password", + "operationId": "usersCreatePHPassUser", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [PHPass](https:\/\/www.openwall.com\/phpass\/) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "createPHPassUser", + "group": "users", + "weight": 243, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-p-h-pass-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-phpass-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or pass the string `ID.unique()`to auto generate it. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using PHPass.", + "default": null, + "x-example": "password" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + ] + } + }, + "\/users\/scrypt": { + "post": { + "summary": "Create user with Scrypt password", + "operationId": "usersCreateScryptUser", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [Scrypt](https:\/\/github.com\/Tarsnap\/scrypt) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "createScryptUser", + "group": "users", + "weight": 244, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-scrypt-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-scrypt-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using Scrypt.", + "default": null, + "x-example": "password" + }, + "passwordSalt": { + "type": "string", + "description": "Optional salt used to hash password.", + "default": null, + "x-example": "<PASSWORD_SALT>" + }, + "passwordCpu": { + "type": "integer", + "description": "Optional CPU cost used to hash password.", + "default": null, + "x-example": null + }, + "passwordMemory": { + "type": "integer", + "description": "Optional memory cost used to hash password.", + "default": null, + "x-example": null + }, + "passwordParallel": { + "type": "integer", + "description": "Optional parallelization cost used to hash password.", + "default": null, + "x-example": null + }, + "passwordLength": { + "type": "integer", + "description": "Optional hash length used to hash password.", + "default": null, + "x-example": null + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password", + "passwordSalt", + "passwordCpu", + "passwordMemory", + "passwordParallel", + "passwordLength" + ] + } + } + ] + } + }, + "\/users\/scrypt-modified": { + "post": { + "summary": "Create user with Scrypt modified password", + "operationId": "usersCreateScryptModifiedUser", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [Scrypt Modified](https:\/\/gist.github.com\/Meldiron\/eecf84a0225eccb5a378d45bb27462cc) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "createScryptModifiedUser", + "group": "users", + "weight": 245, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-scrypt-modified-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-scrypt-modified-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using Scrypt Modified.", + "default": null, + "x-example": "password" + }, + "passwordSalt": { + "type": "string", + "description": "Salt used to hash password.", + "default": null, + "x-example": "<PASSWORD_SALT>" + }, + "passwordSaltSeparator": { + "type": "string", + "description": "Salt separator used to hash password.", + "default": null, + "x-example": "<PASSWORD_SALT_SEPARATOR>" + }, + "passwordSignerKey": { + "type": "string", + "description": "Signer key used to hash password.", + "default": null, + "x-example": "<PASSWORD_SIGNER_KEY>" + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password", + "passwordSalt", + "passwordSaltSeparator", + "passwordSignerKey" + ] + } + } + ] + } + }, + "\/users\/sha": { + "post": { + "summary": "Create user with SHA password", + "operationId": "usersCreateSHAUser", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Create a new user. Password provided must be hashed with the [SHA](https:\/\/en.wikipedia.org\/wiki\/Secure_Hash_Algorithm) algorithm. Use the [POST \/users](https:\/\/appwrite.io\/docs\/server\/users#usersCreate) endpoint to create users with a plain text password.", + "responses": { + "201": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "createSHAUser", + "group": "users", + "weight": 242, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-s-h-a-user.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-sha-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "userId": { + "type": "string", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<USER_ID>" + }, + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + }, + "password": { + "type": "string", + "description": "User password hashed using SHA.", + "default": null, + "x-example": "password" + }, + "passwordVersion": { + "type": "string", + "description": "Optional SHA version used to hash password. Allowed values are: 'sha1', 'sha224', 'sha256', 'sha384', 'sha512\/224', 'sha512\/256', 'sha512', 'sha3-224', 'sha3-256', 'sha3-384', 'sha3-512'", + "default": "", + "x-example": "sha1", + "enum": [ + "sha1", + "sha224", + "sha256", + "sha384", + "sha512\/224", + "sha512\/256", + "sha512", + "sha3-224", + "sha3-256", + "sha3-384", + "sha3-512" + ], + "x-enum-name": "PasswordHash", + "x-enum-keys": [] + }, + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "userId", + "email", + "password" + ] + } + } + ] + } + }, + "\/users\/{userId}": { + "get": { + "summary": "Get user", + "operationId": "usersGet", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get a user by its unique ID.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "get", + "group": "users", + "weight": 248, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/get.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-user.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete user", + "operationId": "usersDelete", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "users" + ], + "description": "Delete a user by its unique ID, thereby releasing it's ID. Since ID is released and can be reused, all user-related resources like documents or storage files should be deleted before user deletion. If you want to keep ID reserved, use the [updateStatus](https:\/\/appwrite.io\/docs\/server\/users#usersUpdateStatus) endpoint instead.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "delete", + "group": "users", + "weight": 276, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/email": { + "patch": { + "summary": "Update email", + "operationId": "usersUpdateEmail", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update the user email by its unique ID.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateEmail", + "group": "users", + "weight": 261, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-email.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-email.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "email": { + "type": "string", + "description": "User email.", + "default": null, + "x-example": "email@example.com" + } + }, + "required": [ + "email" + ] + } + } + ] + } + }, + "\/users\/{userId}\/jwts": { + "post": { + "summary": "Create user JWT", + "operationId": "usersCreateJWT", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Use this endpoint to create a JSON Web Token for user by its unique ID. You can use the resulting JWT to authenticate on behalf of the user. The JWT secret will become invalid if the session it uses gets deleted.", + "responses": { + "201": { + "description": "JWT", + "schema": { + "$ref": "#\/definitions\/jwt" + } + } + }, + "x-appwrite": { + "method": "createJWT", + "group": "sessions", + "weight": 279, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-j-w-t.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-user-jwt.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "sessionId": { + "type": "string", + "description": "Session ID. Use the string 'recent' to use the most recent session. Defaults to the most recent session.", + "default": "", + "x-example": "<SESSION_ID>" + }, + "duration": { + "type": "integer", + "description": "Time in seconds before JWT expires. Default duration is 900 seconds, and maximum is 3600 seconds.", + "default": 900, + "x-example": 0 + } + } + } + } + ] + } + }, + "\/users\/{userId}\/labels": { + "put": { + "summary": "Update user labels", + "operationId": "usersUpdateLabels", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update the user labels by its unique ID. \n\nLabels can be used to grant access to resources. While teams are a way for user's to share access to a resource, labels can be defined by the developer to grant access without an invitation. See the [Permissions docs](https:\/\/appwrite.io\/docs\/permissions) for more info.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateLabels", + "group": "users", + "weight": 257, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-labels.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-labels.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "labels": { + "type": "array", + "description": "Array of user labels. Replaces the previous labels. Maximum of 1000 labels are allowed, each up to 36 alphanumeric characters long.", + "default": null, + "x-example": null, + "items": { + "type": "string" + } + } + }, + "required": [ + "labels" + ] + } + } + ] + } + }, + "\/users\/{userId}\/logs": { + "get": { + "summary": "List user logs", + "operationId": "usersListLogs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get the user activity logs list by its unique ID.", + "responses": { + "200": { + "description": "Logs List", + "schema": { + "$ref": "#\/definitions\/logList" + } + } + }, + "x-appwrite": { + "method": "listLogs", + "group": "logs", + "weight": 253, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-logs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-user-logs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Only supported methods are limit and offset", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + } + }, + "\/users\/{userId}\/memberships": { + "get": { + "summary": "List user memberships", + "operationId": "usersListMemberships", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get the user membership list by its unique ID.", + "responses": { + "200": { + "description": "Memberships List", + "schema": { + "$ref": "#\/definitions\/membershipList" + } + } + }, + "x-appwrite": { + "method": "listMemberships", + "group": "memberships", + "weight": 252, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-memberships.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-user-memberships.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, teamId, invited, joined, confirm, roles", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + }, + { + "name": "search", + "description": "Search term to filter your list results. Max length: 256 chars.", + "required": false, + "type": "string", + "x-example": "<SEARCH>", + "default": "", + "in": "query" + } + ] + } + }, + "\/users\/{userId}\/mfa": { + "patch": { + "summary": "Update MFA", + "operationId": "usersUpdateMfa", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Enable or disable MFA on a user account.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateMfa", + "group": "users", + "weight": 266, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-mfa.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-mfa.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "mfa": { + "type": "boolean", + "description": "Enable or disable MFA.", + "default": null, + "x-example": false + } + }, + "required": [ + "mfa" + ] + } + } + ] + } + }, + "\/users\/{userId}\/mfa\/authenticators\/{type}": { + "delete": { + "summary": "Delete authenticator", + "operationId": "usersDeleteMfaAuthenticator", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "users" + ], + "description": "Delete an authenticator app.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteMfaAuthenticator", + "group": "mfa", + "weight": 271, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-mfa-authenticator.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-mfa-authenticator.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "type", + "description": "Type of authenticator.", + "required": true, + "type": "string", + "x-example": "totp", + "enum": [ + "totp" + ], + "x-enum-name": "AuthenticatorType", + "x-enum-keys": [], + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/mfa\/factors": { + "get": { + "summary": "List factors", + "operationId": "usersListMfaFactors", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "List the factors available on the account to be used as a MFA challange.", + "responses": { + "200": { + "description": "MFAFactors", + "schema": { + "$ref": "#\/definitions\/mfaFactors" + } + } + }, + "x-appwrite": { + "method": "listMfaFactors", + "group": "mfa", + "weight": 267, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-mfa-factors.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-mfa-factors.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/mfa\/recovery-codes": { + "get": { + "summary": "Get MFA recovery codes", + "operationId": "usersGetMfaRecoveryCodes", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get recovery codes that can be used as backup for MFA flow by User ID. Before getting codes, they must be generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "schema": { + "$ref": "#\/definitions\/mfaRecoveryCodes" + } + } + }, + "x-appwrite": { + "method": "getMfaRecoveryCodes", + "group": "mfa", + "weight": 268, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/get-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + }, + "put": { + "summary": "Update MFA recovery codes (regenerate)", + "operationId": "usersUpdateMfaRecoveryCodes", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Regenerate recovery codes that can be used as backup for MFA flow by User ID. Before regenerating codes, they must be first generated using [createMfaRecoveryCodes](\/docs\/references\/cloud\/client-web\/account#createMfaRecoveryCodes) method.", + "responses": { + "200": { + "description": "MFA Recovery Codes", + "schema": { + "$ref": "#\/definitions\/mfaRecoveryCodes" + } + } + }, + "x-appwrite": { + "method": "updateMfaRecoveryCodes", + "group": "mfa", + "weight": 270, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + }, + "patch": { + "summary": "Create MFA recovery codes", + "operationId": "usersCreateMfaRecoveryCodes", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Generate recovery codes used as backup for MFA flow for User ID. Recovery codes can be used as a MFA verification type in [createMfaChallenge](\/docs\/references\/cloud\/client-web\/account#createMfaChallenge) method by client SDK.", + "responses": { + "201": { + "description": "MFA Recovery Codes", + "schema": { + "$ref": "#\/definitions\/mfaRecoveryCodes" + } + } + }, + "x-appwrite": { + "method": "createMfaRecoveryCodes", + "group": "mfa", + "weight": 269, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-mfa-recovery-codes.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-mfa-recovery-codes.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/name": { + "patch": { + "summary": "Update name", + "operationId": "usersUpdateName", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update the user name by its unique ID.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateName", + "group": "users", + "weight": 259, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-name.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-name.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "User name. Max length: 128 chars.", + "default": null, + "x-example": "<NAME>" + } + }, + "required": [ + "name" + ] + } + } + ] + } + }, + "\/users\/{userId}\/password": { + "patch": { + "summary": "Update password", + "operationId": "usersUpdatePassword", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update the user password by its unique ID.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updatePassword", + "group": "users", + "weight": 260, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-password.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-password.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "password": { + "type": "string", + "description": "New user password. Must be at least 8 chars.", + "default": null, + "x-example": null + } + }, + "required": [ + "password" + ] + } + } + ] + } + }, + "\/users\/{userId}\/phone": { + "patch": { + "summary": "Update phone", + "operationId": "usersUpdatePhone", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update the user phone by its unique ID.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updatePhone", + "group": "users", + "weight": 262, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-phone.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-phone.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "number": { + "type": "string", + "description": "User phone number.", + "default": null, + "x-example": "+12065550100" + } + }, + "required": [ + "number" + ] + } + } + ] + } + }, + "\/users\/{userId}\/prefs": { + "get": { + "summary": "Get user preferences", + "operationId": "usersGetPrefs", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get the user preferences by its unique ID.", + "responses": { + "200": { + "description": "Preferences", + "schema": { + "$ref": "#\/definitions\/preferences" + } + } + }, + "x-appwrite": { + "method": "getPrefs", + "group": "users", + "weight": 249, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/get-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-user-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update user preferences", + "operationId": "usersUpdatePrefs", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update the user preferences by its unique ID. The object you pass is stored as is, and replaces any previous value. The maximum allowed prefs size is 64kB and throws error if exceeded.", + "responses": { + "200": { + "description": "Preferences", + "schema": { + "$ref": "#\/definitions\/preferences" + } + } + }, + "x-appwrite": { + "method": "updatePrefs", + "group": "users", + "weight": 264, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-prefs.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-prefs.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "prefs": { + "type": "object", + "description": "Prefs key-value JSON object.", + "default": {}, + "x-example": "{}" + } + }, + "required": [ + "prefs" + ] + } + } + ] + } + }, + "\/users\/{userId}\/sessions": { + "get": { + "summary": "List user sessions", + "operationId": "usersListSessions", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get the user sessions list by its unique ID.", + "responses": { + "200": { + "description": "Sessions List", + "schema": { + "$ref": "#\/definitions\/sessionList" + } + } + }, + "x-appwrite": { + "method": "listSessions", + "group": "sessions", + "weight": 251, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-user-sessions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.read", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + }, + "post": { + "summary": "Create session", + "operationId": "usersCreateSession", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Creates a session for a user. Returns an immediately usable session object.\n\nIf you want to generate a token for a custom authentication flow, use the [POST \/users\/{userId}\/tokens](https:\/\/appwrite.io\/docs\/server\/users#createToken) endpoint.", + "responses": { + "201": { + "description": "Session", + "schema": { + "$ref": "#\/definitions\/session" + } + } + }, + "x-appwrite": { + "method": "createSession", + "group": "sessions", + "weight": 272, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-session.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + }, + "delete": { + "summary": "Delete user sessions", + "operationId": "usersDeleteSessions", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "users" + ], + "description": "Delete all user's sessions by using the user's unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSessions", + "group": "sessions", + "weight": 275, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-sessions.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-user-sessions.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/sessions\/{sessionId}": { + "delete": { + "summary": "Delete user session", + "operationId": "usersDeleteSession", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "users" + ], + "description": "Delete a user sessions by its unique ID.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteSession", + "group": "sessions", + "weight": 274, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-session.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-user-session.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "sessionId", + "description": "Session ID.", + "required": true, + "type": "string", + "x-example": "<SESSION_ID>", + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/status": { + "patch": { + "summary": "Update user status", + "operationId": "usersUpdateStatus", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update the user status by its unique ID. Use this endpoint as an alternative to deleting a user if you want to keep user's ID reserved.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateStatus", + "group": "users", + "weight": 256, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-status.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-status.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "status": { + "type": "boolean", + "description": "User Status. To activate the user pass `true` and to block the user pass `false`.", + "default": null, + "x-example": false + } + }, + "required": [ + "status" + ] + } + } + ] + } + }, + "\/users\/{userId}\/targets": { + "get": { + "summary": "List user targets", + "operationId": "usersListTargets", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "List the messaging targets that are associated with a user.", + "responses": { + "200": { + "description": "Target list", + "schema": { + "$ref": "#\/definitions\/targetList" + } + } + }, + "x-appwrite": { + "method": "listTargets", + "group": "targets", + "weight": 254, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/list-targets.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/list-user-targets.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.read", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "queries", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, providerId, identifier, providerType", + "required": false, + "type": "array", + "collectionFormat": "multi", + "items": { + "type": "string" + }, + "default": [], + "in": "query" + } + ] + }, + "post": { + "summary": "Create user target", + "operationId": "usersCreateTarget", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Create a messaging target.", + "responses": { + "201": { + "description": "Target", + "schema": { + "$ref": "#\/definitions\/target" + } + } + }, + "x-appwrite": { + "method": "createTarget", + "group": "targets", + "weight": 246, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "targetId": { + "type": "string", + "description": "Target ID. Choose a custom ID or generate a random ID with `ID.unique()`. Valid chars are a-z, A-Z, 0-9, period, hyphen, and underscore. Can't start with a special char. Max length is 36 chars.", + "default": null, + "x-example": "<TARGET_ID>" + }, + "providerType": { + "type": "string", + "description": "The target provider type. Can be one of the following: `email`, `sms` or `push`.", + "default": null, + "x-example": "email", + "enum": [ + "email", + "sms", + "push" + ], + "x-enum-name": "MessagingProviderType", + "x-enum-keys": [] + }, + "identifier": { + "type": "string", + "description": "The target identifier (token, email, phone etc.)", + "default": null, + "x-example": "<IDENTIFIER>" + }, + "providerId": { + "type": "string", + "description": "Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.", + "default": "", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Target name. Max length: 128 chars. For example: My Awesome App Galaxy S23.", + "default": "", + "x-example": "<NAME>" + } + }, + "required": [ + "targetId", + "providerType", + "identifier" + ] + } + } + ] + } + }, + "\/users\/{userId}\/targets\/{targetId}": { + "get": { + "summary": "Get user target", + "operationId": "usersGetTarget", + "consumes": [], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Get a user's push notification target by ID.", + "responses": { + "200": { + "description": "Target", + "schema": { + "$ref": "#\/definitions\/target" + } + } + }, + "x-appwrite": { + "method": "getTarget", + "group": "targets", + "weight": 250, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/get-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/get-user-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.read", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "type": "string", + "x-example": "<TARGET_ID>", + "in": "path" + } + ] + }, + "patch": { + "summary": "Update user target", + "operationId": "usersUpdateTarget", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update a messaging target.", + "responses": { + "200": { + "description": "Target", + "schema": { + "$ref": "#\/definitions\/target" + } + } + }, + "x-appwrite": { + "method": "updateTarget", + "group": "targets", + "weight": 265, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "type": "string", + "x-example": "<TARGET_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "identifier": { + "type": "string", + "description": "The target identifier (token, email, phone etc.)", + "default": "", + "x-example": "<IDENTIFIER>" + }, + "providerId": { + "type": "string", + "description": "Provider ID. Message will be sent to this target from the specified provider ID. If no provider ID is set the first setup provider will be used.", + "default": "", + "x-example": "<PROVIDER_ID>" + }, + "name": { + "type": "string", + "description": "Target name. Max length: 128 chars. For example: My Awesome App Galaxy S23.", + "default": "", + "x-example": "<NAME>" + } + } + } + } + ] + }, + "delete": { + "summary": "Delete user target", + "operationId": "usersDeleteTarget", + "consumes": [ + "application\/json" + ], + "produces": [], + "tags": [ + "users" + ], + "description": "Delete a messaging target.", + "responses": { + "204": { + "description": "No content" + } + }, + "x-appwrite": { + "method": "deleteTarget", + "group": "targets", + "weight": 277, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/delete-target.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/delete-target.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "targets.write", + "platforms": [ + "server", + "console" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "targetId", + "description": "Target ID.", + "required": true, + "type": "string", + "x-example": "<TARGET_ID>", + "in": "path" + } + ] + } + }, + "\/users\/{userId}\/tokens": { + "post": { + "summary": "Create token", + "operationId": "usersCreateToken", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Returns a token with a secret key for creating a session. Use the user ID and secret and submit a request to the [PUT \/account\/sessions\/token](https:\/\/appwrite.io\/docs\/references\/cloud\/client-web\/account#createSession) endpoint to complete the login process.\n", + "responses": { + "201": { + "description": "Token", + "schema": { + "$ref": "#\/definitions\/token" + } + } + }, + "x-appwrite": { + "method": "createToken", + "group": "sessions", + "weight": 273, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/create-token.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/create-token.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "length": { + "type": "integer", + "description": "Token length in characters. The default length is 6 characters", + "default": 6, + "x-example": 4 + }, + "expire": { + "type": "integer", + "description": "Token expiration period in seconds. The default expiration is 15 minutes.", + "default": 900, + "x-example": 60 + } + } + } + } + ] + } + }, + "\/users\/{userId}\/verification": { + "patch": { + "summary": "Update email verification", + "operationId": "usersUpdateEmailVerification", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update the user email verification status by its unique ID.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updateEmailVerification", + "group": "users", + "weight": 263, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-email-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-email-verification.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "emailVerification": { + "type": "boolean", + "description": "User email verification status.", + "default": null, + "x-example": false + } + }, + "required": [ + "emailVerification" + ] + } + } + ] + } + }, + "\/users\/{userId}\/verification\/phone": { + "patch": { + "summary": "Update phone verification", + "operationId": "usersUpdatePhoneVerification", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "users" + ], + "description": "Update the user phone verification status by its unique ID.", + "responses": { + "200": { + "description": "User", + "schema": { + "$ref": "#\/definitions\/user" + } + } + }, + "x-appwrite": { + "method": "updatePhoneVerification", + "group": "users", + "weight": 258, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "users\/update-phone-verification.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/users\/update-user-phone-verification.md", + "rate-limit": 0, + "rate-time": 3600, + "rate-key": "url:{url},ip:{ip}", + "scope": "users.write", + "platforms": [ + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [] + } + ], + "parameters": [ + { + "name": "userId", + "description": "User ID.", + "required": true, + "type": "string", + "x-example": "<USER_ID>", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "phoneVerification": { + "type": "boolean", + "description": "User phone verification status.", + "default": null, + "x-example": false + } + }, + "required": [ + "phoneVerification" + ] + } + } + ] + } + } + }, + "tags": [ + { + "name": "account", + "description": "The Account service allows you to authenticate and manage a user account." + }, + { + "name": "avatars", + "description": "The Avatars service aims to help you complete everyday tasks related to your app image, icons, and avatars." + }, + { + "name": "databases", + "description": "The Databases service allows you to create structured collections of documents, query and filter lists of documents" + }, + { + "name": "locale", + "description": "The Locale service allows you to customize your app based on your users' location." + }, + { + "name": "health", + "description": "The Health service allows you to both validate and monitor your Appwrite server's health." + }, + { + "name": "projects", + "description": "The Project service allows you to manage all the projects in your Appwrite server." + }, + { + "name": "project", + "description": "The Project service allows you to manage all the projects in your Appwrite server." + }, + { + "name": "storage", + "description": "The Storage service allows you to manage your project files." + }, + { + "name": "teams", + "description": "The Teams service allows you to group users of your project and to enable them to share read and write access to your project resources" + }, + { + "name": "users", + "description": "The Users service allows you to manage your project users." + }, + { + "name": "sites", + "description": "The Sites Service allows you view, create and manage your web applications." + }, + { + "name": "functions", + "description": "The Functions Service allows you view, create and manage your Cloud Functions." + }, + { + "name": "proxy", + "description": "The Proxy Service allows you to configure actions for your domains beyond DNS configuration." + }, + { + "name": "graphql", + "description": "The GraphQL API allows you to query and mutate your Appwrite server using GraphQL." + }, + { + "name": "console", + "description": "The Console service allows you to interact with console relevant informations." + }, + { + "name": "migrations", + "description": "The Migrations service allows you to migrate third-party data to your Appwrite project." + }, + { + "name": "messaging", + "description": "The Messaging service allows you to send messages to any provider type (SMTP, push notification, SMS, etc.)." + } + ], + "definitions": { + "any": { + "description": "Any", + "type": "object", + "additionalProperties": true + }, + "documentList": { + "description": "Documents List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of documents documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "documents": { + "type": "array", + "description": "List of documents.", + "items": { + "type": "object", + "$ref": "#\/definitions\/document" + }, + "x-example": "" + } + }, + "required": [ + "total", + "documents" + ] + }, + "collectionList": { + "description": "Collections List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of collections documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "collections": { + "type": "array", + "description": "List of collections.", + "items": { + "type": "object", + "$ref": "#\/definitions\/collection" + }, + "x-example": "" + } + }, + "required": [ + "total", + "collections" + ] + }, + "databaseList": { + "description": "Databases List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of databases documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "databases": { + "type": "array", + "description": "List of databases.", + "items": { + "type": "object", + "$ref": "#\/definitions\/database" + }, + "x-example": "" + } + }, + "required": [ + "total", + "databases" + ] + }, + "indexList": { + "description": "Indexes List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of indexes documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "indexes": { + "type": "array", + "description": "List of indexes.", + "items": { + "type": "object", + "$ref": "#\/definitions\/index" + }, + "x-example": "" + } + }, + "required": [ + "total", + "indexes" + ] + }, + "userList": { + "description": "Users List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of users documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "users": { + "type": "array", + "description": "List of users.", + "items": { + "type": "object", + "$ref": "#\/definitions\/user" + }, + "x-example": "" + } + }, + "required": [ + "total", + "users" + ] + }, + "sessionList": { + "description": "Sessions List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of sessions documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "sessions": { + "type": "array", + "description": "List of sessions.", + "items": { + "type": "object", + "$ref": "#\/definitions\/session" + }, + "x-example": "" + } + }, + "required": [ + "total", + "sessions" + ] + }, + "identityList": { + "description": "Identities List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of identities documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "identities": { + "type": "array", + "description": "List of identities.", + "items": { + "type": "object", + "$ref": "#\/definitions\/identity" + }, + "x-example": "" + } + }, + "required": [ + "total", + "identities" + ] + }, + "logList": { + "description": "Logs List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of logs documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "logs": { + "type": "array", + "description": "List of logs.", + "items": { + "type": "object", + "$ref": "#\/definitions\/log" + }, + "x-example": "" + } + }, + "required": [ + "total", + "logs" + ] + }, + "fileList": { + "description": "Files List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of files documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "files": { + "type": "array", + "description": "List of files.", + "items": { + "type": "object", + "$ref": "#\/definitions\/file" + }, + "x-example": "" + } + }, + "required": [ + "total", + "files" + ] + }, + "bucketList": { + "description": "Buckets List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of buckets documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "buckets": { + "type": "array", + "description": "List of buckets.", + "items": { + "type": "object", + "$ref": "#\/definitions\/bucket" + }, + "x-example": "" + } + }, + "required": [ + "total", + "buckets" + ] + }, + "resourceTokenList": { + "description": "Resource Tokens List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of tokens documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "tokens": { + "type": "array", + "description": "List of tokens.", + "items": { + "type": "object", + "$ref": "#\/definitions\/resourceToken" + }, + "x-example": "" + } + }, + "required": [ + "total", + "tokens" + ] + }, + "teamList": { + "description": "Teams List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of teams documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "teams": { + "type": "array", + "description": "List of teams.", + "items": { + "type": "object", + "$ref": "#\/definitions\/team" + }, + "x-example": "" + } + }, + "required": [ + "total", + "teams" + ] + }, + "membershipList": { + "description": "Memberships List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of memberships documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "memberships": { + "type": "array", + "description": "List of memberships.", + "items": { + "type": "object", + "$ref": "#\/definitions\/membership" + }, + "x-example": "" + } + }, + "required": [ + "total", + "memberships" + ] + }, + "siteList": { + "description": "Sites List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of sites documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "sites": { + "type": "array", + "description": "List of sites.", + "items": { + "type": "object", + "$ref": "#\/definitions\/site" + }, + "x-example": "" + } + }, + "required": [ + "total", + "sites" + ] + }, + "functionList": { + "description": "Functions List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of functions documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "functions": { + "type": "array", + "description": "List of functions.", + "items": { + "type": "object", + "$ref": "#\/definitions\/function" + }, + "x-example": "" + } + }, + "required": [ + "total", + "functions" + ] + }, + "frameworkList": { + "description": "Frameworks List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of frameworks documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "frameworks": { + "type": "array", + "description": "List of frameworks.", + "items": { + "type": "object", + "$ref": "#\/definitions\/framework" + }, + "x-example": "" + } + }, + "required": [ + "total", + "frameworks" + ] + }, + "runtimeList": { + "description": "Runtimes List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of runtimes documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "runtimes": { + "type": "array", + "description": "List of runtimes.", + "items": { + "type": "object", + "$ref": "#\/definitions\/runtime" + }, + "x-example": "" + } + }, + "required": [ + "total", + "runtimes" + ] + }, + "deploymentList": { + "description": "Deployments List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of deployments documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "deployments": { + "type": "array", + "description": "List of deployments.", + "items": { + "type": "object", + "$ref": "#\/definitions\/deployment" + }, + "x-example": "" + } + }, + "required": [ + "total", + "deployments" + ] + }, + "executionList": { + "description": "Executions List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of executions documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "executions": { + "type": "array", + "description": "List of executions.", + "items": { + "type": "object", + "$ref": "#\/definitions\/execution" + }, + "x-example": "" + } + }, + "required": [ + "total", + "executions" + ] + }, + "countryList": { + "description": "Countries List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of countries documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "countries": { + "type": "array", + "description": "List of countries.", + "items": { + "type": "object", + "$ref": "#\/definitions\/country" + }, + "x-example": "" + } + }, + "required": [ + "total", + "countries" + ] + }, + "continentList": { + "description": "Continents List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of continents documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "continents": { + "type": "array", + "description": "List of continents.", + "items": { + "type": "object", + "$ref": "#\/definitions\/continent" + }, + "x-example": "" + } + }, + "required": [ + "total", + "continents" + ] + }, + "languageList": { + "description": "Languages List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of languages documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "languages": { + "type": "array", + "description": "List of languages.", + "items": { + "type": "object", + "$ref": "#\/definitions\/language" + }, + "x-example": "" + } + }, + "required": [ + "total", + "languages" + ] + }, + "currencyList": { + "description": "Currencies List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of currencies documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "currencies": { + "type": "array", + "description": "List of currencies.", + "items": { + "type": "object", + "$ref": "#\/definitions\/currency" + }, + "x-example": "" + } + }, + "required": [ + "total", + "currencies" + ] + }, + "phoneList": { + "description": "Phones List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of phones documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "phones": { + "type": "array", + "description": "List of phones.", + "items": { + "type": "object", + "$ref": "#\/definitions\/phone" + }, + "x-example": "" + } + }, + "required": [ + "total", + "phones" + ] + }, + "variableList": { + "description": "Variables List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of variables documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "variables": { + "type": "array", + "description": "List of variables.", + "items": { + "type": "object", + "$ref": "#\/definitions\/variable" + }, + "x-example": "" + } + }, + "required": [ + "total", + "variables" + ] + }, + "localeCodeList": { + "description": "Locale codes list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of localeCodes documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "localeCodes": { + "type": "array", + "description": "List of localeCodes.", + "items": { + "type": "object", + "$ref": "#\/definitions\/localeCode" + }, + "x-example": "" + } + }, + "required": [ + "total", + "localeCodes" + ] + }, + "providerList": { + "description": "Provider list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of providers documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "providers": { + "type": "array", + "description": "List of providers.", + "items": { + "type": "object", + "$ref": "#\/definitions\/provider" + }, + "x-example": "" + } + }, + "required": [ + "total", + "providers" + ] + }, + "messageList": { + "description": "Message list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of messages documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "messages": { + "type": "array", + "description": "List of messages.", + "items": { + "type": "object", + "$ref": "#\/definitions\/message" + }, + "x-example": "" + } + }, + "required": [ + "total", + "messages" + ] + }, + "topicList": { + "description": "Topic list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of topics documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "topics": { + "type": "array", + "description": "List of topics.", + "items": { + "type": "object", + "$ref": "#\/definitions\/topic" + }, + "x-example": "" + } + }, + "required": [ + "total", + "topics" + ] + }, + "subscriberList": { + "description": "Subscriber list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of subscribers documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "subscribers": { + "type": "array", + "description": "List of subscribers.", + "items": { + "type": "object", + "$ref": "#\/definitions\/subscriber" + }, + "x-example": "" + } + }, + "required": [ + "total", + "subscribers" + ] + }, + "targetList": { + "description": "Target list", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of targets documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "targets": { + "type": "array", + "description": "List of targets.", + "items": { + "type": "object", + "$ref": "#\/definitions\/target" + }, + "x-example": "" + } + }, + "required": [ + "total", + "targets" + ] + }, + "specificationList": { + "description": "Specifications List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of specifications documents that matched your query.", + "x-example": 5, + "format": "int32" + }, + "specifications": { + "type": "array", + "description": "List of specifications.", + "items": { + "type": "object", + "$ref": "#\/definitions\/specification" + }, + "x-example": "" + } + }, + "required": [ + "total", + "specifications" + ] + }, + "database": { + "description": "Database", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Database ID.", + "x-example": "5e5ea5c16897e" + }, + "name": { + "type": "string", + "description": "Database name.", + "x-example": "My Database" + }, + "$createdAt": { + "type": "string", + "description": "Database creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Database update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "enabled": { + "type": "boolean", + "description": "If database is enabled. Can be 'enabled' or 'disabled'. When disabled, the database is inaccessible to users, but remains accessible to Server SDKs using API keys.", + "x-example": false + } + }, + "required": [ + "$id", + "name", + "$createdAt", + "$updatedAt", + "enabled" + ] + }, + "collection": { + "description": "Collection", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Collection ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Collection creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Collection update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Collection permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + }, + "databaseId": { + "type": "string", + "description": "Database ID.", + "x-example": "5e5ea5c16897e" + }, + "name": { + "type": "string", + "description": "Collection name.", + "x-example": "My Collection" + }, + "enabled": { + "type": "boolean", + "description": "Collection enabled. Can be 'enabled' or 'disabled'. When disabled, the collection is inaccessible to users, but remains accessible to Server SDKs using API keys.", + "x-example": false + }, + "documentSecurity": { + "type": "boolean", + "description": "Whether document-level permissions are enabled. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": true + }, + "attributes": { + "type": "array", + "description": "Collection attributes.", + "items": { + "x-anyOf": [ + { + "$ref": "#\/definitions\/attributeBoolean" + }, + { + "$ref": "#\/definitions\/attributeInteger" + }, + { + "$ref": "#\/definitions\/attributeFloat" + }, + { + "$ref": "#\/definitions\/attributeEmail" + }, + { + "$ref": "#\/definitions\/attributeEnum" + }, + { + "$ref": "#\/definitions\/attributeUrl" + }, + { + "$ref": "#\/definitions\/attributeIp" + }, + { + "$ref": "#\/definitions\/attributeDatetime" + }, + { + "$ref": "#\/definitions\/attributeRelationship" + }, + { + "$ref": "#\/definitions\/attributeString" + } + ] + }, + "x-example": {} + }, + "indexes": { + "type": "array", + "description": "Collection indexes.", + "items": { + "type": "object", + "$ref": "#\/definitions\/index" + }, + "x-example": {} + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "$permissions", + "databaseId", + "name", + "enabled", + "documentSecurity", + "attributes", + "indexes" + ] + }, + "attributeList": { + "description": "Attributes List", + "type": "object", + "properties": { + "total": { + "type": "integer", + "description": "Total number of attributes in the given collection.", + "x-example": 5, + "format": "int32" + }, + "attributes": { + "type": "array", + "description": "List of attributes.", + "items": { + "x-anyOf": [ + { + "$ref": "#\/definitions\/attributeBoolean" + }, + { + "$ref": "#\/definitions\/attributeInteger" + }, + { + "$ref": "#\/definitions\/attributeFloat" + }, + { + "$ref": "#\/definitions\/attributeEmail" + }, + { + "$ref": "#\/definitions\/attributeEnum" + }, + { + "$ref": "#\/definitions\/attributeUrl" + }, + { + "$ref": "#\/definitions\/attributeIp" + }, + { + "$ref": "#\/definitions\/attributeDatetime" + }, + { + "$ref": "#\/definitions\/attributeRelationship" + }, + { + "$ref": "#\/definitions\/attributeString" + } + ] + }, + "x-example": "" + } + }, + "required": [ + "total", + "attributes" + ] + }, + "attributeString": { + "description": "AttributeString", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "fullName" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "size": { + "type": "integer", + "description": "Attribute size.", + "x-example": 128, + "format": "int32" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "default", + "x-nullable": true + }, + "encrypt": { + "type": "boolean", + "description": "Defines whether this attribute is encrypted or not.", + "x-example": false, + "x-nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "size" + ] + }, + "attributeInteger": { + "description": "AttributeInteger", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "count" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "integer" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "min": { + "type": "integer", + "description": "Minimum value to enforce for new documents.", + "x-example": 1, + "format": "int32", + "x-nullable": true + }, + "max": { + "type": "integer", + "description": "Maximum value to enforce for new documents.", + "x-example": 10, + "format": "int32", + "x-nullable": true + }, + "default": { + "type": "integer", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": 10, + "format": "int32", + "x-nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt" + ] + }, + "attributeFloat": { + "description": "AttributeFloat", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "percentageCompleted" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "double" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "min": { + "type": "number", + "description": "Minimum value to enforce for new documents.", + "x-example": 1.5, + "format": "double", + "x-nullable": true + }, + "max": { + "type": "number", + "description": "Maximum value to enforce for new documents.", + "x-example": 10.5, + "format": "double", + "x-nullable": true + }, + "default": { + "type": "number", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": 2.5, + "format": "double", + "x-nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt" + ] + }, + "attributeBoolean": { + "description": "AttributeBoolean", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "isEnabled" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "boolean" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "default": { + "type": "boolean", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": false, + "x-nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt" + ] + }, + "attributeEmail": { + "description": "AttributeEmail", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "userEmail" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "format": { + "type": "string", + "description": "String format.", + "x-example": "email" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "default@example.com", + "x-nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "format" + ] + }, + "attributeEnum": { + "description": "AttributeEnum", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "status" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "elements": { + "type": "array", + "description": "Array of elements in enumerated type.", + "items": { + "type": "string" + }, + "x-example": "element" + }, + "format": { + "type": "string", + "description": "String format.", + "x-example": "enum" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "element", + "x-nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "elements", + "format" + ] + }, + "attributeIp": { + "description": "AttributeIP", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "ipAddress" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "format": { + "type": "string", + "description": "String format.", + "x-example": "ip" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "192.0.2.0", + "x-nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "format" + ] + }, + "attributeUrl": { + "description": "AttributeURL", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "githubUrl" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "format": { + "type": "string", + "description": "String format.", + "x-example": "url" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", + "x-example": "http:\/\/example.com", + "x-nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "format" + ] + }, + "attributeDatetime": { + "description": "AttributeDatetime", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "birthDay" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "datetime" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "format": { + "type": "string", + "description": "ISO 8601 format.", + "x-example": "datetime" + }, + "default": { + "type": "string", + "description": "Default value for attribute when not provided. Only null is optional", + "x-example": "2020-10-15T06:38:00.000+00:00", + "x-nullable": true + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "format" + ] + }, + "attributeRelationship": { + "description": "AttributeRelationship", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Attribute Key.", + "x-example": "fullName" + }, + "type": { + "type": "string", + "description": "Attribute type.", + "x-example": "string" + }, + "status": { + "type": "string", + "description": "Attribute status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an attribute.", + "x-example": "string" + }, + "required": { + "type": "boolean", + "description": "Is attribute required?", + "x-example": true + }, + "array": { + "type": "boolean", + "description": "Is attribute an array?", + "x-example": false, + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Attribute creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Attribute update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "relatedCollection": { + "type": "string", + "description": "The ID of the related collection.", + "x-example": "collection" + }, + "relationType": { + "type": "string", + "description": "The type of the relationship.", + "x-example": "oneToOne|oneToMany|manyToOne|manyToMany" + }, + "twoWay": { + "type": "boolean", + "description": "Is the relationship two-way?", + "x-example": false + }, + "twoWayKey": { + "type": "string", + "description": "The key of the two-way relationship.", + "x-example": "string" + }, + "onDelete": { + "type": "string", + "description": "How deleting the parent document will propagate to child documents.", + "x-example": "restrict|cascade|setNull" + }, + "side": { + "type": "string", + "description": "Whether this is the parent or child side of the relationship", + "x-example": "parent|child" + } + }, + "required": [ + "key", + "type", + "status", + "error", + "required", + "$createdAt", + "$updatedAt", + "relatedCollection", + "relationType", + "twoWay", + "twoWayKey", + "onDelete", + "side" + ] + }, + "index": { + "description": "Index", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Index Key.", + "x-example": "index1" + }, + "type": { + "type": "string", + "description": "Index type.", + "x-example": "primary" + }, + "status": { + "type": "string", + "description": "Index status. Possible values: `available`, `processing`, `deleting`, `stuck`, or `failed`", + "x-example": "available" + }, + "error": { + "type": "string", + "description": "Error message. Displays error generated on failure of creating or deleting an index.", + "x-example": "string" + }, + "attributes": { + "type": "array", + "description": "Index attributes.", + "items": { + "type": "string" + }, + "x-example": [] + }, + "lengths": { + "type": "array", + "description": "Index attributes length.", + "items": { + "type": "integer", + "format": "int32" + }, + "x-example": [] + }, + "orders": { + "type": "array", + "description": "Index orders.", + "items": { + "type": "string" + }, + "x-example": [], + "x-nullable": true + }, + "$createdAt": { + "type": "string", + "description": "Index creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Index update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "key", + "type", + "status", + "error", + "attributes", + "lengths", + "$createdAt", + "$updatedAt" + ] + }, + "document": { + "description": "Document", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Document ID.", + "x-example": "5e5ea5c16897e" + }, + "$sequence": { + "type": "integer", + "description": "Document automatically incrementing ID.", + "x-example": 1, + "format": "int32" + }, + "$collectionId": { + "type": "string", + "description": "Collection ID.", + "x-example": "5e5ea5c15117e" + }, + "$databaseId": { + "type": "string", + "description": "Database ID.", + "x-example": "5e5ea5c15117e" + }, + "$createdAt": { + "type": "string", + "description": "Document creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Document update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Document permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + } + }, + "additionalProperties": true, + "required": [ + "$id", + "$sequence", + "$collectionId", + "$databaseId", + "$createdAt", + "$updatedAt", + "$permissions" + ] + }, + "log": { + "description": "Log", + "type": "object", + "properties": { + "event": { + "type": "string", + "description": "Event name.", + "x-example": "account.sessions.create" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "610fc2f985ee0" + }, + "userEmail": { + "type": "string", + "description": "User Email.", + "x-example": "john@appwrite.io" + }, + "userName": { + "type": "string", + "description": "User Name.", + "x-example": "John Doe" + }, + "mode": { + "type": "string", + "description": "API mode when event triggered.", + "x-example": "admin" + }, + "ip": { + "type": "string", + "description": "IP session in use when the session was created.", + "x-example": "127.0.0.1" + }, + "time": { + "type": "string", + "description": "Log creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "osCode": { + "type": "string", + "description": "Operating system code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/os.json).", + "x-example": "Mac" + }, + "osName": { + "type": "string", + "description": "Operating system name.", + "x-example": "Mac" + }, + "osVersion": { + "type": "string", + "description": "Operating system version.", + "x-example": "Mac" + }, + "clientType": { + "type": "string", + "description": "Client type.", + "x-example": "browser" + }, + "clientCode": { + "type": "string", + "description": "Client code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/clients.json).", + "x-example": "CM" + }, + "clientName": { + "type": "string", + "description": "Client name.", + "x-example": "Chrome Mobile iOS" + }, + "clientVersion": { + "type": "string", + "description": "Client version.", + "x-example": "84.0" + }, + "clientEngine": { + "type": "string", + "description": "Client engine name.", + "x-example": "WebKit" + }, + "clientEngineVersion": { + "type": "string", + "description": "Client engine name.", + "x-example": "605.1.15" + }, + "deviceName": { + "type": "string", + "description": "Device name.", + "x-example": "smartphone" + }, + "deviceBrand": { + "type": "string", + "description": "Device brand name.", + "x-example": "Google" + }, + "deviceModel": { + "type": "string", + "description": "Device model name.", + "x-example": "Nexus 5" + }, + "countryCode": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + }, + "countryName": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + } + }, + "required": [ + "event", + "userId", + "userEmail", + "userName", + "mode", + "ip", + "time", + "osCode", + "osName", + "osVersion", + "clientType", + "clientCode", + "clientName", + "clientVersion", + "clientEngine", + "clientEngineVersion", + "deviceName", + "deviceBrand", + "deviceModel", + "countryCode", + "countryName" + ] + }, + "user": { + "description": "User", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "User creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "User update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "User name.", + "x-example": "John Doe" + }, + "password": { + "type": "string", + "description": "Hashed user password.", + "x-example": "$argon2id$v=19$m=2048,t=4,p=3$aUZjLnliVWRINmFNTWMudg$5S+x+7uA31xFnrHFT47yFwcJeaP0w92L\/4LdgrVRXxE", + "x-nullable": true + }, + "hash": { + "type": "string", + "description": "Password hashing algorithm.", + "x-example": "argon2", + "x-nullable": true + }, + "hashOptions": { + "type": "object", + "description": "Password hashing algorithm configuration.", + "x-example": {}, + "items": { + "x-oneOf": [ + { + "$ref": "#\/definitions\/algoArgon2" + }, + { + "$ref": "#\/definitions\/algoScrypt" + }, + { + "$ref": "#\/definitions\/algoScryptModified" + }, + { + "$ref": "#\/definitions\/algoBcrypt" + }, + { + "$ref": "#\/definitions\/algoPhpass" + }, + { + "$ref": "#\/definitions\/algoSha" + }, + { + "$ref": "#\/definitions\/algoMd5" + } + ] + }, + "x-nullable": true + }, + "registration": { + "type": "string", + "description": "User registration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "status": { + "type": "boolean", + "description": "User status. Pass `true` for enabled and `false` for disabled.", + "x-example": true + }, + "labels": { + "type": "array", + "description": "Labels for the user.", + "items": { + "type": "string" + }, + "x-example": [ + "vip" + ] + }, + "passwordUpdate": { + "type": "string", + "description": "Password update time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "email": { + "type": "string", + "description": "User email address.", + "x-example": "john@appwrite.io" + }, + "phone": { + "type": "string", + "description": "User phone number in E.164 format.", + "x-example": "+4930901820" + }, + "emailVerification": { + "type": "boolean", + "description": "Email verification status.", + "x-example": true + }, + "phoneVerification": { + "type": "boolean", + "description": "Phone verification status.", + "x-example": true + }, + "mfa": { + "type": "boolean", + "description": "Multi factor authentication status.", + "x-example": true + }, + "prefs": { + "type": "object", + "description": "User preferences as a key-value object", + "x-example": { + "theme": "pink", + "timezone": "UTC" + }, + "items": { + "type": "object", + "$ref": "#\/definitions\/preferences" + } + }, + "targets": { + "type": "array", + "description": "A user-owned message receiver. A single user may have multiple e.g. emails, phones, and a browser. Each target is registered with a single provider.", + "items": { + "type": "object", + "$ref": "#\/definitions\/target" + }, + "x-example": [] + }, + "accessedAt": { + "type": "string", + "description": "Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "registration", + "status", + "labels", + "passwordUpdate", + "email", + "phone", + "emailVerification", + "phoneVerification", + "mfa", + "prefs", + "targets", + "accessedAt" + ] + }, + "algoMd5": { + "description": "AlgoMD5", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "md5" + } + }, + "required": [ + "type" + ] + }, + "algoSha": { + "description": "AlgoSHA", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "sha" + } + }, + "required": [ + "type" + ] + }, + "algoPhpass": { + "description": "AlgoPHPass", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "phpass" + } + }, + "required": [ + "type" + ] + }, + "algoBcrypt": { + "description": "AlgoBcrypt", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "bcrypt" + } + }, + "required": [ + "type" + ] + }, + "algoScrypt": { + "description": "AlgoScrypt", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "scrypt" + }, + "costCpu": { + "type": "integer", + "description": "CPU complexity of computed hash.", + "x-example": 8, + "format": "int32" + }, + "costMemory": { + "type": "integer", + "description": "Memory complexity of computed hash.", + "x-example": 14, + "format": "int32" + }, + "costParallel": { + "type": "integer", + "description": "Parallelization of computed hash.", + "x-example": 1, + "format": "int32" + }, + "length": { + "type": "integer", + "description": "Length used to compute hash.", + "x-example": 64, + "format": "int32" + } + }, + "required": [ + "type", + "costCpu", + "costMemory", + "costParallel", + "length" + ] + }, + "algoScryptModified": { + "description": "AlgoScryptModified", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "scryptMod" + }, + "salt": { + "type": "string", + "description": "Salt used to compute hash.", + "x-example": "UxLMreBr6tYyjQ==" + }, + "saltSeparator": { + "type": "string", + "description": "Separator used to compute hash.", + "x-example": "Bw==" + }, + "signerKey": { + "type": "string", + "description": "Key used to compute hash.", + "x-example": "XyEKE9RcTDeLEsL\/RjwPDBv\/RqDl8fb3gpYEOQaPihbxf1ZAtSOHCjuAAa7Q3oHpCYhXSN9tizHgVOwn6krflQ==" + } + }, + "required": [ + "type", + "salt", + "saltSeparator", + "signerKey" + ] + }, + "algoArgon2": { + "description": "AlgoArgon2", + "type": "object", + "properties": { + "type": { + "type": "string", + "description": "Algo type.", + "x-example": "argon2" + }, + "memoryCost": { + "type": "integer", + "description": "Memory used to compute hash.", + "x-example": 65536, + "format": "int32" + }, + "timeCost": { + "type": "integer", + "description": "Amount of time consumed to compute hash", + "x-example": 4, + "format": "int32" + }, + "threads": { + "type": "integer", + "description": "Number of threads used to compute hash.", + "x-example": 3, + "format": "int32" + } + }, + "required": [ + "type", + "memoryCost", + "timeCost", + "threads" + ] + }, + "preferences": { + "description": "Preferences", + "type": "object", + "additionalProperties": true + }, + "session": { + "description": "Session", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Session ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Session creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Session update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5bb8c16897e" + }, + "expire": { + "type": "string", + "description": "Session expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "provider": { + "type": "string", + "description": "Session Provider.", + "x-example": "email" + }, + "providerUid": { + "type": "string", + "description": "Session Provider User ID.", + "x-example": "user@example.com" + }, + "providerAccessToken": { + "type": "string", + "description": "Session Provider Access Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + }, + "providerAccessTokenExpiry": { + "type": "string", + "description": "The date of when the access token expires in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "providerRefreshToken": { + "type": "string", + "description": "Session Provider Refresh Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + }, + "ip": { + "type": "string", + "description": "IP in use when the session was created.", + "x-example": "127.0.0.1" + }, + "osCode": { + "type": "string", + "description": "Operating system code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/os.json).", + "x-example": "Mac" + }, + "osName": { + "type": "string", + "description": "Operating system name.", + "x-example": "Mac" + }, + "osVersion": { + "type": "string", + "description": "Operating system version.", + "x-example": "Mac" + }, + "clientType": { + "type": "string", + "description": "Client type.", + "x-example": "browser" + }, + "clientCode": { + "type": "string", + "description": "Client code name. View list of [available options](https:\/\/github.com\/appwrite\/appwrite\/blob\/master\/docs\/lists\/clients.json).", + "x-example": "CM" + }, + "clientName": { + "type": "string", + "description": "Client name.", + "x-example": "Chrome Mobile iOS" + }, + "clientVersion": { + "type": "string", + "description": "Client version.", + "x-example": "84.0" + }, + "clientEngine": { + "type": "string", + "description": "Client engine name.", + "x-example": "WebKit" + }, + "clientEngineVersion": { + "type": "string", + "description": "Client engine name.", + "x-example": "605.1.15" + }, + "deviceName": { + "type": "string", + "description": "Device name.", + "x-example": "smartphone" + }, + "deviceBrand": { + "type": "string", + "description": "Device brand name.", + "x-example": "Google" + }, + "deviceModel": { + "type": "string", + "description": "Device model name.", + "x-example": "Nexus 5" + }, + "countryCode": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + }, + "countryName": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + }, + "current": { + "type": "boolean", + "description": "Returns true if this the current user session.", + "x-example": true + }, + "factors": { + "type": "array", + "description": "Returns a list of active session factors.", + "items": { + "type": "string" + }, + "x-example": [ + "email" + ] + }, + "secret": { + "type": "string", + "description": "Secret used to authenticate the user. Only included if the request was made with an API key", + "x-example": "5e5bb8c16897e" + }, + "mfaUpdatedAt": { + "type": "string", + "description": "Most recent date in ISO 8601 format when the session successfully passed MFA challenge.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "userId", + "expire", + "provider", + "providerUid", + "providerAccessToken", + "providerAccessTokenExpiry", + "providerRefreshToken", + "ip", + "osCode", + "osName", + "osVersion", + "clientType", + "clientCode", + "clientName", + "clientVersion", + "clientEngine", + "clientEngineVersion", + "deviceName", + "deviceBrand", + "deviceModel", + "countryCode", + "countryName", + "current", + "factors", + "secret", + "mfaUpdatedAt" + ] + }, + "identity": { + "description": "Identity", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Identity ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Identity creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Identity update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5bb8c16897e" + }, + "provider": { + "type": "string", + "description": "Identity Provider.", + "x-example": "email" + }, + "providerUid": { + "type": "string", + "description": "ID of the User in the Identity Provider.", + "x-example": "5e5bb8c16897e" + }, + "providerEmail": { + "type": "string", + "description": "Email of the User in the Identity Provider.", + "x-example": "user@example.com" + }, + "providerAccessToken": { + "type": "string", + "description": "Identity Provider Access Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + }, + "providerAccessTokenExpiry": { + "type": "string", + "description": "The date of when the access token expires in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "providerRefreshToken": { + "type": "string", + "description": "Identity Provider Refresh Token.", + "x-example": "MTQ0NjJkZmQ5OTM2NDE1ZTZjNGZmZjI3" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "userId", + "provider", + "providerUid", + "providerEmail", + "providerAccessToken", + "providerAccessTokenExpiry", + "providerRefreshToken" + ] + }, + "token": { + "description": "Token", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Token ID.", + "x-example": "bb8ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Token creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c168bb8" + }, + "secret": { + "type": "string", + "description": "Token secret key. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.", + "x-example": "" + }, + "expire": { + "type": "string", + "description": "Token expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "phrase": { + "type": "string", + "description": "Security phrase of a token. Empty if security phrase was not requested when creating a token. It includes randomly generated phrase which is also sent in the external resource such as email.", + "x-example": "Golden Fox" + } + }, + "required": [ + "$id", + "$createdAt", + "userId", + "secret", + "expire", + "phrase" + ] + }, + "jwt": { + "description": "JWT", + "type": "object", + "properties": { + "jwt": { + "type": "string", + "description": "JWT encoded string.", + "x-example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + } + }, + "required": [ + "jwt" + ] + }, + "locale": { + "description": "Locale", + "type": "object", + "properties": { + "ip": { + "type": "string", + "description": "User IP address.", + "x-example": "127.0.0.1" + }, + "countryCode": { + "type": "string", + "description": "Country code in [ISO 3166-1](http:\/\/en.wikipedia.org\/wiki\/ISO_3166-1) two-character format", + "x-example": "US" + }, + "country": { + "type": "string", + "description": "Country name. This field support localization.", + "x-example": "United States" + }, + "continentCode": { + "type": "string", + "description": "Continent code. A two character continent code \"AF\" for Africa, \"AN\" for Antarctica, \"AS\" for Asia, \"EU\" for Europe, \"NA\" for North America, \"OC\" for Oceania, and \"SA\" for South America.", + "x-example": "NA" + }, + "continent": { + "type": "string", + "description": "Continent name. This field support localization.", + "x-example": "North America" + }, + "eu": { + "type": "boolean", + "description": "True if country is part of the European Union.", + "x-example": false + }, + "currency": { + "type": "string", + "description": "Currency code in [ISO 4217-1](http:\/\/en.wikipedia.org\/wiki\/ISO_4217) three-character format", + "x-example": "USD" + } + }, + "required": [ + "ip", + "countryCode", + "country", + "continentCode", + "continent", + "eu", + "currency" + ] + }, + "localeCode": { + "description": "LocaleCode", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Locale codes in [ISO 639-1](https:\/\/en.wikipedia.org\/wiki\/List_of_ISO_639-1_codes)", + "x-example": "en-us" + }, + "name": { + "type": "string", + "description": "Locale name", + "x-example": "US" + } + }, + "required": [ + "code", + "name" + ] + }, + "file": { + "description": "File", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "File ID.", + "x-example": "5e5ea5c16897e" + }, + "bucketId": { + "type": "string", + "description": "Bucket ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "File creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "File update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "File permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + }, + "name": { + "type": "string", + "description": "File name.", + "x-example": "Pink.png" + }, + "signature": { + "type": "string", + "description": "File MD5 signature.", + "x-example": "5d529fd02b544198ae075bd57c1762bb" + }, + "mimeType": { + "type": "string", + "description": "File mime type.", + "x-example": "image\/png" + }, + "sizeOriginal": { + "type": "integer", + "description": "File original size in bytes.", + "x-example": 17890, + "format": "int32" + }, + "chunksTotal": { + "type": "integer", + "description": "Total number of chunks available", + "x-example": 17890, + "format": "int32" + }, + "chunksUploaded": { + "type": "integer", + "description": "Total number of chunks uploaded", + "x-example": 17890, + "format": "int32" + } + }, + "required": [ + "$id", + "bucketId", + "$createdAt", + "$updatedAt", + "$permissions", + "name", + "signature", + "mimeType", + "sizeOriginal", + "chunksTotal", + "chunksUploaded" + ] + }, + "bucket": { + "description": "Bucket", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Bucket ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Bucket creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Bucket update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Bucket permissions. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "items": { + "type": "string" + }, + "x-example": [ + "read(\"any\")" + ] + }, + "fileSecurity": { + "type": "boolean", + "description": "Whether file-level security is enabled. [Learn more about permissions](https:\/\/appwrite.io\/docs\/permissions).", + "x-example": true + }, + "name": { + "type": "string", + "description": "Bucket name.", + "x-example": "Documents" + }, + "enabled": { + "type": "boolean", + "description": "Bucket enabled.", + "x-example": false + }, + "maximumFileSize": { + "type": "integer", + "description": "Maximum file size supported.", + "x-example": 100, + "format": "int32" + }, + "allowedFileExtensions": { + "type": "array", + "description": "Allowed file extensions.", + "items": { + "type": "string" + }, + "x-example": [ + "jpg", + "png" + ] + }, + "compression": { + "type": "string", + "description": "Compression algorithm choosen for compression. Will be one of none, [gzip](https:\/\/en.wikipedia.org\/wiki\/Gzip), or [zstd](https:\/\/en.wikipedia.org\/wiki\/Zstd).", + "x-example": "gzip" + }, + "encryption": { + "type": "boolean", + "description": "Bucket is encrypted.", + "x-example": false + }, + "antivirus": { + "type": "boolean", + "description": "Virus scanning is enabled.", + "x-example": false + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "$permissions", + "fileSecurity", + "name", + "enabled", + "maximumFileSize", + "allowedFileExtensions", + "compression", + "encryption", + "antivirus" + ] + }, + "resourceToken": { + "description": "ResourceToken", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Token ID.", + "x-example": "bb8ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Token creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "resourceId": { + "type": "string", + "description": "Resource ID.", + "x-example": "5e5ea5c168bb8:5e5ea5c168bb8" + }, + "resourceType": { + "type": "string", + "description": "Resource type.", + "x-example": "files" + }, + "expire": { + "type": "string", + "description": "Token expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "secret": { + "type": "string", + "description": "JWT encoded string.", + "x-example": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c" + }, + "accessedAt": { + "type": "string", + "description": "Most recent access date in ISO 8601 format. This attribute is only updated again after 24 hours.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "resourceId", + "resourceType", + "expire", + "secret", + "accessedAt" + ] + }, + "team": { + "description": "Team", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Team ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Team creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Team update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Team name.", + "x-example": "VIP" + }, + "total": { + "type": "integer", + "description": "Total number of team members.", + "x-example": 7, + "format": "int32" + }, + "prefs": { + "type": "object", + "description": "Team preferences as a key-value object", + "x-example": { + "theme": "pink", + "timezone": "UTC" + }, + "items": { + "type": "object", + "$ref": "#\/definitions\/preferences" + } + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "total", + "prefs" + ] + }, + "membership": { + "description": "Membership", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Membership ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Membership creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Membership update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c16897e" + }, + "userName": { + "type": "string", + "description": "User name. Hide this attribute by toggling membership privacy in the Console.", + "x-example": "John Doe" + }, + "userEmail": { + "type": "string", + "description": "User email address. Hide this attribute by toggling membership privacy in the Console.", + "x-example": "john@appwrite.io" + }, + "teamId": { + "type": "string", + "description": "Team ID.", + "x-example": "5e5ea5c16897e" + }, + "teamName": { + "type": "string", + "description": "Team name.", + "x-example": "VIP" + }, + "invited": { + "type": "string", + "description": "Date, the user has been invited to join the team in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "joined": { + "type": "string", + "description": "Date, the user has accepted the invitation to join the team in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "confirm": { + "type": "boolean", + "description": "User confirmation status, true if the user has joined the team or false otherwise.", + "x-example": false + }, + "mfa": { + "type": "boolean", + "description": "Multi factor authentication status, true if the user has MFA enabled or false otherwise. Hide this attribute by toggling membership privacy in the Console.", + "x-example": false + }, + "roles": { + "type": "array", + "description": "User list of roles", + "items": { + "type": "string" + }, + "x-example": [ + "owner" + ] + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "userId", + "userName", + "userEmail", + "teamId", + "teamName", + "invited", + "joined", + "confirm", + "mfa", + "roles" + ] + }, + "site": { + "description": "Site", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Site ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Site creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Site update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Site name.", + "x-example": "My Site" + }, + "enabled": { + "type": "boolean", + "description": "Site enabled.", + "x-example": false + }, + "live": { + "type": "boolean", + "description": "Is the site deployed with the latest configuration? This is set to false if you've changed an environment variables, entrypoint, commands, or other settings that needs redeploy to be applied. When the value is false, redeploy the site to update it with the latest configuration.", + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, request logs will exclude logs and errors, and site responses will be slightly faster.", + "x-example": false + }, + "framework": { + "type": "string", + "description": "Site framework.", + "x-example": "react" + }, + "deploymentId": { + "type": "string", + "description": "Site's active deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "deploymentCreatedAt": { + "type": "string", + "description": "Active deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "deploymentScreenshotLight": { + "type": "string", + "description": "Screenshot of active deployment with light theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "deploymentScreenshotDark": { + "type": "string", + "description": "Screenshot of active deployment with dark theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentId": { + "type": "string", + "description": "Site's latest deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentCreatedAt": { + "type": "string", + "description": "Latest deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentStatus": { + "type": "string", + "description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, + "vars": { + "type": "array", + "description": "Site variables.", + "items": { + "type": "object", + "$ref": "#\/definitions\/variable" + }, + "x-example": [] + }, + "timeout": { + "type": "integer", + "description": "Site request timeout in seconds.", + "x-example": 300, + "format": "int32" + }, + "installCommand": { + "type": "string", + "description": "The install command used to install the site dependencies.", + "x-example": "npm install" + }, + "buildCommand": { + "type": "string", + "description": "The build command used to build the site.", + "x-example": "npm run build" + }, + "outputDirectory": { + "type": "string", + "description": "The directory where the site build output is located.", + "x-example": "build" + }, + "installationId": { + "type": "string", + "description": "Site VCS (Version Control System) installation id.", + "x-example": "6m40at4ejk5h2u9s1hboo" + }, + "providerRepositoryId": { + "type": "string", + "description": "VCS (Version Control System) Repository ID", + "x-example": "appwrite" + }, + "providerBranch": { + "type": "string", + "description": "VCS (Version Control System) branch name", + "x-example": "main" + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to site in VCS (Version Control System) repository", + "x-example": "sites\/helloWorld" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is VCS (Version Control System) connection is in silent mode? When in silence mode, no comments will be posted on the repository pull or merge requests", + "x-example": false + }, + "specification": { + "type": "string", + "description": "Machine specification for builds and executions.", + "x-example": "s-1vcpu-512mb" + }, + "buildRuntime": { + "type": "string", + "description": "Site build runtime.", + "x-example": "node-22" + }, + "adapter": { + "type": "string", + "description": "Site framework adapter.", + "x-example": "static" + }, + "fallbackFile": { + "type": "string", + "description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.", + "x-example": "index.html" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "enabled", + "live", + "logging", + "framework", + "deploymentId", + "deploymentCreatedAt", + "deploymentScreenshotLight", + "deploymentScreenshotDark", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", + "vars", + "timeout", + "installCommand", + "buildCommand", + "outputDirectory", + "installationId", + "providerRepositoryId", + "providerBranch", + "providerRootDirectory", + "providerSilentMode", + "specification", + "buildRuntime", + "adapter", + "fallbackFile" + ] + }, + "function": { + "description": "Function", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Function ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Function creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Function update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "execute": { + "type": "array", + "description": "Execution permissions.", + "items": { + "type": "string" + }, + "x-example": "users" + }, + "name": { + "type": "string", + "description": "Function name.", + "x-example": "My Function" + }, + "enabled": { + "type": "boolean", + "description": "Function enabled.", + "x-example": false + }, + "live": { + "type": "boolean", + "description": "Is the function deployed with the latest configuration? This is set to false if you've changed an environment variables, entrypoint, commands, or other settings that needs redeploy to be applied. When the value is false, redeploy the function to update it with the latest configuration.", + "x-example": false + }, + "logging": { + "type": "boolean", + "description": "When disabled, executions will exclude logs and errors, and will be slightly faster.", + "x-example": false + }, + "runtime": { + "type": "string", + "description": "Function execution and build runtime.", + "x-example": "python-3.8" + }, + "deploymentId": { + "type": "string", + "description": "Function's active deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "deploymentCreatedAt": { + "type": "string", + "description": "Active deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentId": { + "type": "string", + "description": "Function's latest deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "latestDeploymentCreatedAt": { + "type": "string", + "description": "Latest deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "latestDeploymentStatus": { + "type": "string", + "description": "Status of latest deployment. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, + "scopes": { + "type": "array", + "description": "Allowed permission scopes.", + "items": { + "type": "string" + }, + "x-example": "users.read" + }, + "vars": { + "type": "array", + "description": "Function variables.", + "items": { + "type": "object", + "$ref": "#\/definitions\/variable" + }, + "x-example": [] + }, + "events": { + "type": "array", + "description": "Function trigger events.", + "items": { + "type": "string" + }, + "x-example": "account.create" + }, + "schedule": { + "type": "string", + "description": "Function execution schedule in CRON format.", + "x-example": "5 4 * * *" + }, + "timeout": { + "type": "integer", + "description": "Function execution timeout in seconds.", + "x-example": 300, + "format": "int32" + }, + "entrypoint": { + "type": "string", + "description": "The entrypoint file used to execute the deployment.", + "x-example": "index.js" + }, + "commands": { + "type": "string", + "description": "The build command used to build the deployment.", + "x-example": "npm install" + }, + "version": { + "type": "string", + "description": "Version of Open Runtimes used for the function.", + "x-example": "v2" + }, + "installationId": { + "type": "string", + "description": "Function VCS (Version Control System) installation id.", + "x-example": "6m40at4ejk5h2u9s1hboo" + }, + "providerRepositoryId": { + "type": "string", + "description": "VCS (Version Control System) Repository ID", + "x-example": "appwrite" + }, + "providerBranch": { + "type": "string", + "description": "VCS (Version Control System) branch name", + "x-example": "main" + }, + "providerRootDirectory": { + "type": "string", + "description": "Path to function in VCS (Version Control System) repository", + "x-example": "functions\/helloWorld" + }, + "providerSilentMode": { + "type": "boolean", + "description": "Is VCS (Version Control System) connection is in silent mode? When in silence mode, no comments will be posted on the repository pull or merge requests", + "x-example": false + }, + "specification": { + "type": "string", + "description": "Machine specification for builds and executions.", + "x-example": "s-1vcpu-512mb" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "execute", + "name", + "enabled", + "live", + "logging", + "runtime", + "deploymentId", + "deploymentCreatedAt", + "latestDeploymentId", + "latestDeploymentCreatedAt", + "latestDeploymentStatus", + "scopes", + "vars", + "events", + "schedule", + "timeout", + "entrypoint", + "commands", + "version", + "installationId", + "providerRepositoryId", + "providerBranch", + "providerRootDirectory", + "providerSilentMode", + "specification" + ] + }, + "runtime": { + "description": "Runtime", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Runtime ID.", + "x-example": "python-3.8" + }, + "key": { + "type": "string", + "description": "Parent runtime key.", + "x-example": "python" + }, + "name": { + "type": "string", + "description": "Runtime Name.", + "x-example": "Python" + }, + "version": { + "type": "string", + "description": "Runtime version.", + "x-example": "3.8" + }, + "base": { + "type": "string", + "description": "Base Docker image used to build the runtime.", + "x-example": "python:3.8-alpine" + }, + "image": { + "type": "string", + "description": "Image name of Docker Hub.", + "x-example": "appwrite\\\/runtime-for-python:3.8" + }, + "logo": { + "type": "string", + "description": "Name of the logo image.", + "x-example": "python.png" + }, + "supports": { + "type": "array", + "description": "List of supported architectures.", + "items": { + "type": "string" + }, + "x-example": "amd64" + } + }, + "required": [ + "$id", + "key", + "name", + "version", + "base", + "image", + "logo", + "supports" + ] + }, + "framework": { + "description": "Framework", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Framework key.", + "x-example": "sveltekit" + }, + "name": { + "type": "string", + "description": "Framework Name.", + "x-example": "SvelteKit" + }, + "buildRuntime": { + "type": "string", + "description": "Default runtime version.", + "x-example": "node-22" + }, + "runtimes": { + "type": "array", + "description": "List of supported runtime versions.", + "items": { + "type": "string" + }, + "x-example": [ + "static-1", + "node-22" + ] + }, + "adapters": { + "type": "array", + "description": "List of supported adapters.", + "items": { + "type": "object", + "$ref": "#\/definitions\/frameworkAdapter" + }, + "x-example": [ + { + "key": "static", + "buildRuntime": "node-22", + "buildCommand": "npm run build", + "installCommand": "npm install", + "outputDirectory": ".\/dist" + } + ] + } + }, + "required": [ + "key", + "name", + "buildRuntime", + "runtimes", + "adapters" + ] + }, + "frameworkAdapter": { + "description": "Framework Adapter", + "type": "object", + "properties": { + "key": { + "type": "string", + "description": "Adapter key.", + "x-example": "static" + }, + "installCommand": { + "type": "string", + "description": "Default command to download dependencies.", + "x-example": "npm install" + }, + "buildCommand": { + "type": "string", + "description": "Default command to build site into output directory.", + "x-example": "npm run build" + }, + "outputDirectory": { + "type": "string", + "description": "Default output directory of build.", + "x-example": ".\/dist" + }, + "fallbackFile": { + "type": "string", + "description": "Name of fallback file to use instead of 404 page. If null, Appwrite 404 page will be displayed.", + "x-example": "index.html" + } + }, + "required": [ + "key", + "installCommand", + "buildCommand", + "outputDirectory", + "fallbackFile" + ] + }, + "deployment": { + "description": "Deployment", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Deployment ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Deployment creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Deployment update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "type": { + "type": "string", + "description": "Type of deployment.", + "x-example": "vcs" + }, + "resourceId": { + "type": "string", + "description": "Resource ID.", + "x-example": "5e5ea6g16897e" + }, + "resourceType": { + "type": "string", + "description": "Resource type.", + "x-example": "functions" + }, + "entrypoint": { + "type": "string", + "description": "The entrypoint file to use to execute the deployment code.", + "x-example": "index.js" + }, + "sourceSize": { + "type": "integer", + "description": "The code size in bytes.", + "x-example": 128, + "format": "int32" + }, + "buildSize": { + "type": "integer", + "description": "The build output size in bytes.", + "x-example": 128, + "format": "int32" + }, + "totalSize": { + "type": "integer", + "description": "The total size in bytes (source and build output).", + "x-example": 128, + "format": "int32" + }, + "buildId": { + "type": "string", + "description": "The current build ID.", + "x-example": "5e5ea5c16897e" + }, + "activate": { + "type": "boolean", + "description": "Whether the deployment should be automatically activated.", + "x-example": true + }, + "screenshotLight": { + "type": "string", + "description": "Screenshot with light theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "screenshotDark": { + "type": "string", + "description": "Screenshot with dark theme preference file ID.", + "x-example": "5e5ea5c16897e" + }, + "status": { + "type": "string", + "description": "The deployment status. Possible values are \"waiting\", \"processing\", \"building\", \"ready\", and \"failed\".", + "x-example": "ready" + }, + "buildLogs": { + "type": "string", + "description": "The build logs.", + "x-example": "Compiling source files..." + }, + "buildDuration": { + "type": "integer", + "description": "The current build time in seconds.", + "x-example": 128, + "format": "int32" + }, + "providerRepositoryName": { + "type": "string", + "description": "The name of the vcs provider repository", + "x-example": "database" + }, + "providerRepositoryOwner": { + "type": "string", + "description": "The name of the vcs provider repository owner", + "x-example": "utopia" + }, + "providerRepositoryUrl": { + "type": "string", + "description": "The url of the vcs provider repository", + "x-example": "https:\/\/github.com\/vermakhushboo\/g4-node-function" + }, + "providerBranch": { + "type": "string", + "description": "The branch of the vcs repository", + "x-example": "0.7.x" + }, + "providerCommitHash": { + "type": "string", + "description": "The commit hash of the vcs commit", + "x-example": "7c3f25d" + }, + "providerCommitAuthorUrl": { + "type": "string", + "description": "The url of vcs commit author", + "x-example": "https:\/\/github.com\/vermakhushboo" + }, + "providerCommitAuthor": { + "type": "string", + "description": "The name of vcs commit author", + "x-example": "Khushboo Verma" + }, + "providerCommitMessage": { + "type": "string", + "description": "The commit message", + "x-example": "Update index.js" + }, + "providerCommitUrl": { + "type": "string", + "description": "The url of the vcs commit", + "x-example": "https:\/\/github.com\/vermakhushboo\/g4-node-function\/commit\/60c0416257a9cbcdd96b2d370c38d8f8d150ccfb" + }, + "providerBranchUrl": { + "type": "string", + "description": "The branch of the vcs repository", + "x-example": "https:\/\/github.com\/vermakhushboo\/appwrite\/tree\/0.7.x" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "type", + "resourceId", + "resourceType", + "entrypoint", + "sourceSize", + "buildSize", + "totalSize", + "buildId", + "activate", + "screenshotLight", + "screenshotDark", + "status", + "buildLogs", + "buildDuration", + "providerRepositoryName", + "providerRepositoryOwner", + "providerRepositoryUrl", + "providerBranch", + "providerCommitHash", + "providerCommitAuthorUrl", + "providerCommitAuthor", + "providerCommitMessage", + "providerCommitUrl", + "providerBranchUrl" + ] + }, + "execution": { + "description": "Execution", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Execution ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Execution creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Execution upate date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$permissions": { + "type": "array", + "description": "Execution roles.", + "items": { + "type": "string" + }, + "x-example": [ + "any" + ] + }, + "functionId": { + "type": "string", + "description": "Function ID.", + "x-example": "5e5ea6g16897e" + }, + "trigger": { + "type": "string", + "description": "The trigger that caused the function to execute. Possible values can be: `http`, `schedule`, or `event`.", + "x-example": "http" + }, + "status": { + "type": "string", + "description": "The status of the function execution. Possible values can be: `waiting`, `processing`, `completed`, or `failed`.", + "x-example": "processing" + }, + "requestMethod": { + "type": "string", + "description": "HTTP request method type.", + "x-example": "GET" + }, + "requestPath": { + "type": "string", + "description": "HTTP request path and query.", + "x-example": "\/articles?id=5" + }, + "requestHeaders": { + "type": "array", + "description": "HTTP response headers as a key-value object. This will return only whitelisted headers. All headers are returned if execution is created as synchronous.", + "items": { + "type": "object", + "$ref": "#\/definitions\/headers" + }, + "x-example": [ + { + "Content-Type": "application\/json" + } + ] + }, + "responseStatusCode": { + "type": "integer", + "description": "HTTP response status code.", + "x-example": 200, + "format": "int32" + }, + "responseBody": { + "type": "string", + "description": "HTTP response body. This will return empty unless execution is created as synchronous.", + "x-example": "" + }, + "responseHeaders": { + "type": "array", + "description": "HTTP response headers as a key-value object. This will return only whitelisted headers. All headers are returned if execution is created as synchronous.", + "items": { + "type": "object", + "$ref": "#\/definitions\/headers" + }, + "x-example": [ + { + "Content-Type": "application\/json" + } + ] + }, + "logs": { + "type": "string", + "description": "Function logs. Includes the last 4,000 characters. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.", + "x-example": "" + }, + "errors": { + "type": "string", + "description": "Function errors. Includes the last 4,000 characters. This will return an empty string unless the response is returned using an API key or as part of a webhook payload.", + "x-example": "" + }, + "duration": { + "type": "number", + "description": "Resource(function\/site) execution duration in seconds.", + "x-example": 0.4, + "format": "double" + }, + "scheduledAt": { + "type": "string", + "description": "The scheduled time for execution. If left empty, execution will be queued immediately.", + "x-example": "2020-10-15T06:38:00.000+00:00", + "x-nullable": true + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "$permissions", + "functionId", + "trigger", + "status", + "requestMethod", + "requestPath", + "requestHeaders", + "responseStatusCode", + "responseBody", + "responseHeaders", + "logs", + "errors", + "duration" + ] + }, + "variable": { + "description": "Variable", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Variable ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Variable creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Variable creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "key": { + "type": "string", + "description": "Variable key.", + "x-example": "API_KEY" + }, + "value": { + "type": "string", + "description": "Variable value.", + "x-example": "myPa$$word1" + }, + "secret": { + "type": "boolean", + "description": "Variable secret flag. Secret variables can only be updated or deleted, but never read.", + "x-example": false + }, + "resourceType": { + "type": "string", + "description": "Service to which the variable belongs. Possible values are \"project\", \"function\"", + "x-example": "function" + }, + "resourceId": { + "type": "string", + "description": "ID of resource to which the variable belongs. If resourceType is \"project\", it is empty. If resourceType is \"function\", it is ID of the function.", + "x-example": "myAwesomeFunction" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "key", + "value", + "secret", + "resourceType", + "resourceId" + ] + }, + "country": { + "description": "Country", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + }, + "code": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + } + }, + "required": [ + "name", + "code" + ] + }, + "continent": { + "description": "Continent", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Continent name.", + "x-example": "Europe" + }, + "code": { + "type": "string", + "description": "Continent two letter code.", + "x-example": "EU" + } + }, + "required": [ + "name", + "code" + ] + }, + "language": { + "description": "Language", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Language name.", + "x-example": "Italian" + }, + "code": { + "type": "string", + "description": "Language two-character ISO 639-1 codes.", + "x-example": "it" + }, + "nativeName": { + "type": "string", + "description": "Language native name.", + "x-example": "Italiano" + } + }, + "required": [ + "name", + "code", + "nativeName" + ] + }, + "currency": { + "description": "Currency", + "type": "object", + "properties": { + "symbol": { + "type": "string", + "description": "Currency symbol.", + "x-example": "$" + }, + "name": { + "type": "string", + "description": "Currency name.", + "x-example": "US dollar" + }, + "symbolNative": { + "type": "string", + "description": "Currency native symbol.", + "x-example": "$" + }, + "decimalDigits": { + "type": "integer", + "description": "Number of decimal digits.", + "x-example": 2, + "format": "int32" + }, + "rounding": { + "type": "number", + "description": "Currency digit rounding.", + "x-example": 0, + "format": "double" + }, + "code": { + "type": "string", + "description": "Currency code in [ISO 4217-1](http:\/\/en.wikipedia.org\/wiki\/ISO_4217) three-character format.", + "x-example": "USD" + }, + "namePlural": { + "type": "string", + "description": "Currency plural name", + "x-example": "US dollars" + } + }, + "required": [ + "symbol", + "name", + "symbolNative", + "decimalDigits", + "rounding", + "code", + "namePlural" + ] + }, + "phone": { + "description": "Phone", + "type": "object", + "properties": { + "code": { + "type": "string", + "description": "Phone code.", + "x-example": "+1" + }, + "countryCode": { + "type": "string", + "description": "Country two-character ISO 3166-1 alpha code.", + "x-example": "US" + }, + "countryName": { + "type": "string", + "description": "Country name.", + "x-example": "United States" + } + }, + "required": [ + "code", + "countryCode", + "countryName" + ] + }, + "healthAntivirus": { + "description": "Health Antivirus", + "type": "object", + "properties": { + "version": { + "type": "string", + "description": "Antivirus version.", + "x-example": "1.0.0" + }, + "status": { + "type": "string", + "description": "Antivirus status. Possible values can are: `disabled`, `offline`, `online`", + "x-example": "online" + } + }, + "required": [ + "version", + "status" + ] + }, + "healthQueue": { + "description": "Health Queue", + "type": "object", + "properties": { + "size": { + "type": "integer", + "description": "Amount of actions in the queue.", + "x-example": 8, + "format": "int32" + } + }, + "required": [ + "size" + ] + }, + "healthStatus": { + "description": "Health Status", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Name of the service.", + "x-example": "database" + }, + "ping": { + "type": "integer", + "description": "Duration in milliseconds how long the health check took.", + "x-example": 128, + "format": "int32" + }, + "status": { + "type": "string", + "description": "Service status. Possible values can are: `pass`, `fail`", + "x-example": "pass" + } + }, + "required": [ + "name", + "ping", + "status" + ] + }, + "healthCertificate": { + "description": "Health Certificate", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Certificate name", + "x-example": "\/CN=www.google.com" + }, + "subjectSN": { + "type": "string", + "description": "Subject SN", + "x-example": "" + }, + "issuerOrganisation": { + "type": "string", + "description": "Issuer organisation", + "x-example": "" + }, + "validFrom": { + "type": "string", + "description": "Valid from", + "x-example": "1704200998" + }, + "validTo": { + "type": "string", + "description": "Valid to", + "x-example": "1711458597" + }, + "signatureTypeSN": { + "type": "string", + "description": "Signature type SN", + "x-example": "RSA-SHA256" + } + }, + "required": [ + "name", + "subjectSN", + "issuerOrganisation", + "validFrom", + "validTo", + "signatureTypeSN" + ] + }, + "healthTime": { + "description": "Health Time", + "type": "object", + "properties": { + "remoteTime": { + "type": "integer", + "description": "Current unix timestamp on trustful remote server.", + "x-example": 1639490751, + "format": "int32" + }, + "localTime": { + "type": "integer", + "description": "Current unix timestamp of local server where Appwrite runs.", + "x-example": 1639490844, + "format": "int32" + }, + "diff": { + "type": "integer", + "description": "Difference of unix remote and local timestamps in milliseconds.", + "x-example": 93, + "format": "int32" + } + }, + "required": [ + "remoteTime", + "localTime", + "diff" + ] + }, + "headers": { + "description": "Headers", + "type": "object", + "properties": { + "name": { + "type": "string", + "description": "Header name.", + "x-example": "Content-Type" + }, + "value": { + "type": "string", + "description": "Header value.", + "x-example": "application\/json" + } + }, + "required": [ + "name", + "value" + ] + }, + "specification": { + "description": "Specification", + "type": "object", + "properties": { + "memory": { + "type": "integer", + "description": "Memory size in MB.", + "x-example": 512, + "format": "int32" + }, + "cpus": { + "type": "number", + "description": "Number of CPUs.", + "x-example": 1, + "format": "double" + }, + "enabled": { + "type": "boolean", + "description": "Is size enabled.", + "x-example": true + }, + "slug": { + "type": "string", + "description": "Size slug.", + "x-example": "s-1vcpu-512mb" + } + }, + "required": [ + "memory", + "cpus", + "enabled", + "slug" + ] + }, + "mfaChallenge": { + "description": "MFA Challenge", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Token ID.", + "x-example": "bb8ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Token creation date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "5e5ea5c168bb8" + }, + "expire": { + "type": "string", + "description": "Token expiration date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + } + }, + "required": [ + "$id", + "$createdAt", + "userId", + "expire" + ] + }, + "mfaRecoveryCodes": { + "description": "MFA Recovery Codes", + "type": "object", + "properties": { + "recoveryCodes": { + "type": "array", + "description": "Recovery codes.", + "items": { + "type": "string" + }, + "x-example": [ + "a3kf0-s0cl2", + "s0co1-as98s" + ] + } + }, + "required": [ + "recoveryCodes" + ] + }, + "mfaType": { + "description": "MFAType", + "type": "object", + "properties": { + "secret": { + "type": "string", + "description": "Secret token used for TOTP factor.", + "x-example": true + }, + "uri": { + "type": "string", + "description": "URI for authenticator apps.", + "x-example": true + } + }, + "required": [ + "secret", + "uri" + ] + }, + "mfaFactors": { + "description": "MFAFactors", + "type": "object", + "properties": { + "totp": { + "type": "boolean", + "description": "Can TOTP be used for MFA challenge for this account.", + "x-example": true + }, + "phone": { + "type": "boolean", + "description": "Can phone (SMS) be used for MFA challenge for this account.", + "x-example": true + }, + "email": { + "type": "boolean", + "description": "Can email be used for MFA challenge for this account.", + "x-example": true + }, + "recoveryCode": { + "type": "boolean", + "description": "Can recovery code be used for MFA challenge for this account.", + "x-example": true + } + }, + "required": [ + "totp", + "phone", + "email", + "recoveryCode" + ] + }, + "provider": { + "description": "Provider", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Provider ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Provider creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Provider update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "The name for the provider instance.", + "x-example": "Mailgun" + }, + "provider": { + "type": "string", + "description": "The name of the provider service.", + "x-example": "mailgun" + }, + "enabled": { + "type": "boolean", + "description": "Is provider enabled?", + "x-example": true + }, + "type": { + "type": "string", + "description": "Type of provider.", + "x-example": "sms" + }, + "credentials": { + "type": "object", + "additionalProperties": true, + "description": "Provider credentials.", + "x-example": { + "key": "123456789" + } + }, + "options": { + "type": "object", + "additionalProperties": true, + "description": "Provider options.", + "x-example": { + "from": "sender-email@mydomain" + } + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "provider", + "enabled", + "type", + "credentials" + ] + }, + "message": { + "description": "Message", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Message ID.", + "x-example": "5e5ea5c16897e" + }, + "$createdAt": { + "type": "string", + "description": "Message creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Message update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "providerType": { + "type": "string", + "description": "Message provider type.", + "x-example": "email" + }, + "topics": { + "type": "array", + "description": "Topic IDs set as recipients.", + "items": { + "type": "string" + }, + "x-example": [ + "5e5ea5c16897e" + ] + }, + "users": { + "type": "array", + "description": "User IDs set as recipients.", + "items": { + "type": "string" + }, + "x-example": [ + "5e5ea5c16897e" + ] + }, + "targets": { + "type": "array", + "description": "Target IDs set as recipients.", + "items": { + "type": "string" + }, + "x-example": [ + "5e5ea5c16897e" + ] + }, + "scheduledAt": { + "type": "string", + "description": "The scheduled time for message.", + "x-example": "2020-10-15T06:38:00.000+00:00", + "x-nullable": true + }, + "deliveredAt": { + "type": "string", + "description": "The time when the message was delivered.", + "x-example": "2020-10-15T06:38:00.000+00:00", + "x-nullable": true + }, + "deliveryErrors": { + "type": "array", + "description": "Delivery errors if any.", + "items": { + "type": "string" + }, + "x-example": [ + "Failed to send message to target 5e5ea5c16897e: Credentials not valid." + ], + "x-nullable": true + }, + "deliveredTotal": { + "type": "integer", + "description": "Number of recipients the message was delivered to.", + "x-example": 1, + "format": "int32" + }, + "data": { + "type": "object", + "additionalProperties": true, + "description": "Data of the message.", + "x-example": { + "subject": "Welcome to Appwrite", + "content": "Hi there, welcome to Appwrite family." + } + }, + "status": { + "type": "string", + "description": "Status of delivery.", + "x-example": "Message status can be one of the following: draft, processing, scheduled, sent, or failed." + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "providerType", + "topics", + "users", + "targets", + "deliveredTotal", + "data", + "status" + ] + }, + "topic": { + "description": "Topic", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Topic ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Topic creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Topic update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "The name of the topic.", + "x-example": "events" + }, + "emailTotal": { + "type": "integer", + "description": "Total count of email subscribers subscribed to the topic.", + "x-example": 100, + "format": "int32" + }, + "smsTotal": { + "type": "integer", + "description": "Total count of SMS subscribers subscribed to the topic.", + "x-example": 100, + "format": "int32" + }, + "pushTotal": { + "type": "integer", + "description": "Total count of push subscribers subscribed to the topic.", + "x-example": 100, + "format": "int32" + }, + "subscribe": { + "type": "array", + "description": "Subscribe permissions.", + "items": { + "type": "string" + }, + "x-example": "users" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "emailTotal", + "smsTotal", + "pushTotal", + "subscribe" + ] + }, + "subscriber": { + "description": "Subscriber", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Subscriber ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Subscriber creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Subscriber update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "targetId": { + "type": "string", + "description": "Target ID.", + "x-example": "259125845563242502" + }, + "target": { + "type": "object", + "description": "Target.", + "x-example": { + "$id": "259125845563242502", + "$createdAt": "2020-10-15T06:38:00.000+00:00", + "$updatedAt": "2020-10-15T06:38:00.000+00:00", + "providerType": "email", + "providerId": "259125845563242502", + "name": "ageon-app-email", + "identifier": "random-mail@email.org", + "userId": "5e5ea5c16897e" + }, + "items": { + "type": "object", + "$ref": "#\/definitions\/target" + } + }, + "userId": { + "type": "string", + "description": "Topic ID.", + "x-example": "5e5ea5c16897e" + }, + "userName": { + "type": "string", + "description": "User Name.", + "x-example": "Aegon Targaryen" + }, + "topicId": { + "type": "string", + "description": "Topic ID.", + "x-example": "259125845563242502" + }, + "providerType": { + "type": "string", + "description": "The target provider type. Can be one of the following: `email`, `sms` or `push`.", + "x-example": "email" + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "targetId", + "target", + "userId", + "userName", + "topicId", + "providerType" + ] + }, + "target": { + "description": "Target", + "type": "object", + "properties": { + "$id": { + "type": "string", + "description": "Target ID.", + "x-example": "259125845563242502" + }, + "$createdAt": { + "type": "string", + "description": "Target creation time in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "$updatedAt": { + "type": "string", + "description": "Target update date in ISO 8601 format.", + "x-example": "2020-10-15T06:38:00.000+00:00" + }, + "name": { + "type": "string", + "description": "Target Name.", + "x-example": "Apple iPhone 12" + }, + "userId": { + "type": "string", + "description": "User ID.", + "x-example": "259125845563242502" + }, + "providerId": { + "type": "string", + "description": "Provider ID.", + "x-example": "259125845563242502", + "x-nullable": true + }, + "providerType": { + "type": "string", + "description": "The target provider type. Can be one of the following: `email`, `sms` or `push`.", + "x-example": "email" + }, + "identifier": { + "type": "string", + "description": "The target identifier.", + "x-example": "token" + }, + "expired": { + "type": "boolean", + "description": "Is the target expired.", + "x-example": false + } + }, + "required": [ + "$id", + "$createdAt", + "$updatedAt", + "name", + "userId", + "providerType", + "identifier", + "expired" + ] + } + }, + "externalDocs": { + "description": "Full API docs, specs and tutorials", + "url": "https:\/\/appwrite.io\/docs" + } +} \ No newline at end of file diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index 92132151b4..d5ff0f609c 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -5023,7 +5023,7 @@ "x-appwrite": { "method": "deleteDocument", "group": "documents", - "weight": 117, + "weight": 119, "cookies": false, "type": "", "deprecated": false, @@ -5078,6 +5078,222 @@ ] } }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/decrement": { + "patch": { + "summary": "Decrement document attribute", + "operationId": "databasesDecrementDocumentAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Decrement a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "decrementDocumentAttribute", + "group": "documents", + "weight": 116, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/decrement-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/decrement-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to decrement the attribute by. The value must be a number.", + "default": 1, + "x-example": null + }, + "min": { + "type": "mixed", + "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", + "default": null, + "x-example": null + } + } + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/increment": { + "patch": { + "summary": "Increment document attribute", + "operationId": "databasesIncrementDocumentAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Increment a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "incrementDocumentAttribute", + "group": "documents", + "weight": 115, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/increment-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/increment-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to increment the attribute by. The value must be a number.", + "default": 1, + "x-example": null + }, + "max": { + "type": "mixed", + "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", + "default": null, + "x-example": null + } + } + } + } + ] + } + }, "\/functions\/{functionId}\/executions": { "get": { "summary": "List executions", @@ -5101,7 +5317,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 392, + "weight": 394, "cookies": false, "type": "", "deprecated": false, @@ -5175,7 +5391,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 390, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -5292,7 +5508,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 391, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -5364,7 +5580,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 306, + "weight": 308, "cookies": false, "type": "graphql", "deprecated": false, @@ -5438,7 +5654,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 305, + "weight": 307, "cookies": false, "type": "graphql", "deprecated": false, @@ -5510,7 +5726,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 122, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -5562,7 +5778,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 123, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -5614,7 +5830,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 127, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -5666,7 +5882,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 124, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -5718,7 +5934,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 125, + "weight": 127, "cookies": false, "type": "", "deprecated": false, @@ -5770,7 +5986,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 126, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -5822,7 +6038,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 128, + "weight": 130, "cookies": false, "type": "", "deprecated": false, @@ -5874,7 +6090,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 129, + "weight": 131, "cookies": false, "type": "", "deprecated": false, @@ -5928,7 +6144,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 352, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -6013,7 +6229,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 356, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -6084,7 +6300,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 212, + "weight": 214, "cookies": false, "type": "", "deprecated": false, @@ -6167,7 +6383,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 211, + "weight": 213, "cookies": false, "type": "upload", "deprecated": false, @@ -6257,7 +6473,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 213, + "weight": 215, "cookies": false, "type": "", "deprecated": false, @@ -6327,7 +6543,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 218, + "weight": 220, "cookies": false, "type": "", "deprecated": false, @@ -6416,7 +6632,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 219, + "weight": 221, "cookies": false, "type": "", "deprecated": false, @@ -6486,7 +6702,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 215, + "weight": 217, "cookies": false, "type": "location", "deprecated": false, @@ -6565,7 +6781,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 214, + "weight": 216, "cookies": false, "type": "location", "deprecated": false, @@ -6729,7 +6945,8 @@ "png", "webp", "heic", - "avif" + "avif", + "gif" ], "x-enum-name": "ImageFormat", "x-enum-keys": [], @@ -6771,7 +6988,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 216, + "weight": 218, "cookies": false, "type": "location", "deprecated": false, @@ -6850,7 +7067,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 223, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -6925,7 +7142,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 222, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -7015,7 +7232,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 224, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -7077,7 +7294,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 226, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -7152,7 +7369,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 228, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -7214,7 +7431,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 230, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -7297,7 +7514,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 229, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -7410,7 +7627,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 231, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -7480,7 +7697,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 232, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -7566,7 +7783,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 234, + "weight": 236, "cookies": false, "type": "", "deprecated": false, @@ -7638,7 +7855,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 233, + "weight": 235, "cookies": false, "type": "", "deprecated": false, @@ -7732,7 +7949,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 225, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -7793,7 +8010,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 227, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -8285,6 +8502,12 @@ "description": "Document ID.", "x-example": "5e5ea5c16897e" }, + "$sequence": { + "type": "integer", + "description": "Document automatically incrementing ID.", + "x-example": 1, + "format": "int32" + }, "$collectionId": { "type": "string", "description": "Collection ID.", @@ -8319,6 +8542,7 @@ "additionalProperties": true, "required": [ "$id", + "$sequence", "$collectionId", "$databaseId", "$createdAt", diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 06a33c9a3d..333ae6f360 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -4527,7 +4527,7 @@ "x-appwrite": { "method": "chat", "group": "console", - "weight": 308, + "weight": 310, "cookies": false, "type": "", "deprecated": false, @@ -4590,7 +4590,7 @@ "x-appwrite": { "method": "getResource", "group": null, - "weight": 432, + "weight": 434, "cookies": false, "type": "", "deprecated": false, @@ -4661,7 +4661,7 @@ "x-appwrite": { "method": "variables", "group": "console", - "weight": 307, + "weight": 309, "cookies": false, "type": "", "deprecated": false, @@ -4863,7 +4863,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 119, + "weight": 121, "cookies": false, "type": "", "deprecated": false, @@ -8296,7 +8296,7 @@ "x-appwrite": { "method": "upsertDocuments", "group": "documents", - "weight": 116, + "weight": 118, "cookies": false, "type": "", "deprecated": false, @@ -8384,7 +8384,7 @@ "x-appwrite": { "method": "updateDocuments", "group": "documents", - "weight": 115, + "weight": 117, "cookies": false, "type": "", "deprecated": false, @@ -8475,7 +8475,7 @@ "x-appwrite": { "method": "deleteDocuments", "group": "documents", - "weight": 118, + "weight": 120, "cookies": false, "type": "", "deprecated": false, @@ -8852,7 +8852,7 @@ "x-appwrite": { "method": "deleteDocument", "group": "documents", - "weight": 117, + "weight": 119, "cookies": false, "type": "", "deprecated": false, @@ -8993,6 +8993,222 @@ ] } }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/decrement": { + "patch": { + "summary": "Decrement document attribute", + "operationId": "databasesDecrementDocumentAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Decrement a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "decrementDocumentAttribute", + "group": "documents", + "weight": 116, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/decrement-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/decrement-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to decrement the attribute by. The value must be a number.", + "default": 1, + "x-example": null + }, + "min": { + "type": "mixed", + "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", + "default": null, + "x-example": null + } + } + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/increment": { + "patch": { + "summary": "Increment document attribute", + "operationId": "databasesIncrementDocumentAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Increment a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "incrementDocumentAttribute", + "group": "documents", + "weight": 115, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/increment-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/increment-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to increment the attribute by. The value must be a number.", + "default": 1, + "x-example": null + }, + "max": { + "type": "mixed", + "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", + "default": null, + "x-example": null + } + } + } + } + ] + } + }, "\/databases\/{databaseId}\/collections\/{collectionId}\/indexes": { "get": { "summary": "List indexes", @@ -9443,7 +9659,7 @@ "x-appwrite": { "method": "getCollectionUsage", "group": null, - "weight": 121, + "weight": 123, "cookies": false, "type": "", "deprecated": false, @@ -9599,7 +9815,7 @@ "x-appwrite": { "method": "getDatabaseUsage", "group": null, - "weight": 120, + "weight": 122, "cookies": false, "type": "", "deprecated": false, @@ -9677,7 +9893,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 376, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -9749,7 +9965,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 373, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -9835,6 +10051,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -9860,7 +10077,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -9998,7 +10216,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 378, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -10047,7 +10265,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 379, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -10097,7 +10315,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 402, + "weight": 404, "cookies": false, "type": "", "deprecated": false, @@ -10191,7 +10409,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 401, + "weight": 403, "cookies": false, "type": "", "deprecated": false, @@ -10249,7 +10467,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 395, + "weight": 397, "cookies": false, "type": "", "deprecated": false, @@ -10319,7 +10537,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 374, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -10378,7 +10596,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 375, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -10466,6 +10684,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -10491,7 +10710,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -10623,7 +10843,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 377, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -10684,7 +10904,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 382, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -10761,7 +10981,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 383, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -10841,7 +11061,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 380, + "weight": 382, "cookies": false, "type": "upload", "deprecated": false, @@ -10933,7 +11153,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 388, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -11018,7 +11238,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 385, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -11124,7 +11344,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 386, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -11220,7 +11440,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 381, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -11282,7 +11502,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 384, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -11349,7 +11569,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 387, + "weight": 389, "cookies": false, "type": "location", "deprecated": false, @@ -11435,7 +11655,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 389, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -11502,7 +11722,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 392, + "weight": 394, "cookies": false, "type": "", "deprecated": false, @@ -11576,7 +11796,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 390, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -11693,7 +11913,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 391, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -11758,7 +11978,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 393, + "weight": 395, "cookies": false, "type": "", "deprecated": false, @@ -11825,7 +12045,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 394, + "weight": 396, "cookies": false, "type": "", "deprecated": false, @@ -11903,7 +12123,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 398, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -11962,7 +12182,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 396, + "weight": 398, "cookies": false, "type": "", "deprecated": false, @@ -12052,7 +12272,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 397, + "weight": 399, "cookies": false, "type": "", "deprecated": false, @@ -12119,7 +12339,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 399, + "weight": 401, "cookies": false, "type": "", "deprecated": false, @@ -12211,7 +12431,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 400, + "weight": 402, "cookies": false, "type": "", "deprecated": false, @@ -12280,7 +12500,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 306, + "weight": 308, "cookies": false, "type": "graphql", "deprecated": false, @@ -12354,7 +12574,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 305, + "weight": 307, "cookies": false, "type": "graphql", "deprecated": false, @@ -12426,7 +12646,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 130, + "weight": 132, "cookies": false, "type": "", "deprecated": false, @@ -12475,7 +12695,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 151, + "weight": 153, "cookies": false, "type": "", "deprecated": false, @@ -12524,7 +12744,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 133, + "weight": 135, "cookies": false, "type": "", "deprecated": false, @@ -12573,7 +12793,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 138, + "weight": 140, "cookies": false, "type": "", "deprecated": false, @@ -12631,7 +12851,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 132, + "weight": 134, "cookies": false, "type": "", "deprecated": false, @@ -12680,7 +12900,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 134, + "weight": 136, "cookies": false, "type": "", "deprecated": false, @@ -12729,7 +12949,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 140, + "weight": 142, "cookies": false, "type": "", "deprecated": false, @@ -12789,7 +13009,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 139, + "weight": 141, "cookies": false, "type": "", "deprecated": false, @@ -12849,7 +13069,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 141, + "weight": 143, "cookies": false, "type": "", "deprecated": false, @@ -12918,7 +13138,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 142, + "weight": 144, "cookies": false, "type": "", "deprecated": false, @@ -12978,7 +13198,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 152, + "weight": 154, "cookies": false, "type": "", "deprecated": false, @@ -13062,7 +13282,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 146, + "weight": 148, "cookies": false, "type": "", "deprecated": false, @@ -13122,7 +13342,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 137, + "weight": 139, "cookies": false, "type": "", "deprecated": false, @@ -13182,7 +13402,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 143, + "weight": 145, "cookies": false, "type": "", "deprecated": false, @@ -13242,7 +13462,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 144, + "weight": 146, "cookies": false, "type": "", "deprecated": false, @@ -13302,7 +13522,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 145, + "weight": 147, "cookies": false, "type": "", "deprecated": false, @@ -13362,7 +13582,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 147, + "weight": 149, "cookies": false, "type": "", "deprecated": false, @@ -13422,7 +13642,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 148, + "weight": 150, "cookies": false, "type": "", "deprecated": false, @@ -13482,7 +13702,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 136, + "weight": 138, "cookies": false, "type": "", "deprecated": false, @@ -13542,7 +13762,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 150, + "weight": 152, "cookies": false, "type": "", "deprecated": false, @@ -13591,7 +13811,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 149, + "weight": 151, "cookies": false, "type": "", "deprecated": false, @@ -13640,7 +13860,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 135, + "weight": 137, "cookies": false, "type": "", "deprecated": false, @@ -13689,7 +13909,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 122, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -13741,7 +13961,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 123, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -13793,7 +14013,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 127, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -13845,7 +14065,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 124, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -13897,7 +14117,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 125, + "weight": 127, "cookies": false, "type": "", "deprecated": false, @@ -13949,7 +14169,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 126, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -14001,7 +14221,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 128, + "weight": 130, "cookies": false, "type": "", "deprecated": false, @@ -14053,7 +14273,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 129, + "weight": 131, "cookies": false, "type": "", "deprecated": false, @@ -14105,7 +14325,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 360, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -14180,7 +14400,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 357, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -14338,7 +14558,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 364, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -14493,7 +14713,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 359, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -14688,7 +14908,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 366, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -14882,7 +15102,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 358, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -15000,7 +15220,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 365, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -15114,7 +15334,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 363, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -15169,7 +15389,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 367, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -15229,7 +15449,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 361, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -15301,7 +15521,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 362, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -15373,7 +15593,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 332, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -15448,7 +15668,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 331, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -15563,7 +15783,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 344, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -15676,7 +15896,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 330, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -15767,7 +15987,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 343, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -15856,7 +16076,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 322, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -15983,7 +16203,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 335, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -16108,7 +16328,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 325, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -16211,7 +16431,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 338, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -16312,7 +16532,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 323, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -16427,7 +16647,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 336, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -16540,7 +16760,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 324, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -16699,7 +16919,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 337, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -16855,7 +17075,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 326, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -16958,7 +17178,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 339, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -17059,7 +17279,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 327, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -17162,7 +17382,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 340, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -17263,7 +17483,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 328, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -17366,7 +17586,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 341, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -17467,7 +17687,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 329, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -17570,7 +17790,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 342, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -17669,7 +17889,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 334, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -17724,7 +17944,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 345, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -17784,7 +18004,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 333, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -17856,7 +18076,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 354, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -17928,7 +18148,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 347, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -18001,7 +18221,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 346, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -18089,7 +18309,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 349, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -18149,7 +18369,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 350, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -18228,7 +18448,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 351, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -18288,7 +18508,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 348, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -18360,7 +18580,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 353, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -18441,7 +18661,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 352, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -18529,7 +18749,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 355, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -18592,7 +18812,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 356, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -18663,7 +18883,7 @@ "x-appwrite": { "method": "list", "group": null, - "weight": 314, + "weight": 316, "cookies": false, "type": "", "deprecated": false, @@ -18736,7 +18956,7 @@ "x-appwrite": { "method": "createAppwriteMigration", "group": null, - "weight": 309, + "weight": 311, "cookies": false, "type": "", "deprecated": false, @@ -18828,7 +19048,7 @@ "x-appwrite": { "method": "getAppwriteReport", "group": null, - "weight": 316, + "weight": 318, "cookies": false, "type": "", "deprecated": false, @@ -18916,7 +19136,7 @@ "x-appwrite": { "method": "createCsvMigration", "group": null, - "weight": 313, + "weight": 315, "cookies": false, "type": "", "deprecated": false, @@ -19000,7 +19220,7 @@ "x-appwrite": { "method": "createFirebaseMigration", "group": null, - "weight": 310, + "weight": 312, "cookies": false, "type": "", "deprecated": false, @@ -19078,7 +19298,7 @@ "x-appwrite": { "method": "getFirebaseReport", "group": null, - "weight": 317, + "weight": 319, "cookies": false, "type": "", "deprecated": false, @@ -19149,7 +19369,7 @@ "x-appwrite": { "method": "createNHostMigration", "group": null, - "weight": 312, + "weight": 314, "cookies": false, "type": "", "deprecated": false, @@ -19268,7 +19488,7 @@ "x-appwrite": { "method": "getNHostReport", "group": null, - "weight": 319, + "weight": 321, "cookies": false, "type": "", "deprecated": false, @@ -19388,7 +19608,7 @@ "x-appwrite": { "method": "createSupabaseMigration", "group": null, - "weight": 311, + "weight": 313, "cookies": false, "type": "", "deprecated": false, @@ -19500,7 +19720,7 @@ "x-appwrite": { "method": "getSupabaseReport", "group": null, - "weight": 318, + "weight": 320, "cookies": false, "type": "", "deprecated": false, @@ -19611,7 +19831,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 315, + "weight": 317, "cookies": false, "type": "", "deprecated": false, @@ -19669,7 +19889,7 @@ "x-appwrite": { "method": "retry", "group": null, - "weight": 320, + "weight": 322, "cookies": false, "type": "", "deprecated": false, @@ -19722,7 +19942,7 @@ "x-appwrite": { "method": "delete", "group": null, - "weight": 321, + "weight": 323, "cookies": false, "type": "", "deprecated": false, @@ -19780,7 +20000,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 200, + "weight": 202, "cookies": false, "type": "", "deprecated": false, @@ -19862,7 +20082,7 @@ "x-appwrite": { "method": "listVariables", "group": null, - "weight": 202, + "weight": 204, "cookies": false, "type": "", "deprecated": false, @@ -19910,7 +20130,7 @@ "x-appwrite": { "method": "createVariable", "group": null, - "weight": 201, + "weight": 203, "cookies": false, "type": "", "deprecated": false, @@ -19991,7 +20211,7 @@ "x-appwrite": { "method": "getVariable", "group": null, - "weight": 203, + "weight": 205, "cookies": false, "type": "", "deprecated": false, @@ -20049,7 +20269,7 @@ "x-appwrite": { "method": "updateVariable", "group": null, - "weight": 204, + "weight": 206, "cookies": false, "type": "", "deprecated": false, @@ -20132,7 +20352,7 @@ "x-appwrite": { "method": "deleteVariable", "group": null, - "weight": 205, + "weight": 207, "cookies": false, "type": "", "deprecated": false, @@ -20190,7 +20410,7 @@ "x-appwrite": { "method": "list", "group": "projects", - "weight": 155, + "weight": 157, "cookies": false, "type": "", "deprecated": false, @@ -20261,7 +20481,7 @@ "x-appwrite": { "method": "create", "group": "projects", - "weight": 154, + "weight": 156, "cookies": false, "type": "", "deprecated": false, @@ -20408,7 +20628,7 @@ "x-appwrite": { "method": "get", "group": "projects", - "weight": 156, + "weight": 158, "cookies": false, "type": "", "deprecated": false, @@ -20466,7 +20686,7 @@ "x-appwrite": { "method": "update", "group": "projects", - "weight": 157, + "weight": 159, "cookies": false, "type": "", "deprecated": false, @@ -20591,7 +20811,7 @@ "x-appwrite": { "method": "delete", "group": "projects", - "weight": 174, + "weight": 176, "cookies": false, "type": "", "deprecated": false, @@ -20651,7 +20871,7 @@ "x-appwrite": { "method": "updateApiStatus", "group": "projects", - "weight": 161, + "weight": 163, "cookies": false, "type": "", "deprecated": false, @@ -20743,7 +20963,7 @@ "x-appwrite": { "method": "updateApiStatusAll", "group": "projects", - "weight": 162, + "weight": 164, "cookies": false, "type": "", "deprecated": false, @@ -20821,7 +21041,7 @@ "x-appwrite": { "method": "updateAuthDuration", "group": "auth", - "weight": 167, + "weight": 169, "cookies": false, "type": "", "deprecated": false, @@ -20899,7 +21119,7 @@ "x-appwrite": { "method": "updateAuthLimit", "group": "auth", - "weight": 166, + "weight": 168, "cookies": false, "type": "", "deprecated": false, @@ -20977,7 +21197,7 @@ "x-appwrite": { "method": "updateAuthSessionsLimit", "group": "auth", - "weight": 172, + "weight": 174, "cookies": false, "type": "", "deprecated": false, @@ -21055,7 +21275,7 @@ "x-appwrite": { "method": "updateMembershipsPrivacy", "group": "auth", - "weight": 165, + "weight": 167, "cookies": false, "type": "", "deprecated": false, @@ -21147,7 +21367,7 @@ "x-appwrite": { "method": "updateMockNumbers", "group": "auth", - "weight": 173, + "weight": 175, "cookies": false, "type": "", "deprecated": false, @@ -21228,7 +21448,7 @@ "x-appwrite": { "method": "updateAuthPasswordDictionary", "group": "auth", - "weight": 170, + "weight": 172, "cookies": false, "type": "", "deprecated": false, @@ -21306,7 +21526,7 @@ "x-appwrite": { "method": "updateAuthPasswordHistory", "group": "auth", - "weight": 169, + "weight": 171, "cookies": false, "type": "", "deprecated": false, @@ -21384,7 +21604,7 @@ "x-appwrite": { "method": "updatePersonalDataCheck", "group": "auth", - "weight": 171, + "weight": 173, "cookies": false, "type": "", "deprecated": false, @@ -21462,7 +21682,7 @@ "x-appwrite": { "method": "updateSessionAlerts", "group": "auth", - "weight": 164, + "weight": 166, "cookies": false, "type": "", "deprecated": false, @@ -21540,7 +21760,7 @@ "x-appwrite": { "method": "updateAuthStatus", "group": "auth", - "weight": 168, + "weight": 170, "cookies": false, "type": "", "deprecated": false, @@ -21635,7 +21855,7 @@ "x-appwrite": { "method": "listDevKeys", "group": "devKeys", - "weight": 371, + "weight": 373, "cookies": false, "type": "", "deprecated": false, @@ -21705,7 +21925,7 @@ "x-appwrite": { "method": "createDevKey", "group": "devKeys", - "weight": 368, + "weight": 370, "cookies": false, "type": "", "deprecated": false, @@ -21788,7 +22008,7 @@ "x-appwrite": { "method": "getDevKey", "group": "devKeys", - "weight": 370, + "weight": 372, "cookies": false, "type": "", "deprecated": false, @@ -21854,7 +22074,7 @@ "x-appwrite": { "method": "updateDevKey", "group": "devKeys", - "weight": 369, + "weight": 371, "cookies": false, "type": "", "deprecated": false, @@ -21940,7 +22160,7 @@ "x-appwrite": { "method": "deleteDevKey", "group": "devKeys", - "weight": 372, + "weight": 374, "cookies": false, "type": "", "deprecated": false, @@ -22008,7 +22228,7 @@ "x-appwrite": { "method": "createJWT", "group": "auth", - "weight": 186, + "weight": 188, "cookies": false, "type": "", "deprecated": false, @@ -22093,7 +22313,7 @@ "x-appwrite": { "method": "listKeys", "group": "keys", - "weight": 182, + "weight": 184, "cookies": false, "type": "", "deprecated": false, @@ -22151,7 +22371,7 @@ "x-appwrite": { "method": "createKey", "group": "keys", - "weight": 181, + "weight": 183, "cookies": false, "type": "", "deprecated": false, @@ -22243,7 +22463,7 @@ "x-appwrite": { "method": "getKey", "group": "keys", - "weight": 183, + "weight": 185, "cookies": false, "type": "", "deprecated": false, @@ -22309,7 +22529,7 @@ "x-appwrite": { "method": "updateKey", "group": "keys", - "weight": 184, + "weight": 186, "cookies": false, "type": "", "deprecated": false, @@ -22404,7 +22624,7 @@ "x-appwrite": { "method": "deleteKey", "group": "keys", - "weight": 185, + "weight": 187, "cookies": false, "type": "", "deprecated": false, @@ -22472,7 +22692,7 @@ "x-appwrite": { "method": "updateOAuth2", "group": "auth", - "weight": 163, + "weight": 165, "cookies": false, "type": "", "deprecated": false, @@ -22610,7 +22830,7 @@ "x-appwrite": { "method": "listPlatforms", "group": "platforms", - "weight": 188, + "weight": 190, "cookies": false, "type": "", "deprecated": false, @@ -22668,7 +22888,7 @@ "x-appwrite": { "method": "createPlatform", "group": "platforms", - "weight": 187, + "weight": 189, "cookies": false, "type": "", "deprecated": false, @@ -22788,7 +23008,7 @@ "x-appwrite": { "method": "getPlatform", "group": "platforms", - "weight": 189, + "weight": 191, "cookies": false, "type": "", "deprecated": false, @@ -22854,7 +23074,7 @@ "x-appwrite": { "method": "updatePlatform", "group": "platforms", - "weight": 190, + "weight": 192, "cookies": false, "type": "", "deprecated": false, @@ -22951,7 +23171,7 @@ "x-appwrite": { "method": "deletePlatform", "group": "platforms", - "weight": 191, + "weight": 193, "cookies": false, "type": "", "deprecated": false, @@ -23019,7 +23239,7 @@ "x-appwrite": { "method": "updateServiceStatus", "group": "projects", - "weight": 159, + "weight": 161, "cookies": false, "type": "", "deprecated": false, @@ -23120,7 +23340,7 @@ "x-appwrite": { "method": "updateServiceStatusAll", "group": "projects", - "weight": 160, + "weight": 162, "cookies": false, "type": "", "deprecated": false, @@ -23198,7 +23418,7 @@ "x-appwrite": { "method": "updateSmtp", "group": "templates", - "weight": 192, + "weight": 194, "cookies": false, "type": "", "deprecated": false, @@ -23327,7 +23547,7 @@ "x-appwrite": { "method": "createSmtpTest", "group": "templates", - "weight": 193, + "weight": 195, "cookies": false, "type": "", "deprecated": false, @@ -23465,7 +23685,7 @@ "x-appwrite": { "method": "updateTeam", "group": "projects", - "weight": 158, + "weight": 160, "cookies": false, "type": "", "deprecated": false, @@ -23541,7 +23761,7 @@ "x-appwrite": { "method": "getEmailTemplate", "group": "templates", - "weight": 195, + "weight": 197, "cookies": false, "type": "", "deprecated": false, @@ -23761,7 +23981,7 @@ "x-appwrite": { "method": "updateEmailTemplate", "group": "templates", - "weight": 197, + "weight": 199, "cookies": false, "type": "", "deprecated": false, @@ -24024,7 +24244,7 @@ "x-appwrite": { "method": "deleteEmailTemplate", "group": "templates", - "weight": 199, + "weight": 201, "cookies": false, "type": "", "deprecated": false, @@ -24244,7 +24464,7 @@ "x-appwrite": { "method": "getSmsTemplate", "group": "templates", - "weight": 194, + "weight": 196, "cookies": false, "type": "", "deprecated": false, @@ -24461,7 +24681,7 @@ "x-appwrite": { "method": "updateSmsTemplate", "group": "templates", - "weight": 196, + "weight": 198, "cookies": false, "type": "", "deprecated": false, @@ -24696,7 +24916,7 @@ "x-appwrite": { "method": "deleteSmsTemplate", "group": "templates", - "weight": 198, + "weight": 200, "cookies": false, "type": "", "deprecated": false, @@ -24913,7 +25133,7 @@ "x-appwrite": { "method": "listWebhooks", "group": "webhooks", - "weight": 176, + "weight": 178, "cookies": false, "type": "", "deprecated": false, @@ -24971,7 +25191,7 @@ "x-appwrite": { "method": "createWebhook", "group": "webhooks", - "weight": 175, + "weight": 177, "cookies": false, "type": "", "deprecated": false, @@ -25089,7 +25309,7 @@ "x-appwrite": { "method": "getWebhook", "group": "webhooks", - "weight": 177, + "weight": 179, "cookies": false, "type": "", "deprecated": false, @@ -25155,7 +25375,7 @@ "x-appwrite": { "method": "updateWebhook", "group": "webhooks", - "weight": 178, + "weight": 180, "cookies": false, "type": "", "deprecated": false, @@ -25276,7 +25496,7 @@ "x-appwrite": { "method": "deleteWebhook", "group": "webhooks", - "weight": 180, + "weight": 182, "cookies": false, "type": "", "deprecated": false, @@ -25344,7 +25564,7 @@ "x-appwrite": { "method": "updateWebhookSignature", "group": "webhooks", - "weight": 179, + "weight": 181, "cookies": false, "type": "", "deprecated": false, @@ -25410,7 +25630,7 @@ "x-appwrite": { "method": "listRules", "group": null, - "weight": 292, + "weight": 294, "cookies": false, "type": "", "deprecated": false, @@ -25483,7 +25703,7 @@ "x-appwrite": { "method": "createAPIRule", "group": null, - "weight": 433, + "weight": 435, "cookies": false, "type": "", "deprecated": false, @@ -25553,7 +25773,7 @@ "x-appwrite": { "method": "createFunctionRule", "group": null, - "weight": 435, + "weight": 437, "cookies": false, "type": "", "deprecated": false, @@ -25636,7 +25856,7 @@ "x-appwrite": { "method": "createRedirectRule", "group": null, - "weight": 436, + "weight": 438, "cookies": false, "type": "", "deprecated": false, @@ -25756,7 +25976,7 @@ "x-appwrite": { "method": "createSiteRule", "group": null, - "weight": 434, + "weight": 436, "cookies": false, "type": "", "deprecated": false, @@ -25837,7 +26057,7 @@ "x-appwrite": { "method": "getRule", "group": null, - "weight": 293, + "weight": 295, "cookies": false, "type": "", "deprecated": false, @@ -25890,7 +26110,7 @@ "x-appwrite": { "method": "deleteRule", "group": null, - "weight": 294, + "weight": 296, "cookies": false, "type": "", "deprecated": false, @@ -25950,7 +26170,7 @@ "x-appwrite": { "method": "updateRuleVerification", "group": null, - "weight": 295, + "weight": 297, "cookies": false, "type": "", "deprecated": false, @@ -26008,7 +26228,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 405, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -26080,7 +26300,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 403, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -26226,6 +26446,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -26251,7 +26472,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -26345,7 +26567,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 408, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -26394,7 +26616,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 431, + "weight": 433, "cookies": false, "type": "", "deprecated": false, @@ -26444,7 +26666,7 @@ "x-appwrite": { "method": "listTemplates", "group": "templates", - "weight": 427, + "weight": 429, "cookies": false, "type": "", "deprecated": false, @@ -26538,7 +26760,7 @@ "x-appwrite": { "method": "getTemplate", "group": "templates", - "weight": 428, + "weight": 430, "cookies": false, "type": "", "deprecated": false, @@ -26596,7 +26818,7 @@ "x-appwrite": { "method": "listUsage", "group": null, - "weight": 429, + "weight": 431, "cookies": false, "type": "", "deprecated": false, @@ -26666,7 +26888,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 404, + "weight": 406, "cookies": false, "type": "", "deprecated": false, @@ -26725,7 +26947,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 406, + "weight": 408, "cookies": false, "type": "", "deprecated": false, @@ -26873,6 +27095,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -26898,7 +27121,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -26985,7 +27209,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 407, + "weight": 409, "cookies": false, "type": "", "deprecated": false, @@ -27046,7 +27270,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 414, + "weight": 416, "cookies": false, "type": "", "deprecated": false, @@ -27123,7 +27347,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 413, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -27203,7 +27427,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 409, + "weight": 411, "cookies": false, "type": "upload", "deprecated": false, @@ -27303,7 +27527,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 417, + "weight": 419, "cookies": false, "type": "", "deprecated": false, @@ -27382,7 +27606,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 410, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -27488,7 +27712,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 411, + "weight": 413, "cookies": false, "type": "", "deprecated": false, @@ -27585,7 +27809,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 412, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -27647,7 +27871,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 415, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -27714,7 +27938,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 416, + "weight": 418, "cookies": false, "type": "location", "deprecated": false, @@ -27800,7 +28024,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 418, + "weight": 420, "cookies": false, "type": "", "deprecated": false, @@ -27867,7 +28091,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 420, + "weight": 422, "cookies": false, "type": "", "deprecated": false, @@ -27938,7 +28162,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 419, + "weight": 421, "cookies": false, "type": "", "deprecated": false, @@ -28002,7 +28226,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 421, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -28069,7 +28293,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 430, + "weight": 432, "cookies": false, "type": "", "deprecated": false, @@ -28147,7 +28371,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 424, + "weight": 426, "cookies": false, "type": "", "deprecated": false, @@ -28206,7 +28430,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 422, + "weight": 424, "cookies": false, "type": "", "deprecated": false, @@ -28296,7 +28520,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 423, + "weight": 425, "cookies": false, "type": "", "deprecated": false, @@ -28363,7 +28587,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 425, + "weight": 427, "cookies": false, "type": "", "deprecated": false, @@ -28455,7 +28679,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 426, + "weight": 428, "cookies": false, "type": "", "deprecated": false, @@ -28522,7 +28746,7 @@ "x-appwrite": { "method": "listBuckets", "group": "buckets", - "weight": 207, + "weight": 209, "cookies": false, "type": "", "deprecated": false, @@ -28594,7 +28818,7 @@ "x-appwrite": { "method": "createBucket", "group": "buckets", - "weight": 206, + "weight": 208, "cookies": false, "type": "", "deprecated": false, @@ -28731,7 +28955,7 @@ "x-appwrite": { "method": "getBucket", "group": "buckets", - "weight": 208, + "weight": 210, "cookies": false, "type": "", "deprecated": false, @@ -28790,7 +29014,7 @@ "x-appwrite": { "method": "updateBucket", "group": "buckets", - "weight": 209, + "weight": 211, "cookies": false, "type": "", "deprecated": false, @@ -28923,7 +29147,7 @@ "x-appwrite": { "method": "deleteBucket", "group": "buckets", - "weight": 210, + "weight": 212, "cookies": false, "type": "", "deprecated": false, @@ -28982,7 +29206,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 212, + "weight": 214, "cookies": false, "type": "", "deprecated": false, @@ -29065,7 +29289,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 211, + "weight": 213, "cookies": false, "type": "upload", "deprecated": false, @@ -29155,7 +29379,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 213, + "weight": 215, "cookies": false, "type": "", "deprecated": false, @@ -29225,7 +29449,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 218, + "weight": 220, "cookies": false, "type": "", "deprecated": false, @@ -29314,7 +29538,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 219, + "weight": 221, "cookies": false, "type": "", "deprecated": false, @@ -29384,7 +29608,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 215, + "weight": 217, "cookies": false, "type": "location", "deprecated": false, @@ -29463,7 +29687,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 214, + "weight": 216, "cookies": false, "type": "location", "deprecated": false, @@ -29627,7 +29851,8 @@ "png", "webp", "heic", - "avif" + "avif", + "gif" ], "x-enum-name": "ImageFormat", "x-enum-keys": [], @@ -29669,7 +29894,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 216, + "weight": 218, "cookies": false, "type": "location", "deprecated": false, @@ -29748,7 +29973,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 220, + "weight": 222, "cookies": false, "type": "", "deprecated": false, @@ -29818,7 +30043,7 @@ "x-appwrite": { "method": "getBucketUsage", "group": null, - "weight": 221, + "weight": 223, "cookies": false, "type": "", "deprecated": false, @@ -29896,7 +30121,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 223, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -29971,7 +30196,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 222, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -30061,7 +30286,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 224, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -30123,7 +30348,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 226, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -30198,7 +30423,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 228, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -30260,7 +30485,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 235, + "weight": 237, "cookies": false, "type": "", "deprecated": false, @@ -30330,7 +30555,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 230, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -30413,7 +30638,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 229, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -30526,7 +30751,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 231, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -30596,7 +30821,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 232, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -30682,7 +30907,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 234, + "weight": 236, "cookies": false, "type": "", "deprecated": false, @@ -30754,7 +30979,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 233, + "weight": 235, "cookies": false, "type": "", "deprecated": false, @@ -30847,7 +31072,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 225, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -30907,7 +31132,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 227, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -30985,7 +31210,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 439, + "weight": 441, "cookies": false, "type": "", "deprecated": false, @@ -31065,7 +31290,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 437, + "weight": 439, "cookies": false, "type": "", "deprecated": false, @@ -31149,7 +31374,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 438, + "weight": 440, "cookies": false, "type": "", "deprecated": false, @@ -31209,7 +31434,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 440, + "weight": 442, "cookies": false, "type": "", "deprecated": false, @@ -31280,7 +31505,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 441, + "weight": 443, "cookies": false, "type": "", "deprecated": false, @@ -31340,7 +31565,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 245, + "weight": 247, "cookies": false, "type": "", "deprecated": false, @@ -31412,7 +31637,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 236, + "weight": 238, "cookies": false, "type": "", "deprecated": false, @@ -31507,7 +31732,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 239, + "weight": 241, "cookies": false, "type": "", "deprecated": false, @@ -31598,7 +31823,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 237, + "weight": 239, "cookies": false, "type": "", "deprecated": false, @@ -31687,7 +31912,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 253, + "weight": 255, "cookies": false, "type": "", "deprecated": false, @@ -31756,7 +31981,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 276, + "weight": 278, "cookies": false, "type": "", "deprecated": false, @@ -31817,7 +32042,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 238, + "weight": 240, "cookies": false, "type": "", "deprecated": false, @@ -31908,7 +32133,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 241, + "weight": 243, "cookies": false, "type": "", "deprecated": false, @@ -31999,7 +32224,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 242, + "weight": 244, "cookies": false, "type": "", "deprecated": false, @@ -32125,7 +32350,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 243, + "weight": 245, "cookies": false, "type": "", "deprecated": false, @@ -32237,7 +32462,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 240, + "weight": 242, "cookies": false, "type": "", "deprecated": false, @@ -32347,7 +32572,7 @@ "x-appwrite": { "method": "getUsage", "group": null, - "weight": 278, + "weight": 280, "cookies": false, "type": "", "deprecated": false, @@ -32417,7 +32642,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 246, + "weight": 248, "cookies": false, "type": "", "deprecated": false, @@ -32471,7 +32696,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 274, + "weight": 276, "cookies": false, "type": "", "deprecated": false, @@ -32532,7 +32757,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 259, + "weight": 261, "cookies": false, "type": "", "deprecated": false, @@ -32611,7 +32836,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 277, + "weight": 279, "cookies": false, "type": "", "deprecated": false, @@ -32693,7 +32918,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 255, + "weight": 257, "cookies": false, "type": "", "deprecated": false, @@ -32773,7 +32998,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 251, + "weight": 253, "cookies": false, "type": "", "deprecated": false, @@ -32844,7 +33069,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 250, + "weight": 252, "cookies": false, "type": "", "deprecated": false, @@ -32926,7 +33151,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 264, + "weight": 266, "cookies": false, "type": "", "deprecated": false, @@ -33000,7 +33225,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 269, + "weight": 271, "cookies": false, "type": "", "deprecated": false, @@ -33072,7 +33297,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 265, + "weight": 267, "cookies": false, "type": "", "deprecated": false, @@ -33131,7 +33356,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 266, + "weight": 268, "cookies": false, "type": "", "deprecated": false, @@ -33190,7 +33415,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 268, + "weight": 270, "cookies": false, "type": "", "deprecated": false, @@ -33249,7 +33474,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 267, + "weight": 269, "cookies": false, "type": "", "deprecated": false, @@ -33310,7 +33535,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 257, + "weight": 259, "cookies": false, "type": "", "deprecated": false, @@ -33389,7 +33614,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 258, + "weight": 260, "cookies": false, "type": "", "deprecated": false, @@ -33468,7 +33693,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 260, + "weight": 262, "cookies": false, "type": "", "deprecated": false, @@ -33545,7 +33770,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 247, + "weight": 249, "cookies": false, "type": "", "deprecated": false, @@ -33604,7 +33829,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 262, + "weight": 264, "cookies": false, "type": "", "deprecated": false, @@ -33681,7 +33906,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 249, + "weight": 251, "cookies": false, "type": "", "deprecated": false, @@ -33740,7 +33965,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 270, + "weight": 272, "cookies": false, "type": "", "deprecated": false, @@ -33794,7 +34019,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 273, + "weight": 275, "cookies": false, "type": "", "deprecated": false, @@ -33850,7 +34075,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 272, + "weight": 274, "cookies": false, "type": "", "deprecated": false, @@ -33919,7 +34144,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 254, + "weight": 256, "cookies": false, "type": "", "deprecated": false, @@ -33996,7 +34221,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 252, + "weight": 254, "cookies": false, "type": "", "deprecated": false, @@ -34032,7 +34257,7 @@ }, { "name": "queries", - "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, email, phone, status, passwordUpdate, registration, emailVerification, phoneVerification, labels", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, providerId, identifier, providerType", "required": false, "type": "array", "collectionFormat": "multi", @@ -34068,7 +34293,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 244, + "weight": 246, "cookies": false, "type": "", "deprecated": false, @@ -34179,7 +34404,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 248, + "weight": 250, "cookies": false, "type": "", "deprecated": false, @@ -34247,7 +34472,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 263, + "weight": 265, "cookies": false, "type": "", "deprecated": false, @@ -34337,7 +34562,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 275, + "weight": 277, "cookies": false, "type": "", "deprecated": false, @@ -34407,7 +34632,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 271, + "weight": 273, "cookies": false, "type": "", "deprecated": false, @@ -34489,7 +34714,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 261, + "weight": 263, "cookies": false, "type": "", "deprecated": false, @@ -34568,7 +34793,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 256, + "weight": 258, "cookies": false, "type": "", "deprecated": false, @@ -34647,7 +34872,7 @@ "x-appwrite": { "method": "createRepositoryDetection", "group": "repositories", - "weight": 282, + "weight": 284, "cookies": false, "type": "", "deprecated": false, @@ -34742,7 +34967,7 @@ "x-appwrite": { "method": "listRepositories", "group": "repositories", - "weight": 283, + "weight": 285, "cookies": false, "type": "", "deprecated": false, @@ -34823,7 +35048,7 @@ "x-appwrite": { "method": "createRepository", "group": "repositories", - "weight": 284, + "weight": 286, "cookies": false, "type": "", "deprecated": false, @@ -34906,7 +35131,7 @@ "x-appwrite": { "method": "getRepository", "group": "repositories", - "weight": 285, + "weight": 287, "cookies": false, "type": "", "deprecated": false, @@ -34972,7 +35197,7 @@ "x-appwrite": { "method": "listRepositoryBranches", "group": "repositories", - "weight": 286, + "weight": 288, "cookies": false, "type": "", "deprecated": false, @@ -35038,7 +35263,7 @@ "x-appwrite": { "method": "getRepositoryContents", "group": "repositories", - "weight": 281, + "weight": 283, "cookies": false, "type": "", "deprecated": false, @@ -35112,7 +35337,7 @@ "x-appwrite": { "method": "updateExternalDeployments", "group": "repositories", - "weight": 291, + "weight": 293, "cookies": false, "type": "", "deprecated": false, @@ -35196,7 +35421,7 @@ "x-appwrite": { "method": "listInstallations", "group": "installations", - "weight": 288, + "weight": 290, "cookies": false, "type": "", "deprecated": false, @@ -35267,7 +35492,7 @@ "x-appwrite": { "method": "getInstallation", "group": "installations", - "weight": 289, + "weight": 291, "cookies": false, "type": "", "deprecated": false, @@ -35320,7 +35545,7 @@ "x-appwrite": { "method": "deleteInstallation", "group": "installations", - "weight": 290, + "weight": 292, "cookies": false, "type": "", "deprecated": false, @@ -36842,6 +37067,12 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "default", "x-nullable": true + }, + "encrypt": { + "type": "boolean", + "description": "Defines whether this attribute is encrypted or not.", + "x-example": false, + "x-nullable": true } }, "required": [ @@ -37593,6 +37824,12 @@ "description": "Document ID.", "x-example": "5e5ea5c16897e" }, + "$sequence": { + "type": "integer", + "description": "Document automatically incrementing ID.", + "x-example": 1, + "format": "int32" + }, "$collectionId": { "type": "string", "description": "Collection ID.", @@ -37627,6 +37864,7 @@ "additionalProperties": true, "required": [ "$id", + "$sequence", "$collectionId", "$databaseId", "$createdAt", diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 083290bcc0..cdadac68e3 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -7769,7 +7769,7 @@ "x-appwrite": { "method": "upsertDocuments", "group": "documents", - "weight": 116, + "weight": 118, "cookies": false, "type": "", "deprecated": false, @@ -7858,7 +7858,7 @@ "x-appwrite": { "method": "updateDocuments", "group": "documents", - "weight": 115, + "weight": 117, "cookies": false, "type": "", "deprecated": false, @@ -7950,7 +7950,7 @@ "x-appwrite": { "method": "deleteDocuments", "group": "documents", - "weight": 118, + "weight": 120, "cookies": false, "type": "", "deprecated": false, @@ -8334,7 +8334,7 @@ "x-appwrite": { "method": "deleteDocument", "group": "documents", - "weight": 117, + "weight": 119, "cookies": false, "type": "", "deprecated": false, @@ -8391,6 +8391,226 @@ ] } }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/decrement": { + "patch": { + "summary": "Decrement document attribute", + "operationId": "databasesDecrementDocumentAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Decrement a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "decrementDocumentAttribute", + "group": "documents", + "weight": 116, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/decrement-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/decrement-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to decrement the attribute by. The value must be a number.", + "default": 1, + "x-example": null + }, + "min": { + "type": "mixed", + "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", + "default": null, + "x-example": null + } + } + } + } + ] + } + }, + "\/databases\/{databaseId}\/collections\/{collectionId}\/documents\/{documentId}\/{attribute}\/increment": { + "patch": { + "summary": "Increment document attribute", + "operationId": "databasesIncrementDocumentAttribute", + "consumes": [ + "application\/json" + ], + "produces": [ + "application\/json" + ], + "tags": [ + "databases" + ], + "description": "Increment a specific attribute of a document by a given value.", + "responses": { + "200": { + "description": "Document", + "schema": { + "$ref": "#\/definitions\/document" + } + } + }, + "x-appwrite": { + "method": "incrementDocumentAttribute", + "group": "documents", + "weight": 115, + "cookies": false, + "type": "", + "deprecated": false, + "demo": "databases\/increment-document-attribute.md", + "edit": "https:\/\/github.com\/appwrite\/appwrite\/edit\/master\/docs\/references\/databases\/increment-document-attribute.md", + "rate-limit": 120, + "rate-time": 60, + "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", + "scope": "documents.write", + "platforms": [ + "server", + "client", + "server" + ], + "packaging": false, + "auth": { + "Project": [], + "Key": [] + } + }, + "security": [ + { + "Project": [], + "Key": [], + "Session": [], + "JWT": [] + } + ], + "parameters": [ + { + "name": "databaseId", + "description": "Database ID.", + "required": true, + "type": "string", + "x-example": "<DATABASE_ID>", + "in": "path" + }, + { + "name": "collectionId", + "description": "Collection ID.", + "required": true, + "type": "string", + "x-example": "<COLLECTION_ID>", + "in": "path" + }, + { + "name": "documentId", + "description": "Document ID.", + "required": true, + "type": "string", + "x-example": "<DOCUMENT_ID>", + "in": "path" + }, + { + "name": "attribute", + "description": "Attribute key.", + "required": true, + "type": "string", + "in": "path" + }, + { + "name": "payload", + "in": "body", + "schema": { + "type": "object", + "properties": { + "value": { + "type": "mixed", + "description": "Value to increment the attribute by. The value must be a number.", + "default": 1, + "x-example": null + }, + "max": { + "type": "mixed", + "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", + "default": null, + "x-example": null + } + } + } + } + ] + } + }, "\/databases\/{databaseId}\/collections\/{collectionId}\/indexes": { "get": { "summary": "List indexes", @@ -8767,7 +8987,7 @@ "x-appwrite": { "method": "list", "group": "functions", - "weight": 376, + "weight": 378, "cookies": false, "type": "", "deprecated": false, @@ -8840,7 +9060,7 @@ "x-appwrite": { "method": "create", "group": "functions", - "weight": 373, + "weight": 375, "cookies": false, "type": "", "deprecated": false, @@ -8927,6 +9147,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -8952,7 +9173,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -9090,7 +9312,7 @@ "x-appwrite": { "method": "listRuntimes", "group": "runtimes", - "weight": 378, + "weight": 380, "cookies": false, "type": "", "deprecated": false, @@ -9140,7 +9362,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "runtimes", - "weight": 379, + "weight": 381, "cookies": false, "type": "", "deprecated": false, @@ -9191,7 +9413,7 @@ "x-appwrite": { "method": "get", "group": "functions", - "weight": 374, + "weight": 376, "cookies": false, "type": "", "deprecated": false, @@ -9251,7 +9473,7 @@ "x-appwrite": { "method": "update", "group": "functions", - "weight": 375, + "weight": 377, "cookies": false, "type": "", "deprecated": false, @@ -9340,6 +9562,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -9365,7 +9588,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -9497,7 +9721,7 @@ "x-appwrite": { "method": "delete", "group": "functions", - "weight": 377, + "weight": 379, "cookies": false, "type": "", "deprecated": false, @@ -9559,7 +9783,7 @@ "x-appwrite": { "method": "updateFunctionDeployment", "group": "functions", - "weight": 382, + "weight": 384, "cookies": false, "type": "", "deprecated": false, @@ -9637,7 +9861,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 383, + "weight": 385, "cookies": false, "type": "", "deprecated": false, @@ -9718,7 +9942,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 380, + "weight": 382, "cookies": false, "type": "upload", "deprecated": false, @@ -9811,7 +10035,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 388, + "weight": 390, "cookies": false, "type": "", "deprecated": false, @@ -9897,7 +10121,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 385, + "weight": 387, "cookies": false, "type": "", "deprecated": false, @@ -10004,7 +10228,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 386, + "weight": 388, "cookies": false, "type": "", "deprecated": false, @@ -10101,7 +10325,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 381, + "weight": 383, "cookies": false, "type": "", "deprecated": false, @@ -10164,7 +10388,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 384, + "weight": 386, "cookies": false, "type": "", "deprecated": false, @@ -10232,7 +10456,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 387, + "weight": 389, "cookies": false, "type": "location", "deprecated": false, @@ -10319,7 +10543,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 389, + "weight": 391, "cookies": false, "type": "", "deprecated": false, @@ -10387,7 +10611,7 @@ "x-appwrite": { "method": "listExecutions", "group": "executions", - "weight": 392, + "weight": 394, "cookies": false, "type": "", "deprecated": false, @@ -10463,7 +10687,7 @@ "x-appwrite": { "method": "createExecution", "group": "executions", - "weight": 390, + "weight": 392, "cookies": false, "type": "", "deprecated": false, @@ -10582,7 +10806,7 @@ "x-appwrite": { "method": "getExecution", "group": "executions", - "weight": 391, + "weight": 393, "cookies": false, "type": "", "deprecated": false, @@ -10649,7 +10873,7 @@ "x-appwrite": { "method": "deleteExecution", "group": "executions", - "weight": 393, + "weight": 395, "cookies": false, "type": "", "deprecated": false, @@ -10717,7 +10941,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 398, + "weight": 400, "cookies": false, "type": "", "deprecated": false, @@ -10777,7 +11001,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 396, + "weight": 398, "cookies": false, "type": "", "deprecated": false, @@ -10868,7 +11092,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 397, + "weight": 399, "cookies": false, "type": "", "deprecated": false, @@ -10936,7 +11160,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 399, + "weight": 401, "cookies": false, "type": "", "deprecated": false, @@ -11029,7 +11253,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 400, + "weight": 402, "cookies": false, "type": "", "deprecated": false, @@ -11099,7 +11323,7 @@ "x-appwrite": { "method": "query", "group": "graphql", - "weight": 306, + "weight": 308, "cookies": false, "type": "graphql", "deprecated": false, @@ -11175,7 +11399,7 @@ "x-appwrite": { "method": "mutation", "group": "graphql", - "weight": 305, + "weight": 307, "cookies": false, "type": "graphql", "deprecated": false, @@ -11249,7 +11473,7 @@ "x-appwrite": { "method": "get", "group": "health", - "weight": 130, + "weight": 132, "cookies": false, "type": "", "deprecated": false, @@ -11299,7 +11523,7 @@ "x-appwrite": { "method": "getAntivirus", "group": "health", - "weight": 151, + "weight": 153, "cookies": false, "type": "", "deprecated": false, @@ -11349,7 +11573,7 @@ "x-appwrite": { "method": "getCache", "group": "health", - "weight": 133, + "weight": 135, "cookies": false, "type": "", "deprecated": false, @@ -11399,7 +11623,7 @@ "x-appwrite": { "method": "getCertificate", "group": "health", - "weight": 138, + "weight": 140, "cookies": false, "type": "", "deprecated": false, @@ -11458,7 +11682,7 @@ "x-appwrite": { "method": "getDB", "group": "health", - "weight": 132, + "weight": 134, "cookies": false, "type": "", "deprecated": false, @@ -11508,7 +11732,7 @@ "x-appwrite": { "method": "getPubSub", "group": "health", - "weight": 134, + "weight": 136, "cookies": false, "type": "", "deprecated": false, @@ -11558,7 +11782,7 @@ "x-appwrite": { "method": "getQueueBuilds", "group": "queue", - "weight": 140, + "weight": 142, "cookies": false, "type": "", "deprecated": false, @@ -11619,7 +11843,7 @@ "x-appwrite": { "method": "getQueueCertificates", "group": "queue", - "weight": 139, + "weight": 141, "cookies": false, "type": "", "deprecated": false, @@ -11680,7 +11904,7 @@ "x-appwrite": { "method": "getQueueDatabases", "group": "queue", - "weight": 141, + "weight": 143, "cookies": false, "type": "", "deprecated": false, @@ -11750,7 +11974,7 @@ "x-appwrite": { "method": "getQueueDeletes", "group": "queue", - "weight": 142, + "weight": 144, "cookies": false, "type": "", "deprecated": false, @@ -11811,7 +12035,7 @@ "x-appwrite": { "method": "getFailedJobs", "group": "queue", - "weight": 152, + "weight": 154, "cookies": false, "type": "", "deprecated": false, @@ -11896,7 +12120,7 @@ "x-appwrite": { "method": "getQueueFunctions", "group": "queue", - "weight": 146, + "weight": 148, "cookies": false, "type": "", "deprecated": false, @@ -11957,7 +12181,7 @@ "x-appwrite": { "method": "getQueueLogs", "group": "queue", - "weight": 137, + "weight": 139, "cookies": false, "type": "", "deprecated": false, @@ -12018,7 +12242,7 @@ "x-appwrite": { "method": "getQueueMails", "group": "queue", - "weight": 143, + "weight": 145, "cookies": false, "type": "", "deprecated": false, @@ -12079,7 +12303,7 @@ "x-appwrite": { "method": "getQueueMessaging", "group": "queue", - "weight": 144, + "weight": 146, "cookies": false, "type": "", "deprecated": false, @@ -12140,7 +12364,7 @@ "x-appwrite": { "method": "getQueueMigrations", "group": "queue", - "weight": 145, + "weight": 147, "cookies": false, "type": "", "deprecated": false, @@ -12201,7 +12425,7 @@ "x-appwrite": { "method": "getQueueStatsResources", "group": "queue", - "weight": 147, + "weight": 149, "cookies": false, "type": "", "deprecated": false, @@ -12262,7 +12486,7 @@ "x-appwrite": { "method": "getQueueUsage", "group": "queue", - "weight": 148, + "weight": 150, "cookies": false, "type": "", "deprecated": false, @@ -12323,7 +12547,7 @@ "x-appwrite": { "method": "getQueueWebhooks", "group": "queue", - "weight": 136, + "weight": 138, "cookies": false, "type": "", "deprecated": false, @@ -12384,7 +12608,7 @@ "x-appwrite": { "method": "getStorage", "group": "storage", - "weight": 150, + "weight": 152, "cookies": false, "type": "", "deprecated": false, @@ -12434,7 +12658,7 @@ "x-appwrite": { "method": "getStorageLocal", "group": "storage", - "weight": 149, + "weight": 151, "cookies": false, "type": "", "deprecated": false, @@ -12484,7 +12708,7 @@ "x-appwrite": { "method": "getTime", "group": "health", - "weight": 135, + "weight": 137, "cookies": false, "type": "", "deprecated": false, @@ -12534,7 +12758,7 @@ "x-appwrite": { "method": "get", "group": null, - "weight": 122, + "weight": 124, "cookies": false, "type": "", "deprecated": false, @@ -12588,7 +12812,7 @@ "x-appwrite": { "method": "listCodes", "group": null, - "weight": 123, + "weight": 125, "cookies": false, "type": "", "deprecated": false, @@ -12642,7 +12866,7 @@ "x-appwrite": { "method": "listContinents", "group": null, - "weight": 127, + "weight": 129, "cookies": false, "type": "", "deprecated": false, @@ -12696,7 +12920,7 @@ "x-appwrite": { "method": "listCountries", "group": null, - "weight": 124, + "weight": 126, "cookies": false, "type": "", "deprecated": false, @@ -12750,7 +12974,7 @@ "x-appwrite": { "method": "listCountriesEU", "group": null, - "weight": 125, + "weight": 127, "cookies": false, "type": "", "deprecated": false, @@ -12804,7 +13028,7 @@ "x-appwrite": { "method": "listCountriesPhones", "group": null, - "weight": 126, + "weight": 128, "cookies": false, "type": "", "deprecated": false, @@ -12858,7 +13082,7 @@ "x-appwrite": { "method": "listCurrencies", "group": null, - "weight": 128, + "weight": 130, "cookies": false, "type": "", "deprecated": false, @@ -12912,7 +13136,7 @@ "x-appwrite": { "method": "listLanguages", "group": null, - "weight": 129, + "weight": 131, "cookies": false, "type": "", "deprecated": false, @@ -12966,7 +13190,7 @@ "x-appwrite": { "method": "listMessages", "group": "messages", - "weight": 360, + "weight": 362, "cookies": false, "type": "", "deprecated": false, @@ -13042,7 +13266,7 @@ "x-appwrite": { "method": "createEmail", "group": "messages", - "weight": 357, + "weight": 359, "cookies": false, "type": "", "deprecated": false, @@ -13201,7 +13425,7 @@ "x-appwrite": { "method": "updateEmail", "group": "messages", - "weight": 364, + "weight": 366, "cookies": false, "type": "", "deprecated": false, @@ -13357,7 +13581,7 @@ "x-appwrite": { "method": "createPush", "group": "messages", - "weight": 359, + "weight": 361, "cookies": false, "type": "", "deprecated": false, @@ -13553,7 +13777,7 @@ "x-appwrite": { "method": "updatePush", "group": "messages", - "weight": 366, + "weight": 368, "cookies": false, "type": "", "deprecated": false, @@ -13748,7 +13972,7 @@ "x-appwrite": { "method": "createSms", "group": "messages", - "weight": 358, + "weight": 360, "cookies": false, "type": "", "deprecated": false, @@ -13867,7 +14091,7 @@ "x-appwrite": { "method": "updateSms", "group": "messages", - "weight": 365, + "weight": 367, "cookies": false, "type": "", "deprecated": false, @@ -13982,7 +14206,7 @@ "x-appwrite": { "method": "getMessage", "group": "messages", - "weight": 363, + "weight": 365, "cookies": false, "type": "", "deprecated": false, @@ -14038,7 +14262,7 @@ "x-appwrite": { "method": "delete", "group": "messages", - "weight": 367, + "weight": 369, "cookies": false, "type": "", "deprecated": false, @@ -14099,7 +14323,7 @@ "x-appwrite": { "method": "listMessageLogs", "group": "logs", - "weight": 361, + "weight": 363, "cookies": false, "type": "", "deprecated": false, @@ -14172,7 +14396,7 @@ "x-appwrite": { "method": "listTargets", "group": "messages", - "weight": 362, + "weight": 364, "cookies": false, "type": "", "deprecated": false, @@ -14245,7 +14469,7 @@ "x-appwrite": { "method": "listProviders", "group": "providers", - "weight": 332, + "weight": 334, "cookies": false, "type": "", "deprecated": false, @@ -14321,7 +14545,7 @@ "x-appwrite": { "method": "createApnsProvider", "group": "providers", - "weight": 331, + "weight": 333, "cookies": false, "type": "", "deprecated": false, @@ -14437,7 +14661,7 @@ "x-appwrite": { "method": "updateApnsProvider", "group": "providers", - "weight": 344, + "weight": 346, "cookies": false, "type": "", "deprecated": false, @@ -14551,7 +14775,7 @@ "x-appwrite": { "method": "createFcmProvider", "group": "providers", - "weight": 330, + "weight": 332, "cookies": false, "type": "", "deprecated": false, @@ -14643,7 +14867,7 @@ "x-appwrite": { "method": "updateFcmProvider", "group": "providers", - "weight": 343, + "weight": 345, "cookies": false, "type": "", "deprecated": false, @@ -14733,7 +14957,7 @@ "x-appwrite": { "method": "createMailgunProvider", "group": "providers", - "weight": 322, + "weight": 324, "cookies": false, "type": "", "deprecated": false, @@ -14861,7 +15085,7 @@ "x-appwrite": { "method": "updateMailgunProvider", "group": "providers", - "weight": 335, + "weight": 337, "cookies": false, "type": "", "deprecated": false, @@ -14987,7 +15211,7 @@ "x-appwrite": { "method": "createMsg91Provider", "group": "providers", - "weight": 325, + "weight": 327, "cookies": false, "type": "", "deprecated": false, @@ -15091,7 +15315,7 @@ "x-appwrite": { "method": "updateMsg91Provider", "group": "providers", - "weight": 338, + "weight": 340, "cookies": false, "type": "", "deprecated": false, @@ -15193,7 +15417,7 @@ "x-appwrite": { "method": "createSendgridProvider", "group": "providers", - "weight": 323, + "weight": 325, "cookies": false, "type": "", "deprecated": false, @@ -15309,7 +15533,7 @@ "x-appwrite": { "method": "updateSendgridProvider", "group": "providers", - "weight": 336, + "weight": 338, "cookies": false, "type": "", "deprecated": false, @@ -15423,7 +15647,7 @@ "x-appwrite": { "method": "createSmtpProvider", "group": "providers", - "weight": 324, + "weight": 326, "cookies": false, "type": "", "deprecated": false, @@ -15583,7 +15807,7 @@ "x-appwrite": { "method": "updateSmtpProvider", "group": "providers", - "weight": 337, + "weight": 339, "cookies": false, "type": "", "deprecated": false, @@ -15740,7 +15964,7 @@ "x-appwrite": { "method": "createTelesignProvider", "group": "providers", - "weight": 326, + "weight": 328, "cookies": false, "type": "", "deprecated": false, @@ -15844,7 +16068,7 @@ "x-appwrite": { "method": "updateTelesignProvider", "group": "providers", - "weight": 339, + "weight": 341, "cookies": false, "type": "", "deprecated": false, @@ -15946,7 +16170,7 @@ "x-appwrite": { "method": "createTextmagicProvider", "group": "providers", - "weight": 327, + "weight": 329, "cookies": false, "type": "", "deprecated": false, @@ -16050,7 +16274,7 @@ "x-appwrite": { "method": "updateTextmagicProvider", "group": "providers", - "weight": 340, + "weight": 342, "cookies": false, "type": "", "deprecated": false, @@ -16152,7 +16376,7 @@ "x-appwrite": { "method": "createTwilioProvider", "group": "providers", - "weight": 328, + "weight": 330, "cookies": false, "type": "", "deprecated": false, @@ -16256,7 +16480,7 @@ "x-appwrite": { "method": "updateTwilioProvider", "group": "providers", - "weight": 341, + "weight": 343, "cookies": false, "type": "", "deprecated": false, @@ -16358,7 +16582,7 @@ "x-appwrite": { "method": "createVonageProvider", "group": "providers", - "weight": 329, + "weight": 331, "cookies": false, "type": "", "deprecated": false, @@ -16462,7 +16686,7 @@ "x-appwrite": { "method": "updateVonageProvider", "group": "providers", - "weight": 342, + "weight": 344, "cookies": false, "type": "", "deprecated": false, @@ -16562,7 +16786,7 @@ "x-appwrite": { "method": "getProvider", "group": "providers", - "weight": 334, + "weight": 336, "cookies": false, "type": "", "deprecated": false, @@ -16618,7 +16842,7 @@ "x-appwrite": { "method": "deleteProvider", "group": "providers", - "weight": 345, + "weight": 347, "cookies": false, "type": "", "deprecated": false, @@ -16679,7 +16903,7 @@ "x-appwrite": { "method": "listProviderLogs", "group": "providers", - "weight": 333, + "weight": 335, "cookies": false, "type": "", "deprecated": false, @@ -16752,7 +16976,7 @@ "x-appwrite": { "method": "listSubscriberLogs", "group": "subscribers", - "weight": 354, + "weight": 356, "cookies": false, "type": "", "deprecated": false, @@ -16825,7 +17049,7 @@ "x-appwrite": { "method": "listTopics", "group": "topics", - "weight": 347, + "weight": 349, "cookies": false, "type": "", "deprecated": false, @@ -16899,7 +17123,7 @@ "x-appwrite": { "method": "createTopic", "group": "topics", - "weight": 346, + "weight": 348, "cookies": false, "type": "", "deprecated": false, @@ -16988,7 +17212,7 @@ "x-appwrite": { "method": "getTopic", "group": "topics", - "weight": 349, + "weight": 351, "cookies": false, "type": "", "deprecated": false, @@ -17049,7 +17273,7 @@ "x-appwrite": { "method": "updateTopic", "group": "topics", - "weight": 350, + "weight": 352, "cookies": false, "type": "", "deprecated": false, @@ -17129,7 +17353,7 @@ "x-appwrite": { "method": "deleteTopic", "group": "topics", - "weight": 351, + "weight": 353, "cookies": false, "type": "", "deprecated": false, @@ -17190,7 +17414,7 @@ "x-appwrite": { "method": "listTopicLogs", "group": "topics", - "weight": 348, + "weight": 350, "cookies": false, "type": "", "deprecated": false, @@ -17263,7 +17487,7 @@ "x-appwrite": { "method": "listSubscribers", "group": "subscribers", - "weight": 353, + "weight": 355, "cookies": false, "type": "", "deprecated": false, @@ -17345,7 +17569,7 @@ "x-appwrite": { "method": "createSubscriber", "group": "subscribers", - "weight": 352, + "weight": 354, "cookies": false, "type": "", "deprecated": false, @@ -17435,7 +17659,7 @@ "x-appwrite": { "method": "getSubscriber", "group": "subscribers", - "weight": 355, + "weight": 357, "cookies": false, "type": "", "deprecated": false, @@ -17499,7 +17723,7 @@ "x-appwrite": { "method": "deleteSubscriber", "group": "subscribers", - "weight": 356, + "weight": 358, "cookies": false, "type": "", "deprecated": false, @@ -17572,7 +17796,7 @@ "x-appwrite": { "method": "list", "group": "sites", - "weight": 405, + "weight": 407, "cookies": false, "type": "", "deprecated": false, @@ -17645,7 +17869,7 @@ "x-appwrite": { "method": "create", "group": "sites", - "weight": 403, + "weight": 405, "cookies": false, "type": "", "deprecated": false, @@ -17792,6 +18016,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -17817,7 +18042,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -17911,7 +18137,7 @@ "x-appwrite": { "method": "listFrameworks", "group": "frameworks", - "weight": 408, + "weight": 410, "cookies": false, "type": "", "deprecated": false, @@ -17961,7 +18187,7 @@ "x-appwrite": { "method": "listSpecifications", "group": "frameworks", - "weight": 431, + "weight": 433, "cookies": false, "type": "", "deprecated": false, @@ -18012,7 +18238,7 @@ "x-appwrite": { "method": "get", "group": "sites", - "weight": 404, + "weight": 406, "cookies": false, "type": "", "deprecated": false, @@ -18072,7 +18298,7 @@ "x-appwrite": { "method": "update", "group": "sites", - "weight": 406, + "weight": 408, "cookies": false, "type": "", "deprecated": false, @@ -18221,6 +18447,7 @@ "dart-3.1", "dart-3.3", "dart-3.5", + "dart-3.8", "dotnet-6.0", "dotnet-7.0", "dotnet-8.0", @@ -18246,7 +18473,8 @@ "static-1", "flutter-3.24", "flutter-3.27", - "flutter-3.29" + "flutter-3.29", + "flutter-3.32" ], "x-enum-name": null, "x-enum-keys": [] @@ -18333,7 +18561,7 @@ "x-appwrite": { "method": "delete", "group": "sites", - "weight": 407, + "weight": 409, "cookies": false, "type": "", "deprecated": false, @@ -18395,7 +18623,7 @@ "x-appwrite": { "method": "updateSiteDeployment", "group": "sites", - "weight": 414, + "weight": 416, "cookies": false, "type": "", "deprecated": false, @@ -18473,7 +18701,7 @@ "x-appwrite": { "method": "listDeployments", "group": "deployments", - "weight": 413, + "weight": 415, "cookies": false, "type": "", "deprecated": false, @@ -18554,7 +18782,7 @@ "x-appwrite": { "method": "createDeployment", "group": "deployments", - "weight": 409, + "weight": 411, "cookies": false, "type": "upload", "deprecated": false, @@ -18655,7 +18883,7 @@ "x-appwrite": { "method": "createDuplicateDeployment", "group": "deployments", - "weight": 417, + "weight": 419, "cookies": false, "type": "", "deprecated": false, @@ -18735,7 +18963,7 @@ "x-appwrite": { "method": "createTemplateDeployment", "group": "deployments", - "weight": 410, + "weight": 412, "cookies": false, "type": "", "deprecated": false, @@ -18842,7 +19070,7 @@ "x-appwrite": { "method": "createVcsDeployment", "group": "deployments", - "weight": 411, + "weight": 413, "cookies": false, "type": "", "deprecated": false, @@ -18940,7 +19168,7 @@ "x-appwrite": { "method": "getDeployment", "group": "deployments", - "weight": 412, + "weight": 414, "cookies": false, "type": "", "deprecated": false, @@ -19003,7 +19231,7 @@ "x-appwrite": { "method": "deleteDeployment", "group": "deployments", - "weight": 415, + "weight": 417, "cookies": false, "type": "", "deprecated": false, @@ -19071,7 +19299,7 @@ "x-appwrite": { "method": "getDeploymentDownload", "group": "deployments", - "weight": 416, + "weight": 418, "cookies": false, "type": "location", "deprecated": false, @@ -19158,7 +19386,7 @@ "x-appwrite": { "method": "updateDeploymentStatus", "group": "deployments", - "weight": 418, + "weight": 420, "cookies": false, "type": "", "deprecated": false, @@ -19226,7 +19454,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 420, + "weight": 422, "cookies": false, "type": "", "deprecated": false, @@ -19298,7 +19526,7 @@ "x-appwrite": { "method": "getLog", "group": "logs", - "weight": 419, + "weight": 421, "cookies": false, "type": "", "deprecated": false, @@ -19363,7 +19591,7 @@ "x-appwrite": { "method": "deleteLog", "group": "logs", - "weight": 421, + "weight": 423, "cookies": false, "type": "", "deprecated": false, @@ -19431,7 +19659,7 @@ "x-appwrite": { "method": "listVariables", "group": "variables", - "weight": 424, + "weight": 426, "cookies": false, "type": "", "deprecated": false, @@ -19491,7 +19719,7 @@ "x-appwrite": { "method": "createVariable", "group": "variables", - "weight": 422, + "weight": 424, "cookies": false, "type": "", "deprecated": false, @@ -19582,7 +19810,7 @@ "x-appwrite": { "method": "getVariable", "group": "variables", - "weight": 423, + "weight": 425, "cookies": false, "type": "", "deprecated": false, @@ -19650,7 +19878,7 @@ "x-appwrite": { "method": "updateVariable", "group": "variables", - "weight": 425, + "weight": 427, "cookies": false, "type": "", "deprecated": false, @@ -19743,7 +19971,7 @@ "x-appwrite": { "method": "deleteVariable", "group": "variables", - "weight": 426, + "weight": 428, "cookies": false, "type": "", "deprecated": false, @@ -19811,7 +20039,7 @@ "x-appwrite": { "method": "listBuckets", "group": "buckets", - "weight": 207, + "weight": 209, "cookies": false, "type": "", "deprecated": false, @@ -19884,7 +20112,7 @@ "x-appwrite": { "method": "createBucket", "group": "buckets", - "weight": 206, + "weight": 208, "cookies": false, "type": "", "deprecated": false, @@ -20022,7 +20250,7 @@ "x-appwrite": { "method": "getBucket", "group": "buckets", - "weight": 208, + "weight": 210, "cookies": false, "type": "", "deprecated": false, @@ -20082,7 +20310,7 @@ "x-appwrite": { "method": "updateBucket", "group": "buckets", - "weight": 209, + "weight": 211, "cookies": false, "type": "", "deprecated": false, @@ -20216,7 +20444,7 @@ "x-appwrite": { "method": "deleteBucket", "group": "buckets", - "weight": 210, + "weight": 212, "cookies": false, "type": "", "deprecated": false, @@ -20276,7 +20504,7 @@ "x-appwrite": { "method": "listFiles", "group": "files", - "weight": 212, + "weight": 214, "cookies": false, "type": "", "deprecated": false, @@ -20361,7 +20589,7 @@ "x-appwrite": { "method": "createFile", "group": "files", - "weight": 211, + "weight": 213, "cookies": false, "type": "upload", "deprecated": false, @@ -20453,7 +20681,7 @@ "x-appwrite": { "method": "getFile", "group": "files", - "weight": 213, + "weight": 215, "cookies": false, "type": "", "deprecated": false, @@ -20525,7 +20753,7 @@ "x-appwrite": { "method": "updateFile", "group": "files", - "weight": 218, + "weight": 220, "cookies": false, "type": "", "deprecated": false, @@ -20616,7 +20844,7 @@ "x-appwrite": { "method": "deleteFile", "group": "files", - "weight": 219, + "weight": 221, "cookies": false, "type": "", "deprecated": false, @@ -20688,7 +20916,7 @@ "x-appwrite": { "method": "getFileDownload", "group": "files", - "weight": 215, + "weight": 217, "cookies": false, "type": "location", "deprecated": false, @@ -20769,7 +20997,7 @@ "x-appwrite": { "method": "getFilePreview", "group": "files", - "weight": 214, + "weight": 216, "cookies": false, "type": "location", "deprecated": false, @@ -20935,7 +21163,8 @@ "png", "webp", "heic", - "avif" + "avif", + "gif" ], "x-enum-name": "ImageFormat", "x-enum-keys": [], @@ -20977,7 +21206,7 @@ "x-appwrite": { "method": "getFileView", "group": "files", - "weight": 216, + "weight": 218, "cookies": false, "type": "location", "deprecated": false, @@ -21058,7 +21287,7 @@ "x-appwrite": { "method": "list", "group": "teams", - "weight": 223, + "weight": 225, "cookies": false, "type": "", "deprecated": false, @@ -21135,7 +21364,7 @@ "x-appwrite": { "method": "create", "group": "teams", - "weight": 222, + "weight": 224, "cookies": false, "type": "", "deprecated": false, @@ -21227,7 +21456,7 @@ "x-appwrite": { "method": "get", "group": "teams", - "weight": 224, + "weight": 226, "cookies": false, "type": "", "deprecated": false, @@ -21291,7 +21520,7 @@ "x-appwrite": { "method": "updateName", "group": "teams", - "weight": 226, + "weight": 228, "cookies": false, "type": "", "deprecated": false, @@ -21368,7 +21597,7 @@ "x-appwrite": { "method": "delete", "group": "teams", - "weight": 228, + "weight": 230, "cookies": false, "type": "", "deprecated": false, @@ -21432,7 +21661,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 230, + "weight": 232, "cookies": false, "type": "", "deprecated": false, @@ -21517,7 +21746,7 @@ "x-appwrite": { "method": "createMembership", "group": "memberships", - "weight": 229, + "weight": 231, "cookies": false, "type": "", "deprecated": false, @@ -21632,7 +21861,7 @@ "x-appwrite": { "method": "getMembership", "group": "memberships", - "weight": 231, + "weight": 233, "cookies": false, "type": "", "deprecated": false, @@ -21704,7 +21933,7 @@ "x-appwrite": { "method": "updateMembership", "group": "memberships", - "weight": 232, + "weight": 234, "cookies": false, "type": "", "deprecated": false, @@ -21792,7 +22021,7 @@ "x-appwrite": { "method": "deleteMembership", "group": "memberships", - "weight": 234, + "weight": 236, "cookies": false, "type": "", "deprecated": false, @@ -21866,7 +22095,7 @@ "x-appwrite": { "method": "updateMembershipStatus", "group": "memberships", - "weight": 233, + "weight": 235, "cookies": false, "type": "", "deprecated": false, @@ -21961,7 +22190,7 @@ "x-appwrite": { "method": "getPrefs", "group": "teams", - "weight": 225, + "weight": 227, "cookies": false, "type": "", "deprecated": false, @@ -22023,7 +22252,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "teams", - "weight": 227, + "weight": 229, "cookies": false, "type": "", "deprecated": false, @@ -22103,7 +22332,7 @@ "x-appwrite": { "method": "list", "group": "files", - "weight": 439, + "weight": 441, "cookies": false, "type": "", "deprecated": false, @@ -22184,7 +22413,7 @@ "x-appwrite": { "method": "createFileToken", "group": "files", - "weight": 437, + "weight": 439, "cookies": false, "type": "", "deprecated": false, @@ -22269,7 +22498,7 @@ "x-appwrite": { "method": "get", "group": "tokens", - "weight": 438, + "weight": 440, "cookies": false, "type": "", "deprecated": false, @@ -22330,7 +22559,7 @@ "x-appwrite": { "method": "update", "group": "tokens", - "weight": 440, + "weight": 442, "cookies": false, "type": "", "deprecated": false, @@ -22402,7 +22631,7 @@ "x-appwrite": { "method": "delete", "group": "tokens", - "weight": 441, + "weight": 443, "cookies": false, "type": "", "deprecated": false, @@ -22463,7 +22692,7 @@ "x-appwrite": { "method": "list", "group": "users", - "weight": 245, + "weight": 247, "cookies": false, "type": "", "deprecated": false, @@ -22536,7 +22765,7 @@ "x-appwrite": { "method": "create", "group": "users", - "weight": 236, + "weight": 238, "cookies": false, "type": "", "deprecated": false, @@ -22632,7 +22861,7 @@ "x-appwrite": { "method": "createArgon2User", "group": "users", - "weight": 239, + "weight": 241, "cookies": false, "type": "", "deprecated": false, @@ -22724,7 +22953,7 @@ "x-appwrite": { "method": "createBcryptUser", "group": "users", - "weight": 237, + "weight": 239, "cookies": false, "type": "", "deprecated": false, @@ -22814,7 +23043,7 @@ "x-appwrite": { "method": "listIdentities", "group": "identities", - "weight": 253, + "weight": 255, "cookies": false, "type": "", "deprecated": false, @@ -22884,7 +23113,7 @@ "x-appwrite": { "method": "deleteIdentity", "group": "identities", - "weight": 276, + "weight": 278, "cookies": false, "type": "", "deprecated": false, @@ -22946,7 +23175,7 @@ "x-appwrite": { "method": "createMD5User", "group": "users", - "weight": 238, + "weight": 240, "cookies": false, "type": "", "deprecated": false, @@ -23038,7 +23267,7 @@ "x-appwrite": { "method": "createPHPassUser", "group": "users", - "weight": 241, + "weight": 243, "cookies": false, "type": "", "deprecated": false, @@ -23130,7 +23359,7 @@ "x-appwrite": { "method": "createScryptUser", "group": "users", - "weight": 242, + "weight": 244, "cookies": false, "type": "", "deprecated": false, @@ -23257,7 +23486,7 @@ "x-appwrite": { "method": "createScryptModifiedUser", "group": "users", - "weight": 243, + "weight": 245, "cookies": false, "type": "", "deprecated": false, @@ -23370,7 +23599,7 @@ "x-appwrite": { "method": "createSHAUser", "group": "users", - "weight": 240, + "weight": 242, "cookies": false, "type": "", "deprecated": false, @@ -23481,7 +23710,7 @@ "x-appwrite": { "method": "get", "group": "users", - "weight": 246, + "weight": 248, "cookies": false, "type": "", "deprecated": false, @@ -23536,7 +23765,7 @@ "x-appwrite": { "method": "delete", "group": "users", - "weight": 274, + "weight": 276, "cookies": false, "type": "", "deprecated": false, @@ -23598,7 +23827,7 @@ "x-appwrite": { "method": "updateEmail", "group": "users", - "weight": 259, + "weight": 261, "cookies": false, "type": "", "deprecated": false, @@ -23678,7 +23907,7 @@ "x-appwrite": { "method": "createJWT", "group": "sessions", - "weight": 277, + "weight": 279, "cookies": false, "type": "", "deprecated": false, @@ -23761,7 +23990,7 @@ "x-appwrite": { "method": "updateLabels", "group": "users", - "weight": 255, + "weight": 257, "cookies": false, "type": "", "deprecated": false, @@ -23842,7 +24071,7 @@ "x-appwrite": { "method": "listLogs", "group": "logs", - "weight": 251, + "weight": 253, "cookies": false, "type": "", "deprecated": false, @@ -23914,7 +24143,7 @@ "x-appwrite": { "method": "listMemberships", "group": "memberships", - "weight": 250, + "weight": 252, "cookies": false, "type": "", "deprecated": false, @@ -23997,7 +24226,7 @@ "x-appwrite": { "method": "updateMfa", "group": "users", - "weight": 264, + "weight": 266, "cookies": false, "type": "", "deprecated": false, @@ -24072,7 +24301,7 @@ "x-appwrite": { "method": "deleteMfaAuthenticator", "group": "mfa", - "weight": 269, + "weight": 271, "cookies": false, "type": "", "deprecated": false, @@ -24145,7 +24374,7 @@ "x-appwrite": { "method": "listMfaFactors", "group": "mfa", - "weight": 265, + "weight": 267, "cookies": false, "type": "", "deprecated": false, @@ -24205,7 +24434,7 @@ "x-appwrite": { "method": "getMfaRecoveryCodes", "group": "mfa", - "weight": 266, + "weight": 268, "cookies": false, "type": "", "deprecated": false, @@ -24265,7 +24494,7 @@ "x-appwrite": { "method": "updateMfaRecoveryCodes", "group": "mfa", - "weight": 268, + "weight": 270, "cookies": false, "type": "", "deprecated": false, @@ -24325,7 +24554,7 @@ "x-appwrite": { "method": "createMfaRecoveryCodes", "group": "mfa", - "weight": 267, + "weight": 269, "cookies": false, "type": "", "deprecated": false, @@ -24387,7 +24616,7 @@ "x-appwrite": { "method": "updateName", "group": "users", - "weight": 257, + "weight": 259, "cookies": false, "type": "", "deprecated": false, @@ -24467,7 +24696,7 @@ "x-appwrite": { "method": "updatePassword", "group": "users", - "weight": 258, + "weight": 260, "cookies": false, "type": "", "deprecated": false, @@ -24547,7 +24776,7 @@ "x-appwrite": { "method": "updatePhone", "group": "users", - "weight": 260, + "weight": 262, "cookies": false, "type": "", "deprecated": false, @@ -24625,7 +24854,7 @@ "x-appwrite": { "method": "getPrefs", "group": "users", - "weight": 247, + "weight": 249, "cookies": false, "type": "", "deprecated": false, @@ -24685,7 +24914,7 @@ "x-appwrite": { "method": "updatePrefs", "group": "users", - "weight": 262, + "weight": 264, "cookies": false, "type": "", "deprecated": false, @@ -24763,7 +24992,7 @@ "x-appwrite": { "method": "listSessions", "group": "sessions", - "weight": 249, + "weight": 251, "cookies": false, "type": "", "deprecated": false, @@ -24823,7 +25052,7 @@ "x-appwrite": { "method": "createSession", "group": "sessions", - "weight": 270, + "weight": 272, "cookies": false, "type": "", "deprecated": false, @@ -24878,7 +25107,7 @@ "x-appwrite": { "method": "deleteSessions", "group": "sessions", - "weight": 273, + "weight": 275, "cookies": false, "type": "", "deprecated": false, @@ -24935,7 +25164,7 @@ "x-appwrite": { "method": "deleteSession", "group": "sessions", - "weight": 272, + "weight": 274, "cookies": false, "type": "", "deprecated": false, @@ -25005,7 +25234,7 @@ "x-appwrite": { "method": "updateStatus", "group": "users", - "weight": 254, + "weight": 256, "cookies": false, "type": "", "deprecated": false, @@ -25083,7 +25312,7 @@ "x-appwrite": { "method": "listTargets", "group": "targets", - "weight": 252, + "weight": 254, "cookies": false, "type": "", "deprecated": false, @@ -25120,7 +25349,7 @@ }, { "name": "queries", - "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: name, email, phone, status, passwordUpdate, registration, emailVerification, phoneVerification, labels", + "description": "Array of query strings generated using the Query class provided by the SDK. [Learn more about queries](https:\/\/appwrite.io\/docs\/queries). Maximum of 100 queries are allowed, each 4096 characters long. You may filter on the following attributes: userId, providerId, identifier, providerType", "required": false, "type": "array", "collectionFormat": "multi", @@ -25156,7 +25385,7 @@ "x-appwrite": { "method": "createTarget", "group": "targets", - "weight": 244, + "weight": 246, "cookies": false, "type": "", "deprecated": false, @@ -25268,7 +25497,7 @@ "x-appwrite": { "method": "getTarget", "group": "targets", - "weight": 248, + "weight": 250, "cookies": false, "type": "", "deprecated": false, @@ -25337,7 +25566,7 @@ "x-appwrite": { "method": "updateTarget", "group": "targets", - "weight": 263, + "weight": 265, "cookies": false, "type": "", "deprecated": false, @@ -25428,7 +25657,7 @@ "x-appwrite": { "method": "deleteTarget", "group": "targets", - "weight": 275, + "weight": 277, "cookies": false, "type": "", "deprecated": false, @@ -25499,7 +25728,7 @@ "x-appwrite": { "method": "createToken", "group": "sessions", - "weight": 271, + "weight": 273, "cookies": false, "type": "", "deprecated": false, @@ -25582,7 +25811,7 @@ "x-appwrite": { "method": "updateEmailVerification", "group": "users", - "weight": 261, + "weight": 263, "cookies": false, "type": "", "deprecated": false, @@ -25662,7 +25891,7 @@ "x-appwrite": { "method": "updatePhoneVerification", "group": "users", - "weight": 256, + "weight": 258, "cookies": false, "type": "", "deprecated": false, @@ -26854,6 +27083,12 @@ "description": "Default value for attribute when not provided. Cannot be set when attribute is required.", "x-example": "default", "x-nullable": true + }, + "encrypt": { + "type": "boolean", + "description": "Defines whether this attribute is encrypted or not.", + "x-example": false, + "x-nullable": true } }, "required": [ @@ -27605,6 +27840,12 @@ "description": "Document ID.", "x-example": "5e5ea5c16897e" }, + "$sequence": { + "type": "integer", + "description": "Document automatically incrementing ID.", + "x-example": 1, + "format": "int32" + }, "$collectionId": { "type": "string", "description": "Collection ID.", @@ -27639,6 +27880,7 @@ "additionalProperties": true, "required": [ "$id", + "$sequence", "$collectionId", "$databaseId", "$createdAt", From a82bd62ef6c88e1a8c178a83cc595e467ca40855 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Tue, 10 Jun 2025 14:11:49 -0400 Subject: [PATCH 203/219] Remove bundle --- tests/resources/sites/static/code.tar.gz | Bin 349 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tests/resources/sites/static/code.tar.gz diff --git a/tests/resources/sites/static/code.tar.gz b/tests/resources/sites/static/code.tar.gz deleted file mode 100644 index cdc8981ce694314b641302275ef7604a1287cb90..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 349 zcmV-j0iymNiwFP!000001MSpJPlGTR2XM~&6qU2%WxRQSC1z^8>0ur`R(LX+bcL|G z>9@BXn#>v937y&hcPW%VP<VLod}nZhktNA?H1@~sc9;ZVl*U04*<6-|k;9VVm*zOn zE6qE`oUUo~Pq{<K|0&NGs-hRK)=N3mJ#2x~IR3W&Q8MZ4ADQxJCKrZTkU1<EYC*eB zy#D#w)!l6Vcz@087cd>=c3_gLMd6Zi?F8{^I$}n?B+Xe_^KM1Da3AJ3;|q89km5@! z+_j)h+jQDxWur7H6WxeP*F{BZQPOz3bIybkT5vgDm0VI0dcnt~w9t~Kw<Kl5F57m~ z2~D}*&yI4xUr+wjRIl$R)Zv%3nKIEnWA^N${q>tZPM&Xz#7jNkAK+mB$LU`GPbN`{ v{{Ia}+yArvvt%t_9PIwjS@b>t0000000000000000GymRx5W-U04M+eMiH$^ From d3af2e4735176a7c003a6d5b291ffe796249e809 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Tue, 10 Jun 2025 14:27:19 -0400 Subject: [PATCH 204/219] Add SDK version support --- src/Appwrite/Platform/Tasks/SDKs.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Appwrite/Platform/Tasks/SDKs.php b/src/Appwrite/Platform/Tasks/SDKs.php index a0009fd59f..16a0cc4dda 100644 --- a/src/Appwrite/Platform/Tasks/SDKs.php +++ b/src/Appwrite/Platform/Tasks/SDKs.php @@ -64,7 +64,7 @@ class SDKs extends Action $message ??= Console::confirm('Please enter your commit message:'); } - if (!in_array($version, ['0.6.x', '0.7.x', '0.8.x', '0.9.x', '0.10.x', '0.11.x', '0.12.x', '0.13.x', '0.14.x', '0.15.x', '1.0.x', '1.1.x', '1.2.x', '1.3.x', '1.4.x', '1.5.x', '1.6.x', '1.7.x', 'latest'])) { + if (!\in_array($version, ['0.6.x', '0.7.x', '0.8.x', '0.9.x', '0.10.x', '0.11.x', '0.12.x', '0.13.x', '0.14.x', '0.15.x', '1.0.x', '1.1.x', '1.2.x', '1.3.x', '1.4.x', '1.5.x', '1.6.x', '1.7.x', '1.8.x', 'latest'])) { throw new \Exception('Unknown version given'); } From a77eea6b556433860e01543d9dfe0ea051166662 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Tue, 10 Jun 2025 15:05:26 -0400 Subject: [PATCH 205/219] Fix numeric type values --- app/config/specs/swagger2-1.8.x-console.json | 8 ++++---- app/config/specs/swagger2-1.8.x-server.json | 8 ++++---- app/controllers/api/databases.php | 1 - src/Appwrite/SDK/Specification/Format/Swagger2.php | 2 +- 4 files changed, 9 insertions(+), 10 deletions(-) diff --git a/app/config/specs/swagger2-1.8.x-console.json b/app/config/specs/swagger2-1.8.x-console.json index 333ae6f360..68274d7946 100644 --- a/app/config/specs/swagger2-1.8.x-console.json +++ b/app/config/specs/swagger2-1.8.x-console.json @@ -9084,13 +9084,13 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to decrement the attribute by. The value must be a number.", "default": 1, "x-example": null }, "min": { - "type": "mixed", + "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null @@ -9192,13 +9192,13 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "default": 1, "x-example": null }, "max": { - "type": "mixed", + "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null diff --git a/app/config/specs/swagger2-1.8.x-server.json b/app/config/specs/swagger2-1.8.x-server.json index cdadac68e3..7d1e60c99a 100644 --- a/app/config/specs/swagger2-1.8.x-server.json +++ b/app/config/specs/swagger2-1.8.x-server.json @@ -8484,13 +8484,13 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to decrement the attribute by. The value must be a number.", "default": 1, "x-example": null }, "min": { - "type": "mixed", + "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null @@ -8594,13 +8594,13 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "default": 1, "x-example": null }, "max": { - "type": "mixed", + "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 098361651f..167445ba3b 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -3128,7 +3128,6 @@ App::get('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') $response->dynamic($index, Response::MODEL_INDEX); }); - App::delete('/v1/databases/:databaseId/collections/:collectionId/indexes/:key') ->alias('/v1/database/collections/:collectionId/indexes/:key') ->desc('Delete index') diff --git a/src/Appwrite/SDK/Specification/Format/Swagger2.php b/src/Appwrite/SDK/Specification/Format/Swagger2.php index bac483ffee..4c4016e7e7 100644 --- a/src/Appwrite/SDK/Specification/Format/Swagger2.php +++ b/src/Appwrite/SDK/Specification/Format/Swagger2.php @@ -453,11 +453,11 @@ class Swagger2 extends Format $node['format'] = $validator->getType() == Validator::TYPE_INTEGER ? 'int32' : 'float'; $node['x-example'] = $validator->getMin(); break; - case 'Utopia\Validator\Numeric': case 'Utopia\Validator\Integer': $node['type'] = $validator->getType(); $node['format'] = 'int32'; break; + case 'Utopia\Validator\Numeric': case 'Utopia\Validator\FloatValidator': $node['type'] = 'number'; $node['format'] = 'float'; From d067d215b1fe50de2729c90d7c894a2a76f50bed Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Tue, 10 Jun 2025 15:09:15 -0400 Subject: [PATCH 206/219] Generate latest --- app/config/specs/swagger2-latest-client.json | 8 ++++---- app/config/specs/swagger2-latest-console.json | 8 ++++---- app/config/specs/swagger2-latest-server.json | 8 ++++---- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index d5ff0f609c..24ae416a10 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -5169,13 +5169,13 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to decrement the attribute by. The value must be a number.", "default": 1, "x-example": null }, "min": { - "type": "mixed", + "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null @@ -5277,13 +5277,13 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "default": 1, "x-example": null }, "max": { - "type": "mixed", + "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 333ae6f360..68274d7946 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -9084,13 +9084,13 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to decrement the attribute by. The value must be a number.", "default": 1, "x-example": null }, "min": { - "type": "mixed", + "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null @@ -9192,13 +9192,13 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "default": 1, "x-example": null }, "max": { - "type": "mixed", + "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index cdadac68e3..7d1e60c99a 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -8484,13 +8484,13 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to decrement the attribute by. The value must be a number.", "default": 1, "x-example": null }, "min": { - "type": "mixed", + "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null @@ -8594,13 +8594,13 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "default": 1, "x-example": null }, "max": { - "type": "mixed", + "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null From 5f588b0c652dbfed52a41c12361612e128951d82 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Tue, 10 Jun 2025 15:22:13 -0400 Subject: [PATCH 207/219] Fix open API specs --- app/config/specs/open-api3-1.8.x-client.json | 8 ++++---- app/config/specs/open-api3-1.8.x-console.json | 8 ++++---- app/config/specs/open-api3-1.8.x-server.json | 8 ++++---- app/config/specs/open-api3-latest-client.json | 8 ++++---- app/config/specs/open-api3-latest-console.json | 8 ++++---- app/config/specs/open-api3-latest-server.json | 8 ++++---- app/config/specs/swagger2-1.8.x-client.json | 8 ++++---- src/Appwrite/SDK/Specification/Format/OpenAPI3.php | 2 +- 8 files changed, 29 insertions(+), 29 deletions(-) diff --git a/app/config/specs/open-api3-1.8.x-client.json b/app/config/specs/open-api3-1.8.x-client.json index fd2752e337..033a84f680 100644 --- a/app/config/specs/open-api3-1.8.x-client.json +++ b/app/config/specs/open-api3-1.8.x-client.json @@ -5049,12 +5049,12 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to decrement the attribute by. The value must be a number.", "x-example": null }, "min": { - "type": "mixed", + "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "x-example": null } @@ -5163,12 +5163,12 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "x-example": null }, "max": { - "type": "mixed", + "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "x-example": null } diff --git a/app/config/specs/open-api3-1.8.x-console.json b/app/config/specs/open-api3-1.8.x-console.json index 4372df4eb3..158cb9859a 100644 --- a/app/config/specs/open-api3-1.8.x-console.json +++ b/app/config/specs/open-api3-1.8.x-console.json @@ -8996,12 +8996,12 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to decrement the attribute by. The value must be a number.", "x-example": null }, "min": { - "type": "mixed", + "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "x-example": null } @@ -9110,12 +9110,12 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "x-example": null }, "max": { - "type": "mixed", + "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "x-example": null } diff --git a/app/config/specs/open-api3-1.8.x-server.json b/app/config/specs/open-api3-1.8.x-server.json index 871f5a1e57..05f3e778fc 100644 --- a/app/config/specs/open-api3-1.8.x-server.json +++ b/app/config/specs/open-api3-1.8.x-server.json @@ -8399,12 +8399,12 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to decrement the attribute by. The value must be a number.", "x-example": null }, "min": { - "type": "mixed", + "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "x-example": null } @@ -8515,12 +8515,12 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "x-example": null }, "max": { - "type": "mixed", + "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "x-example": null } diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index fd2752e337..033a84f680 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -5049,12 +5049,12 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to decrement the attribute by. The value must be a number.", "x-example": null }, "min": { - "type": "mixed", + "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "x-example": null } @@ -5163,12 +5163,12 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "x-example": null }, "max": { - "type": "mixed", + "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "x-example": null } diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 4372df4eb3..158cb9859a 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -8996,12 +8996,12 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to decrement the attribute by. The value must be a number.", "x-example": null }, "min": { - "type": "mixed", + "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "x-example": null } @@ -9110,12 +9110,12 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "x-example": null }, "max": { - "type": "mixed", + "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "x-example": null } diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 871f5a1e57..05f3e778fc 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -8399,12 +8399,12 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to decrement the attribute by. The value must be a number.", "x-example": null }, "min": { - "type": "mixed", + "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "x-example": null } @@ -8515,12 +8515,12 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "x-example": null }, "max": { - "type": "mixed", + "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "x-example": null } diff --git a/app/config/specs/swagger2-1.8.x-client.json b/app/config/specs/swagger2-1.8.x-client.json index d5ff0f609c..24ae416a10 100644 --- a/app/config/specs/swagger2-1.8.x-client.json +++ b/app/config/specs/swagger2-1.8.x-client.json @@ -5169,13 +5169,13 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to decrement the attribute by. The value must be a number.", "default": 1, "x-example": null }, "min": { - "type": "mixed", + "type": "number", "description": "Minimum value for the attribute. If the current value is lesser than this value, an exception will be thrown.", "default": null, "x-example": null @@ -5277,13 +5277,13 @@ "type": "object", "properties": { "value": { - "type": "mixed", + "type": "number", "description": "Value to increment the attribute by. The value must be a number.", "default": 1, "x-example": null }, "max": { - "type": "mixed", + "type": "number", "description": "Maximum value for the attribute. If the current value is greater than this value, an error will be thrown.", "default": null, "x-example": null diff --git a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php index 19742ee3ee..b808a27f98 100644 --- a/src/Appwrite/SDK/Specification/Format/OpenAPI3.php +++ b/src/Appwrite/SDK/Specification/Format/OpenAPI3.php @@ -444,11 +444,11 @@ class OpenAPI3 extends Format $node['schema']['format'] = $validator->getType() == Validator::TYPE_INTEGER ? 'int32' : 'float'; $node['schema']['x-example'] = $validator->getMin(); break; - case 'Utopia\Validator\Numeric': case 'Utopia\Validator\Integer': $node['schema']['type'] = $validator->getType(); $node['schema']['format'] = 'int32'; break; + case 'Utopia\Validator\Numeric': case 'Utopia\Validator\FloatValidator': $node['schema']['type'] = 'number'; $node['schema']['format'] = 'float'; From 178dec01fdeadac4c09c88f8385d5fccda719ecf Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Tue, 10 Jun 2025 15:44:40 -0400 Subject: [PATCH 208/219] Add admin key --- app/controllers/api/databases.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 167445ba3b..ef92dffcc7 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -2849,7 +2849,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/indexes') ->param('type', null, new WhiteList([Database::INDEX_KEY, Database::INDEX_FULLTEXT, Database::INDEX_UNIQUE]), 'Index type.') ->param('attributes', null, new ArrayList(new Key(true), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of attributes to index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' attributes are allowed, each 32 characters long.') ->param('orders', [], new ArrayList(new WhiteList(['ASC', 'DESC'], false, Database::VAR_STRING), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Array of index orders. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE . ' orders are allowed.', true) - ->param('lengths', [], new ArrayList(new Nullable(new Integer()), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Length of index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE, optional:true) + ->param('lengths', [], new ArrayList(new Nullable(new Integer()), APP_LIMIT_ARRAY_PARAMS_SIZE), 'Length of index. Maximum of ' . APP_LIMIT_ARRAY_PARAMS_SIZE, optional: true) ->inject('response') ->inject('dbForProject') ->inject('queueForDatabase') @@ -4479,7 +4479,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum group: 'documents', name: 'incrementDocumentAttribute', description: '/docs/references/databases/increment-document-attribute.md', - auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT], + auth: [AuthType::ADMIN, AuthType::KEY, AuthType::SESSION, AuthType::JWT], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -4556,7 +4556,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents/:docum group: 'documents', name: 'decrementDocumentAttribute', description: '/docs/references/databases/decrement-document-attribute.md', - auth: [AuthType::KEY, AuthType::SESSION, AuthType::JWT], + auth: [AuthType::ADMIN, AuthType::KEY, AuthType::SESSION, AuthType::JWT], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, From 963d177b175ad194aadfe6ae8c70b490a04c90d4 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Tue, 10 Jun 2025 15:50:18 -0400 Subject: [PATCH 209/219] Update admin spec --- app/config/specs/open-api3-1.8.x-client.json | 4 ++++ app/config/specs/open-api3-1.8.x-console.json | 8 ++++++++ app/config/specs/open-api3-1.8.x-server.json | 8 ++++++++ app/config/specs/open-api3-latest-client.json | 4 ++++ app/config/specs/open-api3-latest-console.json | 8 ++++++++ app/config/specs/open-api3-latest-server.json | 8 ++++++++ app/config/specs/swagger2-1.8.x-client.json | 4 ++++ app/config/specs/swagger2-1.8.x-console.json | 8 ++++++++ app/config/specs/swagger2-1.8.x-server.json | 8 ++++++++ app/config/specs/swagger2-latest-client.json | 4 ++++ app/config/specs/swagger2-latest-console.json | 8 ++++++++ app/config/specs/swagger2-latest-server.json | 8 ++++++++ app/controllers/api/databases.php | 10 +++++----- 13 files changed, 85 insertions(+), 5 deletions(-) diff --git a/app/config/specs/open-api3-1.8.x-client.json b/app/config/specs/open-api3-1.8.x-client.json index 033a84f680..8f03738786 100644 --- a/app/config/specs/open-api3-1.8.x-client.json +++ b/app/config/specs/open-api3-1.8.x-client.json @@ -4457,6 +4457,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "client", "server", "server" @@ -4466,6 +4467,7 @@ { "name": "createDocument", "auth": { + "Admin": [], "Session": [], "Key": [], "JWT": [] @@ -4985,6 +4987,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" @@ -5099,6 +5102,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" diff --git a/app/config/specs/open-api3-1.8.x-console.json b/app/config/specs/open-api3-1.8.x-console.json index 158cb9859a..85ef1334d4 100644 --- a/app/config/specs/open-api3-1.8.x-console.json +++ b/app/config/specs/open-api3-1.8.x-console.json @@ -8016,6 +8016,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "client", "server", "server" @@ -8025,6 +8026,7 @@ { "name": "createDocument", "auth": { + "Admin": [], "Session": [], "Key": [], "JWT": [] @@ -8053,6 +8055,7 @@ { "name": "createDocuments", "auth": { + "Admin": [], "Key": [] }, "parameters": [ @@ -8178,6 +8181,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -8269,6 +8273,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -8362,6 +8367,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -8932,6 +8938,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" @@ -9046,6 +9053,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" diff --git a/app/config/specs/open-api3-1.8.x-server.json b/app/config/specs/open-api3-1.8.x-server.json index 05f3e778fc..3e9b87fdf1 100644 --- a/app/config/specs/open-api3-1.8.x-server.json +++ b/app/config/specs/open-api3-1.8.x-server.json @@ -7497,6 +7497,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "client", "server", "server" @@ -7506,6 +7507,7 @@ { "name": "createDocument", "auth": { + "Admin": [], "Session": [], "Key": [], "JWT": [] @@ -7534,6 +7536,7 @@ { "name": "createDocuments", "auth": { + "Admin": [], "Key": [] }, "parameters": [ @@ -7661,6 +7664,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -7753,6 +7757,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -7847,6 +7852,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -8333,6 +8339,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" @@ -8449,6 +8456,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" diff --git a/app/config/specs/open-api3-latest-client.json b/app/config/specs/open-api3-latest-client.json index 033a84f680..8f03738786 100644 --- a/app/config/specs/open-api3-latest-client.json +++ b/app/config/specs/open-api3-latest-client.json @@ -4457,6 +4457,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "client", "server", "server" @@ -4466,6 +4467,7 @@ { "name": "createDocument", "auth": { + "Admin": [], "Session": [], "Key": [], "JWT": [] @@ -4985,6 +4987,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" @@ -5099,6 +5102,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" diff --git a/app/config/specs/open-api3-latest-console.json b/app/config/specs/open-api3-latest-console.json index 158cb9859a..85ef1334d4 100644 --- a/app/config/specs/open-api3-latest-console.json +++ b/app/config/specs/open-api3-latest-console.json @@ -8016,6 +8016,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "client", "server", "server" @@ -8025,6 +8026,7 @@ { "name": "createDocument", "auth": { + "Admin": [], "Session": [], "Key": [], "JWT": [] @@ -8053,6 +8055,7 @@ { "name": "createDocuments", "auth": { + "Admin": [], "Key": [] }, "parameters": [ @@ -8178,6 +8181,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -8269,6 +8273,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -8362,6 +8367,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -8932,6 +8938,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" @@ -9046,6 +9053,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" diff --git a/app/config/specs/open-api3-latest-server.json b/app/config/specs/open-api3-latest-server.json index 05f3e778fc..3e9b87fdf1 100644 --- a/app/config/specs/open-api3-latest-server.json +++ b/app/config/specs/open-api3-latest-server.json @@ -7497,6 +7497,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "client", "server", "server" @@ -7506,6 +7507,7 @@ { "name": "createDocument", "auth": { + "Admin": [], "Session": [], "Key": [], "JWT": [] @@ -7534,6 +7536,7 @@ { "name": "createDocuments", "auth": { + "Admin": [], "Key": [] }, "parameters": [ @@ -7661,6 +7664,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -7753,6 +7757,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -7847,6 +7852,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -8333,6 +8339,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" @@ -8449,6 +8456,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" diff --git a/app/config/specs/swagger2-1.8.x-client.json b/app/config/specs/swagger2-1.8.x-client.json index 24ae416a10..33fe1a93c9 100644 --- a/app/config/specs/swagger2-1.8.x-client.json +++ b/app/config/specs/swagger2-1.8.x-client.json @@ -4603,6 +4603,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "client", "server", "server" @@ -4612,6 +4613,7 @@ { "name": "createDocument", "auth": { + "Admin": [], "Session": [], "Key": [], "JWT": [] @@ -5114,6 +5116,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" @@ -5222,6 +5225,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" diff --git a/app/config/specs/swagger2-1.8.x-console.json b/app/config/specs/swagger2-1.8.x-console.json index 68274d7946..a11fd21b42 100644 --- a/app/config/specs/swagger2-1.8.x-console.json +++ b/app/config/specs/swagger2-1.8.x-console.json @@ -8145,6 +8145,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "client", "server", "server" @@ -8154,6 +8155,7 @@ { "name": "createDocument", "auth": { + "Admin": [], "Session": [], "Key": [], "JWT": [] @@ -8182,6 +8184,7 @@ { "name": "createDocuments", "auth": { + "Admin": [], "Key": [] }, "parameters": [ @@ -8307,6 +8310,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -8395,6 +8399,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -8486,6 +8491,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -9029,6 +9035,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" @@ -9137,6 +9144,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" diff --git a/app/config/specs/swagger2-1.8.x-server.json b/app/config/specs/swagger2-1.8.x-server.json index 7d1e60c99a..7c15f9e5ea 100644 --- a/app/config/specs/swagger2-1.8.x-server.json +++ b/app/config/specs/swagger2-1.8.x-server.json @@ -7616,6 +7616,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "client", "server", "server" @@ -7625,6 +7626,7 @@ { "name": "createDocument", "auth": { + "Admin": [], "Session": [], "Key": [], "JWT": [] @@ -7653,6 +7655,7 @@ { "name": "createDocuments", "auth": { + "Admin": [], "Key": [] }, "parameters": [ @@ -7780,6 +7783,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -7869,6 +7873,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -7961,6 +7966,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -8427,6 +8433,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" @@ -8537,6 +8544,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" diff --git a/app/config/specs/swagger2-latest-client.json b/app/config/specs/swagger2-latest-client.json index 24ae416a10..33fe1a93c9 100644 --- a/app/config/specs/swagger2-latest-client.json +++ b/app/config/specs/swagger2-latest-client.json @@ -4603,6 +4603,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "client", "server", "server" @@ -4612,6 +4613,7 @@ { "name": "createDocument", "auth": { + "Admin": [], "Session": [], "Key": [], "JWT": [] @@ -5114,6 +5116,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" @@ -5222,6 +5225,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" diff --git a/app/config/specs/swagger2-latest-console.json b/app/config/specs/swagger2-latest-console.json index 68274d7946..a11fd21b42 100644 --- a/app/config/specs/swagger2-latest-console.json +++ b/app/config/specs/swagger2-latest-console.json @@ -8145,6 +8145,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "client", "server", "server" @@ -8154,6 +8155,7 @@ { "name": "createDocument", "auth": { + "Admin": [], "Session": [], "Key": [], "JWT": [] @@ -8182,6 +8184,7 @@ { "name": "createDocuments", "auth": { + "Admin": [], "Key": [] }, "parameters": [ @@ -8307,6 +8310,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -8395,6 +8399,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -8486,6 +8491,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -9029,6 +9035,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" @@ -9137,6 +9144,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" diff --git a/app/config/specs/swagger2-latest-server.json b/app/config/specs/swagger2-latest-server.json index 7d1e60c99a..7c15f9e5ea 100644 --- a/app/config/specs/swagger2-latest-server.json +++ b/app/config/specs/swagger2-latest-server.json @@ -7616,6 +7616,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "client", "server", "server" @@ -7625,6 +7626,7 @@ { "name": "createDocument", "auth": { + "Admin": [], "Session": [], "Key": [], "JWT": [] @@ -7653,6 +7655,7 @@ { "name": "createDocuments", "auth": { + "Admin": [], "Key": [] }, "parameters": [ @@ -7780,6 +7783,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -7869,6 +7873,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -7961,6 +7966,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server" ], "packaging": false, @@ -8427,6 +8433,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" @@ -8537,6 +8544,7 @@ "rate-key": "ip:{ip},method:{method},url:{url},userId:{userId}", "scope": "documents.write", "platforms": [ + "console", "server", "client", "server" diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index ef92dffcc7..22fa6eba58 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -3221,7 +3221,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') group: 'documents', name: 'createDocument', description: '/docs/references/databases/create-document.md', - auth: [AuthType::SESSION, AuthType::KEY, AuthType::JWT], + auth: [AuthType::ADMIN, AuthType::SESSION, AuthType::KEY, AuthType::JWT], responses: [ new SDKResponse( code: Response::STATUS_CODE_CREATED, @@ -3242,7 +3242,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/documents') group: 'documents', name: 'createDocuments', description: '/docs/references/databases/create-documents.md', - auth: [AuthType::KEY], + auth: [AuthType::ADMIN, AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_CREATED, @@ -4632,7 +4632,7 @@ App::patch('/v1/databases/:databaseId/collections/:collectionId/documents') group: 'documents', name: 'updateDocuments', description: '/docs/references/databases/update-documents.md', - auth: [AuthType::KEY], + auth: [AuthType::ADMIN, AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -4742,7 +4742,7 @@ App::put('/v1/databases/:databaseId/collections/:collectionId/documents') group: 'documents', name: 'upsertDocuments', description: '/docs/references/databases/upsert-documents.md', - auth: [AuthType::KEY], + auth: [AuthType::ADMIN, AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, @@ -4961,7 +4961,7 @@ App::delete('/v1/databases/:databaseId/collections/:collectionId/documents') group: 'documents', name: 'deleteDocuments', description: '/docs/references/databases/delete-documents.md', - auth: [AuthType::KEY], + auth: [AuthType::ADMIN, AuthType::KEY], responses: [ new SDKResponse( code: Response::STATUS_CODE_OK, From 082309697c07ac1945dc514a57126afa44eb7c2c Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Tue, 10 Jun 2025 15:55:54 -0400 Subject: [PATCH 210/219] Fix DB delete cache purge --- app/controllers/api/databases.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 22fa6eba58..1cd7cd0ebd 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -841,7 +841,7 @@ App::delete('/v1/databases/:databaseId') } $dbForProject->purgeCachedDocument('databases', $database->getId()); - $dbForProject->purgeCachedCollection('databases_' . $database->getSequence()); + $dbForProject->purgeCachedCollection('database_' . $database->getSequence()); $queueForDatabase ->setType(DATABASE_TYPE_DELETE_DATABASE) From 077c80ca2675abc154a862485f8e7c23aed0e3ad Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Tue, 10 Jun 2025 19:57:41 -0400 Subject: [PATCH 211/219] Fix exclude --- .github/workflows/tests.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 6fd4e89858..97f3696e67 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -198,7 +198,7 @@ jobs: docker compose exec -T \ -e _APP_DATABASE_SHARED_TABLES \ -e _APP_DATABASE_SHARED_TABLES_V1 \ - appwrite test /usr/src/code/tests/e2e/Services/${{ matrix.service }} --debug --exclude=devKeys + appwrite test /usr/src/code/tests/e2e/Services/${{ matrix.service }} --debug --exclude-group devKeys e2e_shared_mode_test: name: E2E Shared Mode Service Test @@ -277,7 +277,7 @@ jobs: docker compose exec -T \ -e _APP_DATABASE_SHARED_TABLES \ -e _APP_DATABASE_SHARED_TABLES_V1 \ - appwrite test /usr/src/code/tests/e2e/Services/${{ matrix.service }} --debug --exclude=devKeys + appwrite test /usr/src/code/tests/e2e/Services/${{ matrix.service }} --debug --exclude-group devKeys e2e_dev_keys: name: E2E Service Test (Dev Keys) From 851894947fbd60fa209498c5f8ed25f27d4aed5e Mon Sep 17 00:00:00 2001 From: Chirag Aggarwal <chiragaggarwal5k@gmail.com> Date: Wed, 11 Jun 2025 03:55:11 +0000 Subject: [PATCH 212/219] chore: restore unique filename for health check #9842 --- app/controllers/api/health.php | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/app/controllers/api/health.php b/app/controllers/api/health.php index b95eb432a1..2bdaea3c2c 100644 --- a/app/controllers/api/health.php +++ b/app/controllers/api/health.php @@ -845,15 +845,18 @@ App::get('/v1/health/storage') $checkStart = \microtime(true); foreach ($devices as $device) { - if (!$device->write($device->getPath('health.txt'), 'test', 'text/plain')) { + $uniqueFileName = \uniqid('health', true); + $filePath = $device->getPath($uniqueFileName); + + if (!$device->write($filePath, 'test', 'text/plain')) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed writing test file to ' . $device->getRoot()); } - if ($device->read($device->getPath('health.txt')) !== 'test') { + if ($device->read($filePath) !== 'test') { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed reading test file from ' . $device->getRoot()); } - if (!$device->delete($device->getPath('health.txt'))) { + if (!$device->delete($filePath)) { throw new Exception(Exception::GENERAL_SERVER_ERROR, 'Failed deleting test file from ' . $device->getRoot()); } } From b4b28a9cf41b943b0da940bf8a4750b753fea333 Mon Sep 17 00:00:00 2001 From: Christy Jacob <christyjacob4@gmail.com> Date: Wed, 11 Jun 2025 18:36:51 +0400 Subject: [PATCH 213/219] fix: project iteration loop --- src/Appwrite/Platform/Tasks/Maintenance.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Appwrite/Platform/Tasks/Maintenance.php b/src/Appwrite/Platform/Tasks/Maintenance.php index 47f9262006..ddc8c3cb6f 100644 --- a/src/Appwrite/Platform/Tasks/Maintenance.php +++ b/src/Appwrite/Platform/Tasks/Maintenance.php @@ -64,9 +64,9 @@ class Maintenance extends Action Console::info("[{$time}] Notifying workers with maintenance tasks every {$interval} seconds"); - // Iterate through project only if it was accessed in last 24 hours - $dateInterval = DateInterval::createFromDateString('24 hours'); - $before24h = (new DateTime())->sub($dateInterval); + // Iterate through project only if it was accessed in last 30 days + $dateInterval = DateInterval::createFromDateString('30 days'); + $before30days = (new DateTime())->sub($dateInterval); $dbForPlatform->foreach( 'projects', @@ -80,7 +80,7 @@ class Maintenance extends Action [ Query::equal('region', [System::getEnv('_APP_REGION', 'default')]), Query::limit(100), - Query::greaterThanEqual('accessedAt', DatabaseDateTime::format($before24h)), + Query::greaterThanEqual('accessedAt', DatabaseDateTime::format($before30days)), Query::orderAsc('teamInternalId'), ] ); From 0c8ae4f34f3d6755c766dd66efb857137198ece0 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Fri, 6 Jun 2025 12:31:06 +0100 Subject: [PATCH 214/219] feat(builds): after build hook --- .../Modules/Functions/Workers/Builds.php | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php index de5543c9f3..399a4d5c44 100644 --- a/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php +++ b/src/Appwrite/Platform/Modules/Functions/Workers/Builds.php @@ -877,6 +877,10 @@ class Builds extends Action } } + $deployment->setAttribute('buildLogs', $logs); + + $this->afterBuildSuccess($dbForProject, $deployment); + $deployment = $dbForProject->updateDocument('deployments', $deployment->getId(), $deployment); $queueForRealtime @@ -1313,6 +1317,19 @@ class Builds extends Action ->trigger(); } + /** + * Hook to run after build success + * + * @param Database $dbForProject + * @param Document $deployment + * @return void + */ + protected function afterBuildSuccess(Database $dbForProject, Document &$deployment): void + { + assert($dbForProject instanceof Database); + assert($deployment instanceof Document); + } + protected function getRuntime(Document $resource, string $version): array { $runtimes = Config::getParam($version === 'v2' ? 'runtimes-v2' : 'runtimes', []); From 84f4a5dba0420d1e150705efa7cffd4f79a17845 Mon Sep 17 00:00:00 2001 From: ArnabChatterjee20k <arnabchatterjee.ac.2@gmail.com> Date: Wed, 11 Jun 2025 22:11:43 +0530 Subject: [PATCH 215/219] added logging of errors instead of throwing --- src/Appwrite/Platform/Workers/Migrations.php | 27 ++++++++++---------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/Appwrite/Platform/Workers/Migrations.php b/src/Appwrite/Platform/Workers/Migrations.php index 395ec1351e..f8e302089e 100644 --- a/src/Appwrite/Platform/Workers/Migrations.php +++ b/src/Appwrite/Platform/Workers/Migrations.php @@ -279,20 +279,21 @@ class Migrations extends Action ); /** Start Transfer */ - $migration->setAttribute('stage', 'migrating'); - $this->updateMigrationDocument($migration, $projectDocument, $queueForRealtime); - - $transfer->run( - $migration->getAttribute('resources'), - function () use ($migration, $transfer, $projectDocument, $queueForRealtime) { - $migration->setAttribute('resourceData', json_encode($transfer->getCache())); - $migration->setAttribute('statusCounters', json_encode($transfer->getStatusCounters())); - $this->updateMigrationDocument($migration, $projectDocument, $queueForRealtime); - }, - $migration->getAttribute('resourceId'), - $migration->getAttribute('resourceType') - ); + if (empty($source->getErrors())) { + $migration->setAttribute('stage', 'migrating'); + $this->updateMigrationDocument($migration, $projectDocument, $queueForRealtime); + $transfer->run( + $migration->getAttribute('resources'), + function () use ($migration, $transfer, $projectDocument, $queueForRealtime) { + $migration->setAttribute('resourceData', json_encode($transfer->getCache())); + $migration->setAttribute('statusCounters', json_encode($transfer->getStatusCounters())); + $this->updateMigrationDocument($migration, $projectDocument, $queueForRealtime); + }, + $migration->getAttribute('resourceId'), + $migration->getAttribute('resourceType') + ); + } $destination->shutDown(); $source->shutDown(); From 517870dd4561f66f67b08348a235c51a4ab68a35 Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Wed, 11 Jun 2025 20:41:02 -0400 Subject: [PATCH 216/219] Test timing --- tests/e2e/Services/Databases/DatabasesBase.php | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/tests/e2e/Services/Databases/DatabasesBase.php b/tests/e2e/Services/Databases/DatabasesBase.php index 54502c44f9..e34691839d 100644 --- a/tests/e2e/Services/Databases/DatabasesBase.php +++ b/tests/e2e/Services/Databases/DatabasesBase.php @@ -5339,14 +5339,14 @@ trait DatabasesBase 'required' => true, ]); - \sleep(2); + \sleep(3); // Create document with initial count = 5 $doc = $this->client->call(Client::METHOD_POST, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents', array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders()), [ - 'documentId' => 'counter1', + 'documentId' => ID::unique(), 'data' => [ 'count' => 5 ], @@ -5357,8 +5357,10 @@ trait DatabasesBase ]); $this->assertEquals(201, $doc['headers']['status-code']); + $docId = $doc['body']['$id']; + // Increment by default 1 - $inc = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/counter1/count/increment', array_merge([ + $inc = $this->client->call(Client::METHOD_PATCH, "/databases/$databaseId/collections/$collectionId/documents/$docId/count/increment", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ])); @@ -5366,14 +5368,14 @@ trait DatabasesBase $this->assertEquals(6, $inc['body']['count']); // Verify count = 6 - $get = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/counter1', array_merge([ + $get = $this->client->call(Client::METHOD_GET, "/databases/$databaseId/collections/$collectionId/documents/$docId", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(6, $get['body']['count']); // Increment by custom value 4 - $inc2 = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/counter1/count/increment', array_merge([ + $inc2 = $this->client->call(Client::METHOD_PATCH, "/databases/$databaseId/collections/$collectionId/documents/$docId/count/increment", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]), [ @@ -5382,21 +5384,21 @@ trait DatabasesBase $this->assertEquals(200, $inc2['headers']['status-code']); $this->assertEquals(10, $inc2['body']['count']); - $get2 = $this->client->call(Client::METHOD_GET, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/counter1', array_merge([ + $get2 = $this->client->call(Client::METHOD_GET, "/databases/$databaseId/collections/$collectionId/documents/$docId", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ], $this->getHeaders())); $this->assertEquals(10, $get2['body']['count']); // Test max limit exceeded - $err = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/counter1/count/increment', array_merge([ + $err = $this->client->call(Client::METHOD_PATCH, "/databases/$databaseId/collections/$collectionId/documents/$docId/count/increment", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ]), ['max' => 8]); $this->assertEquals(400, $err['headers']['status-code']); // Test attribute not found - $notFound = $this->client->call(Client::METHOD_PATCH, '/databases/' . $databaseId . '/collections/' . $collectionId . '/documents/counter1/unknown/increment', array_merge([ + $notFound = $this->client->call(Client::METHOD_PATCH, "/databases/$databaseId/collections/$collectionId/documents/$docId/unknown/increment", array_merge([ 'content-type' => 'application/json', 'x-appwrite-project' => $this->getProject()['$id'], ])); From 3d9e22a6df84868bdc0be87cd65f26e75e6b462e Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 12 Jun 2025 14:18:05 +0100 Subject: [PATCH 217/219] chore: remove endpoint selector for edge --- src/Executor/Executor.php | 34 +++++++++------------------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index 5b204c1910..c30df4852b 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -21,19 +21,12 @@ class Executor private bool $selfSigned = false; - /** - * @var callable(string, string): string $endpoint - */ - private $endpointSelector; - + private string $endpoint; protected array $headers; - /** - * @param callable(string, string): string $endpointSelector - */ - public function __construct(callable $endpointSelector) + public function __construct() { - $this->endpointSelector = $endpointSelector; + $this->endpoint = System::getEnv('_APP_EXECUTOR_HOST', ''); $this->headers = [ 'content-type' => 'application/json', 'authorization' => 'Bearer ' . System::getEnv('_APP_EXECUTOR_SECRET', ''), @@ -97,8 +90,8 @@ class Executor 'outputDirectory' => $outputDirectory ]; - $endpoint = $this->selectEndpoint($projectId, $deploymentId); - $response = $this->call($endpoint, self::METHOD_POST, $route, [ 'x-opr-runtime-id' => $runtimeId ], $params, true, $timeout); + + $response = $this->call($this->endpoint, self::METHOD_POST, $route, [ 'x-opr-runtime-id' => $runtimeId ], $params, true, $timeout); $status = $response['headers']['status-code']; if ($status >= 400) { @@ -128,8 +121,7 @@ class Executor 'timeout' => $timeout ]; - $endpoint = $this->selectEndpoint($projectId, $deploymentId); - $this->call($endpoint, self::METHOD_GET, $route, [ 'x-opr-runtime-id' => $runtimeId ], $params, true, $timeout, $callback); + $this->call($this->endpoint, self::METHOD_GET, $route, [ 'x-opr-runtime-id' => $runtimeId ], $params, true, $timeout, $callback); } /** @@ -145,8 +137,7 @@ class Executor $runtimeId = "$projectId-$deploymentId" . $suffix; $route = "/runtimes/$runtimeId"; - $endpoint = $this->selectEndpoint($projectId, $deploymentId); - $response = $this->call($endpoint, self::METHOD_DELETE, $route, [ + $response = $this->call($this->endpoint, self::METHOD_DELETE, $route, [ 'x-opr-addressing-method' => 'broadcast' ], [], true, 30); @@ -239,8 +230,7 @@ class Executor $requestTimeout = $timeout + 15; } - $endpoint = $this->selectEndpoint($projectId, $deploymentId); - $response = $this->call($endpoint, self::METHOD_POST, $route, [ 'x-opr-runtime-id' => $runtimeId, 'content-type' => 'multipart/form-data', 'accept' => 'multipart/form-data' ], $params, true, $requestTimeout); + $response = $this->call($this->endpoint, self::METHOD_POST, $route, [ 'x-opr-runtime-id' => $runtimeId, 'content-type' => 'multipart/form-data', 'accept' => 'multipart/form-data' ], $params, true, $requestTimeout); $status = $response['headers']['status-code']; if ($status >= 400) { @@ -274,8 +264,7 @@ class Executor 'timeout' => $timeout ]; - $endpoint = $this->selectEndpoint($projectId, $deploymentId); - $response = $this->call($endpoint, self::METHOD_POST, $route, [ 'x-opr-runtime-id' => $runtimeId ], $params, true, $timeout); + $response = $this->call($this->endpoint, self::METHOD_POST, $route, [ 'x-opr-runtime-id' => $runtimeId ], $params, true, $timeout); $status = $response['headers']['status-code']; if ($status >= 400) { @@ -465,9 +454,4 @@ class Executor return $output; } - - private function selectEndpoint(string $projectId, string $deploymentId): string - { - return call_user_func($this->endpointSelector, $projectId, $deploymentId); - } } From bc41838c66aa37ed9d65e9966c8ef93c3ae644a7 Mon Sep 17 00:00:00 2001 From: loks0n <22452787+loks0n@users.noreply.github.com> Date: Thu, 12 Jun 2025 14:18:35 +0100 Subject: [PATCH 218/219] chore: remove endpoint selector --- app/cli.php | 2 +- app/init/resources.php | 2 +- app/worker.php | 2 +- src/Executor/Executor.php | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/cli.php b/app/cli.php index 7c2daf4500..119534a8b9 100644 --- a/app/cli.php +++ b/app/cli.php @@ -251,7 +251,7 @@ CLI::setResource('logError', function (Registry $register) { }; }, ['register']); -CLI::setResource('executor', fn () => new Executor(fn (string $projectId, string $deploymentId) => System::getEnv('_APP_EXECUTOR_HOST'))); +CLI::setResource('executor', fn () => new Executor()); CLI::setResource('telemetry', fn () => new NoTelemetry()); diff --git a/app/init/resources.php b/app/init/resources.php index 6ca0522b6c..39bdd66a86 100644 --- a/app/init/resources.php +++ b/app/init/resources.php @@ -880,7 +880,7 @@ App::setResource('apiKey', function (Request $request, Document $project): ?Key return Key::decode($project, $key); }, ['request', 'project']); -App::setResource('executor', fn () => new Executor(fn (string $projectId, string $deploymentId) => System::getEnv('_APP_EXECUTOR_HOST'))); +App::setResource('executor', fn () => new Executor()); App::setResource('resourceToken', function ($project, $dbForProject, $request) { $tokenJWT = $request->getParam('token'); diff --git a/app/worker.php b/app/worker.php index c25608cd5e..b596e8bd1b 100644 --- a/app/worker.php +++ b/app/worker.php @@ -402,7 +402,7 @@ Server::setResource('logError', function (Registry $register, Document $project) }; }, ['register', 'project']); -Server::setResource('executor', fn () => new Executor(fn (string $projectId, string $deploymentId) => System::getEnv('_APP_EXECUTOR_HOST'))); +Server::setResource('executor', fn () => new Executor()); $pools = $register->get('pools'); $platform = new Appwrite(); diff --git a/src/Executor/Executor.php b/src/Executor/Executor.php index c30df4852b..15411f18ab 100644 --- a/src/Executor/Executor.php +++ b/src/Executor/Executor.php @@ -19,9 +19,9 @@ class Executor public const METHOD_CONNECT = 'CONNECT'; public const METHOD_TRACE = 'TRACE'; - private bool $selfSigned = false; + protected bool $selfSigned = false; - private string $endpoint; + protected string $endpoint; protected array $headers; public function __construct() From cf830affc9a5076b3f808ef65dd64191a66e050e Mon Sep 17 00:00:00 2001 From: Jake Barnby <jakeb994@gmail.com> Date: Thu, 12 Jun 2025 12:20:21 -0400 Subject: [PATCH 219/219] Check not development for plan error --- app/controllers/api/databases.php | 2 +- tests/e2e/Services/Databases/DatabasesCustomServerTest.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/app/controllers/api/databases.php b/app/controllers/api/databases.php index 1cd7cd0ebd..0e85171772 100644 --- a/app/controllers/api/databases.php +++ b/app/controllers/api/databases.php @@ -1351,7 +1351,7 @@ App::post('/v1/databases/:databaseId/collections/:collectionId/attributes/string ->inject('queueForEvents') ->inject('plan') ->action(function (string $databaseId, string $collectionId, string $key, ?int $size, ?bool $required, ?string $default, bool $array, bool $encrypt, Response $response, Database $dbForProject, EventDatabase $queueForDatabase, Event $queueForEvents, array $plan) { - if ($encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) { + if (!App::isDevelopment() && $encrypt && !empty($plan) && !($plan['databasesAllowEncrypt'] ?? false)) { throw new Exception(Exception::GENERAL_BAD_REQUEST, 'Encrypted string attributes are not available on your plan. Please upgrade to create encrypted string attributes.'); } if ($encrypt && $size < APP_DATABASE_ENCRYPT_SIZE_MIN) { diff --git a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php index 993624a1fe..e84c760c86 100644 --- a/tests/e2e/Services/Databases/DatabasesCustomServerTest.php +++ b/tests/e2e/Services/Databases/DatabasesCustomServerTest.php @@ -641,7 +641,6 @@ class DatabasesCustomServerTest extends Scope /** * @depends testListCollections - * @group cl-ignore */ public function testCreateEncryptedAttribute(array $data): void {